Mercurial > hg > aim92
view model/gen.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line source
/* Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 =========================================================================== Permission to use, copy, modify, and distribute this software without fee is hereby granted for research purposes, provided that this copyright notice appears in all copies and in all supporting documentation, and that the software is not redistributed for any fee (except for a nominal shipping charge). Anyone wanting to incorporate all or part of this software in a commercial product must obtain a license from the Medical Research Council. The MRC makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ /* gen.c ===== APU, ASP model demonstration program. Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit. Authors : John Holdsworth (1989), Mike Allerhand (1990) Edited : M.Akeroyd 22-1-1993 Removed the conditional of `if (centering) Clear (w)' (in plot_frame), so that Clear may be called for PostScriptWindows that AREN'T centered, so allowing showpages to be generated. See also edit to ps.c : M Akeroyd 3-8-1993 Added new options: erbscale_efb (InputOption) mono_ctn (SilentOption) colour_ctn (SilentOption) planemask_ctn (SilentOption) Allowed "bitmap=stdout". : MAA 3rd August 1993 Extra options framenumber (SilentOption), review (SilentOption) : MAA 22nd July 1994. Extra postscript options ALl silent xstart_ps xend_ps ystart_ps yend_ps xtitle_ps ytitle_ps Extra X options fg_col bg_col : MAA Summer 1984. Lots of postscript options. All silent portraitstr, landscapestr; fontnamestr, fontsizestr; xmajorticksstr, xminorticksstr, ymajorticksstr, yminorticksstr; axistop, axisbottom, axisleft, axisright; : AJD Spring 1995. Added a new argument 'nwid' to the function SourceDraw, so that genspl can have the necessary information. : AJD May, 1995. Made options overlap, headroom, perspective, bytemax and type silent. */ #ifndef lint static char *sccs_id = "@(#)gen.c 1.66 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 6/6/91" ; #endif /**************************************************************************** * This module contains: * Display option parameter strings. * Model option parameter strings. * File-format strings. * X windows interface, (included from windows.h). * Options handler routines, (included from options.h). * Option defaults, (application specific). * Strings for generic option types, (OnOption etc). * Display options table, (displayopts[]). * Model option tables, (included from table.c). * Model entry-point functions, (included from model.c). * Display drawing routines, (included from draw.h and fill.h). * Options table construction, (constructOptions(), and mapOptions()). * Main. ****************************************************************************/ #include <string.h> #include <ctype.h> #include <stdio.h> #include <math.h> #if defined(THINK_C) || defined(NeXT) #include <stdlib.h> #endif /********************* Display option parameter strings ********************* * The strings defined here are pointers referenced by the "value" field in * the display options table, displayopts. They are assigned to space which * initially contains defaults in the "defaultValue" field of the display * options table. ****************************************************************************/ static char *bmaxstr, *topstr, *botstr, *overstr ; static char *headstr, *downcstr, *heightstr, *helpstr ; static char *invertstr, *lengthstr, *linstr, *outstr ; static char *reusestr, *startstr, *envstr, *typestr ; #ifdef X11 static char *dispstr, *erasestr, *hiddenstr, *bitmapstr ; static char *kludgestr, *magstr, *penstr, *psfilestr ; static char *psstr, *animstr, *titlestr, *viewstr ; static char *widthstr, *xstr, *ystr ; /* All these MAA. */ char *monostr, *colourstr, *planemaskstr, *rotateaxesstr; char *fgcolourstr, *bgcolourstr; char *xstartstr, *ystartstr, *xendstr, *yendstr; char *xnewtitlestr, *ynewtitlestr; char *portraitstr, *landscapestr; char *fontnamestr, *fontsizestr, *titlesizestr; char *xticksstr, *yticksstr, *outsidestr; char *axistopstr, *axisbottomstr, *axisleftstr, *axisrightstr; char *xmajorticksstr, *xminorticksstr, *ymajorticksstr, *yminorticksstr; char *axislinewidthstr, *figurelinewidthstr; char *boxstr; #endif /* X11 */ char *framenumberstr, *reviewstr; /* MAA: 3-8-1993 */ static char *test1str, *test2str, *test3str, *test4str ; char headerstr[64] ; char *filestr ; /* application display parameters */ #ifdef X11 static char *tiltstr = "0." ; static char *diststr = "0.5" ; static char *roomstr = "0%" ; #endif /* X11 */ /*************** Included from glib (graphics library) directory ***********/ #include "options.h" #include "defaults.h" #ifdef X11 #include "windows.h" #endif /* X11 */ /******************* Strings for generic option values ********************** * Generic option values, (ON_OPTION etc), are defined in options.h. * Convenience routines used to test or convert option values are: * OptionStringsEqual( str1, str2 ) -(defined in options.c). * isON( str ) -(defined in options.h). * isOFF( str ) -(defined in options.c). * isNULL( str ) -(defined in options.c). * OptionInt( str ) -(defined in model.c). * OptionDouble( str ) -(defined in model.c). * Samples( str ) -(defined in model.c). * Cycles( str, cfreq ) -(defined in model.c). * Scalar( str ) -(defined in model.c). * Freq( str ) -(defined in model.c). * ****************************************************************************/ static char helpstring[200] = "no help initially" ; static char OnOption[] = ON_OPTION ; /* "on" */ static char OffOption[] = OFF_OPTION ; /* "off" */ static char NullOption[] = NULL_OPTION ; /* "none" */ static char CenterStr[] = "center" ; static char LengthStr[] = "remainder" ; static char LandStr[] = "landscape" ; static int isEXCITE( str ) char *str ; { return ( strncmp( str, "excitation", strlen( str ) ) == 0 ) ; } static int isWATERFALL( str ) char *str ; { return ( strncmp( str, "waterfall", strlen( str ) ) == 0 ) ; } static int isGREYSCALE( str ) char *str ; { return ( strncmp( str, "greyscale", strlen( str ) ) == 0 || strncmp( str, "grayscale", strlen( str ) ) == 0 ) ; } /************************* Options table *********************************** * The complete options table is built by constructOptions() according to the * application. It is composed of the display options, (displayopts[], below), * and the model option tables (from table.c) which are appropriate for the * application. The sequence of processing stages, (and hence model option * tables), for an application is determined by FindStage() in model.c. * * The complete options table is an array of Option structs. * The Option struct is defined in options.h as: * * typedef struct { * char *name ; The name of the option. * char *defaultValue ; Default value. * char **value ; Address of current value. * char *comment ; Something to print when the user types "-help". * short classification ; Type of option it is. * } Option; * * The classification of options uses names defined in options.h: * InputOption * OutputOption * InOutOption * SilentOption * * Routines which access the option table: * Note: Some routines are called to supply arguments to other routines. * Routines which access the option table in some way are denoted (*). * Most of these routines are defined in options.c. * * main() * | * +-----------------+-----------+----+-------+-----------------+ * | | | | | * | | | ModeledSource() | * | | | | | * | | | checkForFile() | * helpopts() | | | | * | | +---+---+ | * | | | | * | getopts() readopts() writeopts() * | | | | * | getnopts(*) readnopts() writenopts(*) * | [arg countOptions(*)] [arg countOptions(*)] [arg countOptions(*)] * | | | | * | +-------+------+ | countBytesToWrite(*) * | | | | | * | | | +------+------+ * | | | | * | | | processOptionFile() * | | | | * | | +------+------+ * | | | * | | LookUpAndStore(*) * | | | * | | +---+---+----------+ * | | | | | * | +-----+----+ LookUp(*) Ambiguity(*) * | | | * +----+----+ updateOptionsFile(*) * | * defaultHelpHandler(*) * * * getopts() * Operates on the options table given to it as an argument. * a) Each "value" field is initialized to its "defaultValue" field. * b) The "value" fields are re-initialized by any corresponding values found * in the options ("rc") file, (overriding the "defaultValue"). * c) The "value" fields are re-initialized again by any corresponding values * found in command-line arguments. * d) Special arguments are dealt with: * "help" calls the onLineHelpHandler() routine, (see below). * "update" calls the updateOptionsFile() routine. * e) Return the remainder of the command-line (argc and argv) for use in * main(). * * helpopts() * Is called to print the help menu if no input file has been found by * getopts(), (in the "rc" file), and none remains on the command-line. * An alias for the onLineHelpHandler() function, which is in turn an * alias for the defaultHelpHandler() routine, (see options.c). * * readopts() * Read any options header which may be at the start of the input file. * Interpret the header like an options ("rc") file, and re-initialize any * corresponding "value" fields in the given options table, (as in getopts()). * Skip to the start of the input data, allowing for any offset (ie startstr). * * writeopts() * Write the given options table as an options header at the start of an o/p * file, if the "header" option is "on". * ****************************************************************************/ static Option *options; /******************** Display options table ******************************** * Options table for application display parameters. ****************************************************************************/ static Option displayopts[] = { /* Miscellaneous Silent Parameters (hidden from users) */ { "Version", headerstr, &versionstr, "Version number and date", OutputOption}, { "test1", "0", &test1str, "Dummy option for test and development", SilentOption}, { "test2", "0", &test2str, "Dummy option for test and development", SilentOption}, { "test3", "0", &test3str, "Dummy option for test and development", SilentOption}, { "test4", "0", &test4str, "Dummy option for test and development", SilentOption}, { "linear_sgm", OffOption, &linstr, "Linear frequency axis for spectrograms",SilentOption}, { "useprevious", OffOption, &reusestr, "Use previously stored output", SilentOption}, /* MAA: 21-8-1993 * These next two options are here, because otherwise "gensgm -use ..." (at least) core dumps. */ { "framenumber", OffOption, &framenumberstr, "Index of current frame (to stderr)\n", SilentOption}, { "review", OffOption, &reviewstr, "Wait for keyboard <return> between frames",SilentOption}, #ifdef X11 { "pstofile", OffOption, &psfilestr, "Send PostScript output to .ps file", SilentOption}, { "invert", OffOption, &invertstr, "Invert axis of sai image", SilentOption}, { "fast", OffOption, &kludgestr, "Speed up image generation", SilentOption}, #endif /* X11 */ /* ( The order of the "help" option members is strange due to the way */ /* it was originally used. See options.c: defaultHelpHandler() and */ /* updateOptionsFile() ). */ /* Input Parameters */ { "envelope", OffOption, &envstr, "Type of model to use required", SilentOption}, { "help", "not used", &helpstr, helpstring, SilentOption}, #ifdef X11 /* Screen Output Parameters */ { "title", "filename", &titlestr, "Title of picture, or input filename", InputOption}, #ifdef THINK_C { "x0_win", "10", &xstr, "Left edge of window (pixels)", InOutOption}, { "y0_win", "50", &ystr, "Lower edge of window (pixels)", InOutOption}, #else { "x0_win", CenterStr, &xstr, "Left edge of window (pixels)", InOutOption}, { "y0_win", CenterStr, &ystr, "Lower edge of window (pixels)", InOutOption}, #endif #ifdef PC { "width_win", "400", &widthstr, "Window width (pixels)", InOutOption}, { "height_win", "300", &heightstr, "Window height (pixels)\n", InOutOption}, #else /* UNIX */ { "width_win", "540", &widthstr, "Window width (pixels)", InOutOption}, { "height_win", "400", &heightstr, "Window height (pixels)\n", InOutOption}, #endif { "display", OnOption, &dispstr, "Select display of output image", InOutOption}, { "view", LandStr, &viewstr, "Select display format", InOutOption}, { "top", "1024", &topstr, "Maximum of plotted range", InputOption}, { "bottom", "-1024", &botstr, "Minimum of plotted range", InputOption}, { "overlap", "50%", &overstr, "Overlap between channels", SilentOption}, /* AJD 16-5-95 */ { "headroom", "0%", &roomstr, "Headroom at top of picture", SilentOption}, /* AJD 16-5-95 */ { "magnification", "1", &magstr, "Magnification of image in display", InputOption}, { "pensize", "1", &penstr, "Size of plotted lines and dots", InputOption}, { "hiddenline", OnOption, &hiddenstr, "Hidden line removal\n", InputOption}, { "perspective", "0", &tiltstr, "Perspective view of display (degrees)\n", SilentOption}, /* AJD 16-5-95 */ #endif /* X11 */ { "downchannel", OffOption, &downcstr, "Average adjacent frequency channels\n", InOutOption}, #ifdef X11 /* Auditory image cartoon parameters */ { "erase_ctn", OnOption, &erasestr, "Erase display between cartoon frames", InOutOption}, { "animate_ctn", OffOption, &animstr, "Animate cartoon", InOutOption}, { "bitmap_ctn", OffOption, &bitmapstr, "Produce cartoon output (.ctn)\n", InputOption}, { "mono_ctn", OnOption, &monostr, "Force monochrome (single plane) cartoons.", SilentOption}, { "colour_ctn", OffOption, &colourstr, "Force colour (multi-plane) cartoons.", SilentOption}, {"planemask_ctn", "1", &planemaskstr, "Planemask for creating cartoons.\n", SilentOption}, {"fg_col", "black", &fgcolourstr, "Foreground Colour.\n", SilentOption}, {"bg_col", "white", &bgcolourstr, "Background Colour.\n", SilentOption}, /* Postscript options */ { "postscript", OffOption, &psstr, "Produce postscript output", InputOption}, { "rotateaxes", OffOption, &rotateaxesstr, "Rotate the axes labels in .ps output", SilentOption}, { "xstart_ps", "", &xstartstr, "Postscript x-axis: start point.", SilentOption}, { "xend_ps", "", &xendstr, "Postscript x-axis: end point.", SilentOption}, { "ystart_ps", "", &ystartstr, "Postscript y-axis: start point.", SilentOption}, { "yend_ps", "", ¥dstr, "Postscript y-axis: end point.", SilentOption}, { "xtitle_ps", "", &xnewtitlestr, "Postscript x-axis: title.", SilentOption}, { "ytitle_ps", "", &ynewtitlestr, "Postscript x-axis: title.", SilentOption}, { "portrait_ps", "", &portraitstr, "Use 'portrait' page format", SilentOption}, { "landscape_ps", "", &landscapestr, "Use 'landscape' page format (overrides 'portriat)", SilentOption}, { "fontname_ps", "Helvetica", &fontnamestr, "Define font", SilentOption}, { "fontsize_ps", "12", &fontsizestr, "Define fontsize (points)", SilentOption}, { "fonttitlesize_ps", "0", &titlesizestr, "Define fontsize for title (points)", SilentOption}, { "axislinewidth_ps", "1", &axislinewidthstr, "Linewidth for axes & tickmarks (points)", SilentOption}, { "figurelinewidth_ps", "1", &figurelinewidthstr, "Linewidth for figures (points)", SilentOption}, { "xticks_ps", "6", &xticksstr, "Define size of x-axis (big) ticks (points)", SilentOption}, { "yticks_ps", "6", &yticksstr, "Define size of y-axis (big) ticks' (points)", SilentOption}, { "outsideticks_ps",OnOption, &outsidestr, "Print tick-marks 'outside' figure", SilentOption}, { "axistop_ps", OnOption, &axistopstr, "Print tick-marks on top side", SilentOption}, { "axisbottom_ps", OnOption, &axisbottomstr, "Print tick-marks on bottom side", SilentOption}, { "axisleft_ps", OnOption, &axisleftstr, "Print tick-marks on left side", SilentOption}, { "axisright_ps", OnOption, &axisrightstr, "Print tick-marks on right side", SilentOption}, { "xmajorticks_ps", "1", &xmajorticksstr, "Relative *spacing* of ticks", SilentOption}, { "xminorticks_ps", "1", &xminorticksstr, "Relative *spacing* of ticks", SilentOption}, { "ymajorticks_ps", "1", &ymajorticksstr, "Relative *spacing* of ticks", SilentOption}, { "yminorticks_ps", "1", &yminorticksstr, "Relative *spacing* of ticks", SilentOption}, { "box_ps", OnOption, &boxstr, "Plot a box", SilentOption}, #endif /* X11 */ /* File Output Parameters */ { "output", OffOption, &outstr, "Produce output file", InputOption}, { "header", OnOption, &headstr, "Add a header to the output file\n", InOutOption}, { "bytemax", "255", &bmaxstr, "Maximum value in byte output", SilentOption}, /* AJD 16-5-95 */ { "type", "short", &typestr, "Output data type\n", SilentOption}, /* AJD 16-5-95 */ { "input_wave", NullOption, &filestr, "Default input file name", InputOption}, { "start_wave", "0ms", &startstr, "Start point in wave (ms)", InputOption}, { "length_wave", LengthStr, &lengthstr, "Length of wave to process (ms)", InputOption}, ( char * ) 0 } ; /*********************** Included from stitch directory ********************/ /* interfaces to stitch system */ #include "stitch.h" #include "source.h" #include "spiral.h" #include "image.h" #include "model.h" #include "units.h" #include "calc.h" #include "ops.h" #include "io.h" #ifdef X11 #include "draw.h" #include "fill.h" #endif /* X11 */ /**************************************************************************/ char *AlterSuffix() ; /* alter suffix of file name. */ #ifdef X11 void save_frame(), plot_frame() ; /* draw callbacks. */ void fast_frame() ; #endif /* X11 */ extern char *genstate() ; static char *gen_state ; Source DownChannel() ; /* reduce channels by averaging. */ #ifdef X11 Source PackShorts() ; /* pack output into one byte. */ #endif /* X11 */ Source checkForFile() ; /* create source from file if present. */ #define POSTSCRIPT_FILE_SUFFIX ".ps" #define CARTOON_FILE_SUFFIX ".ctn" #ifdef X11 static WindowObject display = 0 ; #endif /* X11 */ /***************************************************************************/ /* Return length of the file in bytes */ static long fileLength( fp ) FILE *fp ; { long posn = ftell( fp ) ; long length = 0 ; if( fseek( fp, 0l, 2 ) == 0 ) { length = ftell( fp ) ; (void) fseek( fp, posn, 0 ) ; } return ( length ) ; } /* per frame image handling */ static FILE *inputFilePointer = ( FILE * ) 0 ; #ifdef X11 static FILE *imageFilePointer = ( FILE * ) 0 ; static int images = 0 ; static void (*frame_drawer)() ; /***** axis information *****/ /* "Axis" is defined in windows.h:143 The postscript program for drawing axis stuff is in axis.h */ static int Top() { return ( atof( topstr ) / atof( magstr ) + 0.5 ) ; } static int Bot() { if( atof( botstr ) < 0 ) return ( atof( botstr ) / atof( magstr ) - 0.5 ) ; else return ( atof( botstr ) / atof( magstr ) + 0.5 ) ; } static struct { double min, max ; char *label ; } xaxis, yaxis ; TimeAxis( min, max, label ) double *min, *max ; char **label ; { *min = Samples( startstr, Samplerate() ) / Samplerate() ; *max = Samples( startstr, Samplerate() ) / Samplerate() + Frames() * Framestep() / Samplerate() ; if( *max > 1. ) *label = "Time [s]" ; else { *label = "Time [ms]" ; *min *= 1000. ; *max *= 1000. ; } } MagnitudeAxis( min, max, label ) double *min, *max ; char **label ; { *min = Bot() ; *max = Top() / ( 1. - atof( headstr ) / 100. ) ; *label = "Magnitude" ; } static void DrawAxes( win ) WindowObject win ; { /* frame window with axes */ Axes( win, titlestr, xaxis.min, xaxis.max, xaxis.label, yaxis.min, yaxis.max, yaxis.label ) ; return ; } #endif /* X11 */ /******************************* main ************************************** * The following tables are used extensively: * stage table Arrays of _stage structs, ("envelope", "fine", etc.), defined * in routine FindStage() in model.c. * option table Array of Option structs built at run-time by * constructOptions() from displayopts, (in gen.c), and tables of * model options included from table.c. * * Compiler switches for model versions are: * FLOAT For floating point version, (default uses integer arithmetic). * Defined in calc.h. * * The model version number is the sccs <release-number>.<level-number> of * the file version.c. Refer to that file for incrementing the version number. * The version number is stored in versionstr in routine getversion(). ****************************************************************************/ int argc_save ; char **argv_save ; main( argc, argv ) int argc ; char *argv[] ; #ifdef THINK_C { static char *realargv[] = { "prog", "", 0 }; static char *progs = { "\pgenwav;-;\ genfbm;genfbr;genfbc;genfbt;genfbd;gensai;genspl;gensas;-;\ genbmm;gennap;gensai;-;gensgm;gencgm;gensas;-;genasa;genepn;gensep;-;Quit/Q" } ; extern char *MacMenu(), *MacFile() ; MacInit() ; realargv[0] = MacMenu(progs) ; realargv[1] = MacFile() ; return ( real_main( sizeof( realargv ) / sizeof (*realargv) - 1, realargv ) ) ; } real_main( argc, argv ) int argc ; char *argv[] ; #endif { int i ; FILE *ofp = 0 ; Source source ; char *which, *psfilename ; char title[256] ; char *programName ; int x, y, pixels, image, time ; long headerSize, fileFramebytes ; double *frequency_scale ; #ifdef X11 WindowObject psw = 0 ; char *imageFileName ; #endif /* X11 */ /************************************************************************** * Determine which version of the model is required. * Set "which" to the last three chars of the program name, (allowing for * a ".exe" extension in the case of a PC version). **************************************************************************/ programName = argv[0] ; which = programName + strlen( programName ) - strlen( "xxx" ) ; #ifdef PC lowerArgs( argv, argc ) ; which -= strlen( ".exe" ) ; #endif /*************************************************************************** * Process arguments, (the model options): * Set option defaults (from option table in model.c). * Then override these by any options in the options file, * (the resource control file, eg .gensairc). * Finally, override these by any options given as command-line arguments. * * offsetOptions() finds the first option, (a ptr to one line of the "res" * array), required by the program. This gives a place mark in the options * table. (Note that the bottom of the options table, a null, corresponds with * the top of the help menu). * This first option appropriate to the program is found by looking it up in * the stage table (in model.c), and then cross-referencing the option name * with the names in the options table. * * Here is an example of an option, showing the members of the Options struct: * name: defaultValue: value: comment: classification: * {"length_wave", LengthStr, &lengthstr, "Length of wave", InputOption}, * * getopts() operates on the options between the given place mark and the * bottom of the table. * This is the only call to routine getopts(), which is defined in options.c. * First, each "value" is set to its corresponding "defaultvalue". * Then the options file (the "rc" file) is opened, and any options found there * are assigned to the corresponding "value", (overriding the "defaultvalue"). * Then the command-line arguments are examined, and any options found there * are assigned to the corresponding "value", (overriding again). * Special arguments are dealt with: * "help" calls the onLineHelpHandler() routine, (see below). * "update" calls the updateOptionsFile() routine. * * Finally, leave the remainder of the command line (argc and argv). * Anything left on the command line is interpreted as follows: * "filestr" is the input data filename, * "startstr" is the start point in the data, * "lengthstr" is the amount of data to process, * "whichstr" is the last 3 chars of the program name (the program version). * * Note that if no input file has been found by getopts(), (in the "rc" file), * and none remains on the command line, then helpopts() is called. * This is an alias for the onLineHelpHandler() function, which is in turn an * alias for the defaultHelpHandler() routine, (see options.c). * * ***************************************************************************/ getversion( programName ) ; /* The helpstring, defined in model.c, is stored as the comment field */ /* of the help option (see table.c). It is accessed in options.c in */ /* defaultHelpHandler(), using options[help].comment. */ (void) sprintf( helpstring, " [file_name]\n Generates %s", modelHelp( which ) ) ; options = constructOptions( which, displayopts ) ; /* Hack to save argc and argv so they don't get mangled by getopts */ /* This is so the command line args can override a reused file header */ argc_save = argc ; argv_save = (char **)malloc( ( argc + 1 ) * sizeof( char *) ) ; for ( i = 0 ; i < argc ; i++ ) { argv_save[i] = (char *)malloc( ( strlen( argv[i] ) + 1 ) * sizeof( char ) ) ; strcpy( argv_save[i], argv[i] ) ; } getopts( options, &argc, &argv ) ; if( argc == 0 && isNULL( filestr ) ) { (void) helpopts( options, programName ) ; stitch_exit( -1 ) ; } if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 ) filestr = *argv++ ; if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 ) startstr = *argv++ ; if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 ) lengthstr = *argv++ ; if( isNULL( whichstr ) ) whichstr = which ; /*************************************************************************** * horrrrrrrrible hack for now to try out -envelope option ***************************************************************************/ if( isON( envstr ) ) if( whichstr[1] == 'b' ) whichstr[1] = 'e' ; else { /* map sai to sie and sas to sse */ whichstr[1] = whichstr[2] ; whichstr[2] = 'e' ; } /*************************************************************************** * hack test arguments ***************************************************************************/ #if 00 test1 = atof( test1str ) ; test2 = atof( test2str ) ; test3 = atof( test3str ) ; test4 = atof( test4str ) ; #endif /*************************************************************************** * Open input data file, (use stdin if filename "-" is given). ***************************************************************************/ if( strcmp( filestr, "-" ) == 0 ) inputFilePointer = stdin ; else inputFilePointer = fopen( filestr, readBinary ) ; /*************************************************************************** * Position input data file pointer correctly: * Read any options header at the start of the input file. Set any options. * Skip to the start of the input data, allowing for any offset (ie startstr). * Set "framesstr" to the number of frames in the input data file, (here this * means the number of shorts remaining in the input file). * Create a source for the input data file. * Re-set "framesstr" to allow for a given "lengthstr", (ie not the whole file). ***************************************************************************/ if( inputFilePointer != (FILE *) 0 ) { readopts( options, inputFilePointer ) ; headerSize = ftell( inputFilePointer ) ; setFrames( fileLength( inputFilePointer ) / sizeof ( short ) - (long) Samples( startstr, Samplerate() ) ) ; (void) fseek( inputFilePointer, (long)( headerSize + (long) Samples( startstr, Samplerate() ) * sizeof ( short ) ), 0 ) ; source = FileSource( inputFilePointer ) ; } /* If a specific processing amount is specifed (other than "remainder") */ /* and this amount is less than the remainder of the input file, then */ /* override the amount of data to process, (in framesstr). */ if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) != 0 && Samples( lengthstr, Samplerate() ) < Frames() ) setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ; /*************************************************************************** * Create source with data derived from processing file through model. * This may involve several stages of callback, and will initialize a chain of * objects which will ultimately execute the program, (see SinkSource() below). * If reusestr in "on", the "useprevious" option will use a previously * generated file, (see checkForFile() routine below). * If no input data file is found, report error: "could not open file". * * The routine ModeledSource() first uses Findstage() to find the appropriate * place in the stage table called for by the program, (see model.c). * Then it finds the end of the stage table, and works back up the table to * the stage called for by the program. Each stage in the table is a process * on the way to the program as a whole. The order of the stage table sets the * order of processing. * Immediately below are the only two calls to routine ModeledSource(). ***************************************************************************/ if( isON( reusestr ) ) source = ModeledSource( source, checkForFile ) ; else if( inputFilePointer != (FILE *) 0 ) source = ModeledSource( source, (Source ( * )()) 0 ) ; if( inputFilePointer == (FILE *) 0 ) stitch_error( "Could not open file \"%s\" for input\n", filestr ) ; /*************************************************************************** * If the "downchannel" option is on, reduce channels by averaging. * (See DownChannel() routine below). * Then updateFramebytes sets "framebytesstr" to the total number of bytes * in each frame, (ie the new width * height). ***************************************************************************/ for( time=0 ; time<OptionInt( downcstr ) ; time++ ) { source = DownChannel( source, Frameheight() ) ; setFrameheight( Frameheight() / 2 ) ; } updateFramebytes() ; #if 0 /* for debugging */ fprintf( stderr, "%d %d %d %d %ld\n", Framewidth(), Frameheight(), Framebytes(), Framestep(), Frames() ) ; #endif /*************************************************************************** * From here on is concerned with setting up for output, then starting the * processing, and finally cleaning up. ***************************************************************************/ #ifdef X11 /* First sort out window placement. */ if( strcmp( xstr, CenterStr ) == 0 ) x = -1 ; else x = atoi( xstr ) ; if( strcmp( ystr, CenterStr ) == 0 ) y = -1 ; else y = atoi( ystr ) ; if( isGREYSCALE( viewstr ) ) pixels = 0 ; else { pixels = atoi( penstr ) ; if( isON( hiddenstr ) && Frameheight() > 1 ) pixels = -abs( pixels ) ; /* Convert arguments for line-drawing. See draw.ch */ drawTilt = atof( tiltstr ) ; drawDistance = atof( diststr ) ; drawHeadroom = atof( roomstr ) ; drawOverlap = atof( overstr ) / 100. ; #ifdef mips if( pixels == 0 ) pixels = 1 ; #endif } #endif /* X11 */ /* work out title of output */ (void) strcpy( title, filestr ) ; (void) strcat( title, "." ) ; (void) strncat( title, whichstr, strlen( "xxx" )+1 ) ; #ifdef X11 if( strcmp(titlestr,"filename") == 0) /* was: if(isNULL(titlestr)) */ titlestr = title ; /* calculate axis information */ if( isEXCITE( viewstr ) ) { ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; } else if( isWATERFALL( viewstr ) ) { ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; TimeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; } /* landscape ones */ else if( Framewidth() > 1 ) { DelayAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; } else { TimeAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; if( Frameheight() > 1 ) ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; else MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; } /* select outputs... */ /* select sai drawing method */ /* Hack so spiral parameters are independent of stage and option order */ /* (Spiral parameters appear late in options list, so are not known */ /* when an earlier stage is specified. So don't process unless sai). */ if( strncmp(whichstr,"spl",strlen("spl")) == 0 ) { frame_drawer = draw_spiral; dotthresh_spl = Top() ; dotsize_spl = OptionInt( penstr ) ; } else frame_drawer = draw_frame; /* screen output first */ /* (set by option: display=on) */ if( isON( dispstr ) ) { display = newDisplayWindow( titlestr, x, y, atoi( widthstr ), atoi( heightstr ), pixels ) ; if( !isGREYSCALE( viewstr ) /* && OptionInt( penstr ) != 0 */ ) { if( Top() == Bot() ) stitch_error( "error: display top and bottom parameters the same value\n" ); if( isEXCITE( viewstr ) ) source = SourceDraw( source, Bot(), Top(), display, Frameheight(), 1, Nwidth(), Frames(), save_frame, frame_drawer ) ; else if( isWATERFALL( viewstr ) ) source = SourceDraw( source, Bot(), Top(), display, Frameheight(), Frames(), Nwidth(), 1, save_frame, frame_drawer ) ; else if( !isON( kludgestr ) ) source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, frame_drawer ) ; else { /* speed-up for sai */ source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, fast_frame ) ; gen_state = genstate( display, Bot(), Top(), Framewidth(), Frameheight(), Nwidth(), Frames(), pixels ) ; frame_drawer=fast_frame ; } } else { if( isON( erasestr ) ) Clear( display ) ; DrawAxes( display ) ; if( isON( linstr ) ) frequency_scale = frequencies ; else frequency_scale = (double *) 0 ; if( Framewidth() > 1 ) source = FillDown( display, source, Top(), Bot(), Framewidth(), Frameheight() ) ; else source = fillAcross( display, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ; } } /* postscript output next */ /* (set by option: postscript=on) */ if( isON( psstr ) ) { if( isON( psfilestr ) ) psfilename = AlterSuffix( filestr, POSTSCRIPT_FILE_SUFFIX ) ; else psfilename = (char *) 0 ; /* the extra argument to newPSWindow. MAA> 27-1-1993. */ psw = newPSWindow( psfilename, x, y, atoi(widthstr), atoi(heightstr), atoi( penstr ), isON( hiddenstr ) ); if( !isGREYSCALE( viewstr ) && OptionInt( penstr ) != 0 ) { if( isEXCITE( viewstr ) ) source = SourceDraw( source, Bot(), Top(), psw, Frameheight(), 1, Nwidth(), Frames(), plot_frame, frame_drawer ) ; else if( isWATERFALL( viewstr ) ) source = SourceDraw( source, Bot(), Top(), psw, Frameheight(), Frames(), Nwidth(), 1, plot_frame, frame_drawer ) ; else source = SourceDraw( source, Bot(), Top(), psw, Framewidth(), Frameheight(), Nwidth(), Frames(), plot_frame, frame_drawer ) ; } else { /* greyscale displays */ if( isON( erasestr ) ) Clear( psw ) ; DrawAxes( psw ) ; if( isON( linstr ) ) frequency_scale = frequencies ; else frequency_scale = (double *) 0 ; if( Framewidth() > 1 ) source = FillDown( psw, source, Top(), Bot(), Framewidth(), Frameheight() ) ; else source = fillAcross( psw, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ; } } if( strcmp( typestr, "char" ) == 0 ) { source = PackShorts( source ) ; fileFramebytes = Framebytes() / sizeof ( short ) * sizeof ( char ) ; } else #endif /* X11 */ fileFramebytes = Framebytes() ; /* output to file */ if( !isOFF( outstr ) ) { (void) unlink( title ) ; if( OptionStringsEqual( outstr, OnOption ) ) ofp = fopen( title, writeBinary ) ; else { if( strcmp( outstr, "stdout" ) == 0 ) ofp = stdout; else ofp = fopen( outstr, writeBinary ) ; } if( ofp == (FILE *) 0 ) stitch_error( "Unable to open file %s for output\n", title ) ; else { if( isON( headstr ) ) writeopts( options, ofp ) ; source = FileTap( source, ofp ) ; } } #ifdef X11 /* output of screen "image" files in display format */ if( !isOFF( bitmapstr ) ) { imageFileName = AlterSuffix(filestr, CARTOON_FILE_SUFFIX ) ; if( (strcmp( bitmapstr, "stdout" ) == 0 )){ imageFilePointer = stdout; writeopts( options, imageFilePointer ) ;} else if ( ( imageFilePointer = fopen(imageFileName, writeBinary ) ) == (FILE *) 0) stitch_error( "Unable to open file %s for image output\n", imageFileName ) ; else writeopts( options, imageFilePointer ) ;} if (( ofp == stdout ) && ( imageFilePointer == stdout )) stitch_error( "Both 'output' and 'bitmap' set to stdout.\n", title); #endif /* X11 */ /*************************************************************************** * Execute the program by pulling data from the source. * This is the only call to routine SinkSource(), which is defined in * stitch/source.c as sinkSource(). * (SinkSource is an alias, defined in stitch/source.h, to cast the arguments). * Routine sinkSource() executes: "(void) Pull( source, fileFramebytes ) ;" * for "Frames()" times in succession. * A chain of source objects, linked by callback-function pointers, was setup * earlier, (see call to ModeledSource() above). ***************************************************************************/ SinkSource( source, fileFramebytes, Frames() ) ; /*************************************************************************** * Clean up and close ****************************************************************************/ CloseSource( source ) ; if( ofp != (FILE *) 0 ) (void) fclose( ofp ) ; #ifdef X11 if( psw != (WindowObject) 0 ) Close( psw ) ; if( display != (WindowObject) 0 ) { /* animate sai's if selected */ do { for( image=1 ; image <= images ; image++ ) for( time = OptionInt( animstr ) ; time>0 ; time-- ) Recall( display, image ) ; if( Pause( display ) == 'q' ) break; } while( isON( animstr ) ) ; Close( display ) ; } #endif /* X11 */ stitch_exit( 0 ) ; } /*************************** End main *************************************/ /*************************************************************************** * checkForFile() * Create source from file if present, to be used if reusestr in "on". * This is the "useprevious" option to use previously generated files. ***************************************************************************/ Source checkForFile( which ) char *which ; { static Source noSource = { (struct _source *) 0 } ; long headerSize, fileFramebytes ; char file_name[200] ; FILE *tmp ; (void) strcpy( file_name, filestr ) ; (void) strcat( file_name, "." ) ; (void) strcat( file_name, which ) ; if( ( tmp = fopen( file_name, readBinary ) ) != ( FILE * ) 0 ) { inputFilePointer = tmp ; (void) fprintf( stderr, "Using existing file \"%s\"\n", file_name ) ; readopts( options, inputFilePointer ) ; /* the saved command line overrides options from file header */ if( isON( reusestr ) ) cmd_line_opts( options, &argc_save, &argv_save ) ; headerSize = ftell( inputFilePointer ) ; if( strcmp( typestr, "char" ) == 0 ) fileFramebytes = Framebytes() / 2 ; else fileFramebytes = Framebytes() ; /* If length=remainder then use the whole file. Otherwise the length of the reused file is that given on the command line, or the default length (if no length option is given). */ if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) == 0 ) setFrames( ( fileLength( inputFilePointer ) - headerSize ) / fileFramebytes - (long) Samples( startstr, Samplerate() ) / Framestep() ) ; else setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ; (void) fseek( inputFilePointer, headerSize + (long) Samples( startstr, Samplerate() ) / Framestep() * fileFramebytes, 0 ) ; #ifndef PC if( strcmp( typestr, "char" ) == 0 ) return( CharShortSource( FileSource( inputFilePointer ) ) ) ; else #endif return( FileSource( inputFilePointer ) ) ; } else return( noSource ) ; } /*************************************************************************** * AlterSuffix(). * Returns its argument fileName with a newSuffix appended in place of * any previous suffix it may have had. It should be noted that this * suffix must include any DOT it wishes to have appended to the name. ***************************************************************************/ /* File Name Suffix Conversion Parameters */ #define BACKSLASH_CHAR '\\' #define SLASH_CHARACTER '/' #define NULL_CHARACTER '\000' #define DOT_CHARACTER '.' char *AlterSuffix(fileName, newSuffix) char *fileName, *newSuffix; { char *temp, *temp2, *lastPart; #if defined( PC ) int i; #endif temp = stitch_malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1), "AlterSuffix" ); temp = strcpy(temp, fileName); #if defined(PC) /* Change all backslashes to forward slashes */ for (i = 0; temp[i] != NULL_CHARACTER; i++) if (temp[i] == BACKSLASH_CHAR) temp[i] = SLASH_CHARACTER; #endif if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL) lastPart = temp; else lastPart++; /* Skip over the actual "/" */ /* lastPart points to the tail name of the path */ if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL) temp = strcat(temp, newSuffix); else temp2 = strcpy(temp2, newSuffix); return (temp); } #ifdef X11 /*************************************************************************** * Interceptions for various combinations of drawing. * An "interception function" is a function inserted into a chain a functions * linked by function pointers. The inserted function "intercepts" the * processing, to perform some transformation. ****************************************************************************/ /* intercept draw to store images for animation */ void save_frame( state, frame, first ) struct _draw_state *state ; short *frame ; int first ; { if( first ) { if( isON( erasestr ) ) Clear( state->window ) ; if( frame_drawer != (void (*)()) draw_spiral && state->framenumber == 1 ) DrawAxes( state->window ) ; } frame_drawer( state, frame ) ; if( isON( animstr ) && isOFF( kludgestr ) ) if( Store( state->window ) ) ++images ; if( isON( bitmapstr ) ) Write( state->window, imageFilePointer ) ; return ; } /* hacky but effective faster frame drawing routine - for sai only! */ void fast_frame( state, frame, first ) struct _draw_state *state ; short *frame ; int first ; { if( isON( animstr ) || images == 0 ) if( Store( state->window ) ) ++images ; /* generate image in current cleared image */ generate( gen_state, frame ) ; /* then recal the window using the modified image */ Recall( state->window, images ); return ; } /* intercept plot to check if page should be output for printing */ static int plot_wanted( state ) struct _draw_state *state ; { #if !defined(PC) if( display != ( WindowObject ) 0 && state->framewidth > 1 && state->frames > 1 ) { (void) fprintf(stderr, "Hit \"y\" to include this image in the PostScript file: "); switch ( Pause( display ) ) { case 'y' : case 'Y' : case 'p' : case 'P' : return 1 ; default : return 0 ; } } #endif return 1 ; } void plot_frame( state, frame, first ) struct _draw_state *state ; short *frame ; int first ; { int centering = state->window->entries->x( state->window ) < 0 && state->window->entries->y( state->window ) < 0 ; if( isOFF( erasestr ) || state->framewidth == 1 || plot_wanted( state ) ) { if( first && ( state->framenumber == 1 || isON( erasestr ) ) ) { /* *** if( centering ) *** removed the conditional. M.Akeroyd. 22-1-1993.*/ Clear( state->window ) ; if( frame_drawer != (void (*)()) draw_spiral ) DrawAxes( state->window ) ; } frame_drawer( state, frame ) ; } return ; } #endif /* X11 */ /*************************************************************************** * downchannel: average across channels for output (with special sai version) ***************************************************************************/ struct _down_channel_state { struct _fillable_source parent ; int channels ; Source input ; } ; static Pointer down_channel_callback( state, bytes, buffer ) struct _down_channel_state *state ; ByteCount *bytes ; short *buffer ; { register int last = *bytes == 0 ; register int chan, outchans = state->channels >> 1 ; long frame, frames = ToPoints( short, *bytes ) / outchans ; register short *iptr = PullItems( state->input, frames * state->channels, short ) ; register short *bptr = buffer ; for( frame=0 ; frame<frames ; frame++ ) { for( chan=0 ; chan<outchans ; chan++ ) *bptr++ = ( *iptr++ + *iptr++ ) / 2 ; if( ( outchans << 1 ) != state->channels ) iptr++ ; } if( !last ) return ( (Pointer) buffer ) ; else return ( DeleteFillableSource( state ) ) ; } static Pointer down_channel_callback_sai( state, bytes, buffer ) struct _down_channel_state *state ; ByteCount *bytes ; short *buffer ; { register int last = *bytes == 0 ; register int chan, outchans = state->channels >> 1 ; long frame, frames = ToPoints( short, *bytes ) / outchans ; register short *iptr = PullItems( state->input, frames * state->channels, short ) ; register short *bptr = buffer ; register short *iptr2 ; iptr2 = iptr + frames ; for( chan=0 ; chan<outchans ; chan++ ) { for( frame=0 ; frame<frames ; frame++ ) *bptr++ = ( *iptr++ + *iptr2++ ) / 2 ; } if( !last ) return ( (Pointer) buffer ) ; else return ( DeleteFillableSource( state ) ) ; } Source DownChannel( source, channels ) Source source ; { DeclareNew( struct _down_channel_state *, state ) ; state->channels = channels ; state->input = source ; /* Hack for special-case downchannel routine to handle format of sai and spl frames (mha: 22/6/93) */ if( strncmp(whichstr,"sai",strlen("sai")) == 0 || strncmp(whichstr,"spl",strlen("spl")) == 0 ) return ( SetFillableSource( state, down_channel_callback_sai, "down channeling sai frames" ) ) ; return ( SetFillableSource( state, down_channel_callback, "down channeling" ) ) ; } #ifdef X11 /*************************************************************************** * Pack model output onto a single byte if required, * using greyscale Top() from display. ***************************************************************************/ typedef struct { struct _fillable_source parent ; Source input ; } *PackSource ; static Pointer pack_callback( state, bytes, buffer ) PackSource state ; ByteCount *bytes ; Pointer buffer ; { register int last = *bytes == 0 ; register short *iptr = PullShorts( state->input, *bytes ) ; register Pointer optr = buffer ; register Pointer eptr = buffer + *bytes ; register int bytemax = atoi( bmaxstr ) ; register int max = Top() ; register int min = Bot() ; while( optr < eptr ) if( *iptr > max ) { *optr++ = bytemax ; iptr++ ; } else if( *iptr < min ) { *optr++ = 0 ; iptr++ ; } else *optr++ = ( ( ( *iptr++ - min ) * bytemax + ( bytemax >> 1 ) ) / ( max - min ) ) & 0xff ; if( !last ) return ( buffer ) ; else return ( DeleteFillableSource( state ) ) ; } Source PackShorts( input ) Source input ; { DeclareNew( PackSource, source ) ; source->input = input ; return ( SetFillableSource( source, pack_callback, "gen.c packing" ) ) ; } #endif /* X11 */ /***************************************************************************/ #ifdef PC static lowerArgs( argv, argc ) char **argv ; int argc ; { register char *ptr ; register int arg ; for( arg=0 ; arg<=argc ; arg++ ) for( ptr=argv[arg] ; *ptr != '\000' ; ptr++ ) if( isupper( *ptr ) ) *ptr = tolower( (int) *ptr ) ; return ; } #endif /*************************************************************************** * Set the value of versionstr to the model version number and current time. * The version number is the sccs <release-number>.<level-number> of the file * version.c. The current time is returned by ctime(time(0)). * This routine initializes the default version-string (headerstr), which is * later copied into the version-string (versionstr) during getopts(). * In this way, the version-string is available for output at the head of * the help and the options (rc) files, and also output as part of the header, * (when output=on). * Note, the versionstr has to be quoted, otherwise the routine * processOptionFile in options.c will report an error (Detected Trailing...) * when it finds blanks within a line. This happens when trying to read an * options file, for example when reviewing. The addition of quotes enables * a line containing blanks to be read complete by the subroutine getName. ***************************************************************************/ #include "version.c" getversion( name ) char *name ; { char releasestr[8] ; char levelstr[8] ; char timestr[32] ; char *namestr ; long int timeval ; sprintf(releasestr, "%d", atoi( version_Id ) ) ; sprintf(levelstr, "%d", atoi( version_Id + strlen(releasestr) + 1 ) ) ; if ( ( namestr = strrchr( name, '/' ) ) == (char *)0 ) namestr = name ; else namestr++ ; #if defined( PC ) || defined( THINK_C ) sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s]\"", releasestr, levelstr, namestr ) ; #else timeval = time(0); sprintf(timestr,"%s", ctime(&timeval) ) ; timestr[strlen(timestr) - 1] = '\0'; /* remove newline */ sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s] %s\"", releasestr, levelstr, namestr, timestr ) ; #endif }