comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:5242703e91d3
1 /*
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
3 ===========================================================================
4
5 Permission to use, copy, modify, and distribute this software without fee
6 is hereby granted for research purposes, provided that this copyright
7 notice appears in all copies and in all supporting documentation, and that
8 the software is not redistributed for any fee (except for a nominal shipping
9 charge). Anyone wanting to incorporate all or part of this software in a
10 commercial product must obtain a license from the Medical Research Council.
11
12 The MRC makes no representations about the suitability of this
13 software for any purpose. It is provided "as is" without express or implied
14 warranty.
15
16 */
17
18 /*
19 gen.c
20 =====
21
22 APU, ASP model demonstration program.
23
24
25 Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit.
26
27
28 Authors : John Holdsworth (1989), Mike Allerhand (1990)
29
30
31 Edited : M.Akeroyd 22-1-1993
32 Removed the conditional of `if (centering) Clear (w)'
33 (in plot_frame), so that Clear may be called for
34 PostScriptWindows that AREN'T centered, so allowing
35 showpages to be generated.
36 See also edit to ps.c
37
38 : M Akeroyd 3-8-1993
39 Added new options:
40 erbscale_efb (InputOption) mono_ctn (SilentOption)
41 colour_ctn (SilentOption) planemask_ctn (SilentOption)
42 Allowed "bitmap=stdout".
43
44 : MAA 3rd August 1993
45 Extra options
46 framenumber (SilentOption), review (SilentOption)
47
48 : MAA 22nd July 1994.
49 Extra postscript options ALl silent
50 xstart_ps xend_ps ystart_ps yend_ps
51 xtitle_ps ytitle_ps
52 Extra X options
53 fg_col bg_col
54
55 : MAA Summer 1984. Lots of postscript options. All silent
56 portraitstr, landscapestr;
57 fontnamestr, fontsizestr;
58 xmajorticksstr, xminorticksstr, ymajorticksstr, yminorticksstr;
59 axistop, axisbottom, axisleft, axisright;
60
61 : AJD Spring 1995.
62 Added a new argument 'nwid' to the function SourceDraw, so that genspl
63 can have the necessary information.
64
65 : AJD May, 1995.
66 Made options overlap, headroom, perspective, bytemax and type silent.
67 */
68
69
70 #ifndef lint
71 static char *sccs_id = "@(#)gen.c 1.66 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 6/6/91" ;
72 #endif
73
74
75 /****************************************************************************
76 * This module contains:
77 * Display option parameter strings.
78 * Model option parameter strings.
79 * File-format strings.
80 * X windows interface, (included from windows.h).
81 * Options handler routines, (included from options.h).
82 * Option defaults, (application specific).
83 * Strings for generic option types, (OnOption etc).
84 * Display options table, (displayopts[]).
85 * Model option tables, (included from table.c).
86 * Model entry-point functions, (included from model.c).
87 * Display drawing routines, (included from draw.h and fill.h).
88 * Options table construction, (constructOptions(), and mapOptions()).
89 * Main.
90 ****************************************************************************/
91
92 #include <string.h>
93 #include <ctype.h>
94 #include <stdio.h>
95 #include <math.h>
96
97 #if defined(THINK_C) || defined(NeXT)
98 #include <stdlib.h>
99 #endif
100
101 /********************* Display option parameter strings *********************
102 * The strings defined here are pointers referenced by the "value" field in
103 * the display options table, displayopts. They are assigned to space which
104 * initially contains defaults in the "defaultValue" field of the display
105 * options table.
106 ****************************************************************************/
107
108 static char *bmaxstr, *topstr, *botstr, *overstr ;
109 static char *headstr, *downcstr, *heightstr, *helpstr ;
110 static char *invertstr, *lengthstr, *linstr, *outstr ;
111 static char *reusestr, *startstr, *envstr, *typestr ;
112 #ifdef X11
113 static char *dispstr, *erasestr, *hiddenstr, *bitmapstr ;
114 static char *kludgestr, *magstr, *penstr, *psfilestr ;
115 static char *psstr, *animstr, *titlestr, *viewstr ;
116 static char *widthstr, *xstr, *ystr ;
117 /* All these MAA. */
118 char *monostr, *colourstr, *planemaskstr, *rotateaxesstr;
119 char *fgcolourstr, *bgcolourstr;
120 char *xstartstr, *ystartstr, *xendstr, *yendstr;
121 char *xnewtitlestr, *ynewtitlestr;
122 char *portraitstr, *landscapestr;
123 char *fontnamestr, *fontsizestr, *titlesizestr;
124 char *xticksstr, *yticksstr, *outsidestr;
125 char *axistopstr, *axisbottomstr, *axisleftstr, *axisrightstr;
126 char *xmajorticksstr, *xminorticksstr, *ymajorticksstr, *yminorticksstr;
127 char *axislinewidthstr, *figurelinewidthstr;
128 char *boxstr;
129 #endif /* X11 */
130
131 char *framenumberstr, *reviewstr; /* MAA: 3-8-1993 */
132
133 static char *test1str, *test2str, *test3str, *test4str ;
134
135 char headerstr[64] ;
136
137 char *filestr ;
138
139 /* application display parameters */
140
141 #ifdef X11
142 static char *tiltstr = "0." ;
143 static char *diststr = "0.5" ;
144 static char *roomstr = "0%" ;
145 #endif /* X11 */
146
147 /*************** Included from glib (graphics library) directory ***********/
148
149 #include "options.h"
150 #include "defaults.h"
151
152 #ifdef X11
153 #include "windows.h"
154 #endif /* X11 */
155
156 /******************* Strings for generic option values **********************
157 * Generic option values, (ON_OPTION etc), are defined in options.h.
158 * Convenience routines used to test or convert option values are:
159 * OptionStringsEqual( str1, str2 ) -(defined in options.c).
160 * isON( str ) -(defined in options.h).
161 * isOFF( str ) -(defined in options.c).
162 * isNULL( str ) -(defined in options.c).
163 * OptionInt( str ) -(defined in model.c).
164 * OptionDouble( str ) -(defined in model.c).
165 * Samples( str ) -(defined in model.c).
166 * Cycles( str, cfreq ) -(defined in model.c).
167 * Scalar( str ) -(defined in model.c).
168 * Freq( str ) -(defined in model.c).
169 *
170 ****************************************************************************/
171
172
173 static char helpstring[200] = "no help initially" ;
174 static char OnOption[] = ON_OPTION ; /* "on" */
175 static char OffOption[] = OFF_OPTION ; /* "off" */
176 static char NullOption[] = NULL_OPTION ; /* "none" */
177 static char CenterStr[] = "center" ;
178 static char LengthStr[] = "remainder" ;
179 static char LandStr[] = "landscape" ;
180
181 static int isEXCITE( str )
182 char *str ;
183 {
184 return ( strncmp( str, "excitation", strlen( str ) ) == 0 ) ;
185 }
186
187 static int isWATERFALL( str )
188 char *str ;
189 {
190 return ( strncmp( str, "waterfall", strlen( str ) ) == 0 ) ;
191 }
192
193 static int isGREYSCALE( str )
194 char *str ;
195 {
196 return ( strncmp( str, "greyscale", strlen( str ) ) == 0 ||
197 strncmp( str, "grayscale", strlen( str ) ) == 0 ) ;
198 }
199
200
201
202 /************************* Options table ***********************************
203 * The complete options table is built by constructOptions() according to the
204 * application. It is composed of the display options, (displayopts[], below),
205 * and the model option tables (from table.c) which are appropriate for the
206 * application. The sequence of processing stages, (and hence model option
207 * tables), for an application is determined by FindStage() in model.c.
208 *
209 * The complete options table is an array of Option structs.
210 * The Option struct is defined in options.h as:
211 *
212 * typedef struct {
213 * char *name ; The name of the option.
214 * char *defaultValue ; Default value.
215 * char **value ; Address of current value.
216 * char *comment ; Something to print when the user types "-help".
217 * short classification ; Type of option it is.
218 * } Option;
219 *
220 * The classification of options uses names defined in options.h:
221 * InputOption
222 * OutputOption
223 * InOutOption
224 * SilentOption
225 *
226 * Routines which access the option table:
227 * Note: Some routines are called to supply arguments to other routines.
228 * Routines which access the option table in some way are denoted (*).
229 * Most of these routines are defined in options.c.
230 *
231 * main()
232 * |
233 * +-----------------+-----------+----+-------+-----------------+
234 * | | | | |
235 * | | | ModeledSource() |
236 * | | | | |
237 * | | | checkForFile() |
238 * helpopts() | | | |
239 * | | +---+---+ |
240 * | | | |
241 * | getopts() readopts() writeopts()
242 * | | | |
243 * | getnopts(*) readnopts() writenopts(*)
244 * | [arg countOptions(*)] [arg countOptions(*)] [arg countOptions(*)]
245 * | | | |
246 * | +-------+------+ | countBytesToWrite(*)
247 * | | | | |
248 * | | | +------+------+
249 * | | | |
250 * | | | processOptionFile()
251 * | | | |
252 * | | +------+------+
253 * | | |
254 * | | LookUpAndStore(*)
255 * | | |
256 * | | +---+---+----------+
257 * | | | | |
258 * | +-----+----+ LookUp(*) Ambiguity(*)
259 * | | |
260 * +----+----+ updateOptionsFile(*)
261 * |
262 * defaultHelpHandler(*)
263 *
264 *
265 * getopts()
266 * Operates on the options table given to it as an argument.
267 * a) Each "value" field is initialized to its "defaultValue" field.
268 * b) The "value" fields are re-initialized by any corresponding values found
269 * in the options ("rc") file, (overriding the "defaultValue").
270 * c) The "value" fields are re-initialized again by any corresponding values
271 * found in command-line arguments.
272 * d) Special arguments are dealt with:
273 * "help" calls the onLineHelpHandler() routine, (see below).
274 * "update" calls the updateOptionsFile() routine.
275 * e) Return the remainder of the command-line (argc and argv) for use in
276 * main().
277 *
278 * helpopts()
279 * Is called to print the help menu if no input file has been found by
280 * getopts(), (in the "rc" file), and none remains on the command-line.
281 * An alias for the onLineHelpHandler() function, which is in turn an
282 * alias for the defaultHelpHandler() routine, (see options.c).
283 *
284 * readopts()
285 * Read any options header which may be at the start of the input file.
286 * Interpret the header like an options ("rc") file, and re-initialize any
287 * corresponding "value" fields in the given options table, (as in getopts()).
288 * Skip to the start of the input data, allowing for any offset (ie startstr).
289 *
290 * writeopts()
291 * Write the given options table as an options header at the start of an o/p
292 * file, if the "header" option is "on".
293 *
294 ****************************************************************************/
295
296 static Option *options;
297
298 /******************** Display options table ********************************
299 * Options table for application display parameters.
300 ****************************************************************************/
301
302 static Option displayopts[] = {
303
304 /* Miscellaneous Silent Parameters (hidden from users) */
305
306
307 { "Version", headerstr, &versionstr, "Version number and date", OutputOption},
308
309 { "test1", "0", &test1str, "Dummy option for test and development", SilentOption},
310 { "test2", "0", &test2str, "Dummy option for test and development", SilentOption},
311 { "test3", "0", &test3str, "Dummy option for test and development", SilentOption},
312 { "test4", "0", &test4str, "Dummy option for test and development", SilentOption},
313
314 { "linear_sgm", OffOption, &linstr, "Linear frequency axis for spectrograms",SilentOption},
315 { "useprevious", OffOption, &reusestr, "Use previously stored output", SilentOption},
316
317 /* MAA: 21-8-1993
318 * These next two options are here, because otherwise "gensgm -use ..." (at least) core dumps.
319 */
320 { "framenumber", OffOption, &framenumberstr, "Index of current frame (to stderr)\n", SilentOption},
321 { "review", OffOption, &reviewstr, "Wait for keyboard <return> between frames",SilentOption},
322
323 #ifdef X11
324 { "pstofile", OffOption, &psfilestr, "Send PostScript output to .ps file", SilentOption},
325 { "invert", OffOption, &invertstr, "Invert axis of sai image", SilentOption},
326 { "fast", OffOption, &kludgestr, "Speed up image generation", SilentOption},
327 #endif /* X11 */
328
329 /* ( The order of the "help" option members is strange due to the way */
330 /* it was originally used. See options.c: defaultHelpHandler() and */
331 /* updateOptionsFile() ). */
332
333 /* Input Parameters */
334
335 { "envelope", OffOption, &envstr, "Type of model to use required", SilentOption},
336 { "help", "not used", &helpstr, helpstring, SilentOption},
337
338 #ifdef X11
339
340 /* Screen Output Parameters */
341
342 { "title", "filename", &titlestr, "Title of picture, or input filename", InputOption},
343 #ifdef THINK_C
344 { "x0_win", "10", &xstr, "Left edge of window (pixels)", InOutOption},
345 { "y0_win", "50", &ystr, "Lower edge of window (pixels)", InOutOption},
346 #else
347 { "x0_win", CenterStr, &xstr, "Left edge of window (pixels)", InOutOption},
348 { "y0_win", CenterStr, &ystr, "Lower edge of window (pixels)", InOutOption},
349 #endif
350 #ifdef PC
351 { "width_win", "400", &widthstr, "Window width (pixels)", InOutOption},
352 { "height_win", "300", &heightstr, "Window height (pixels)\n", InOutOption},
353 #else /* UNIX */
354 { "width_win", "540", &widthstr, "Window width (pixels)", InOutOption},
355 { "height_win", "400", &heightstr, "Window height (pixels)\n", InOutOption},
356 #endif
357 { "display", OnOption, &dispstr, "Select display of output image", InOutOption},
358 { "view", LandStr, &viewstr, "Select display format", InOutOption},
359 { "top", "1024", &topstr, "Maximum of plotted range", InputOption},
360 { "bottom", "-1024", &botstr, "Minimum of plotted range", InputOption},
361 { "overlap", "50%", &overstr, "Overlap between channels", SilentOption}, /* AJD 16-5-95 */
362 { "headroom", "0%", &roomstr, "Headroom at top of picture", SilentOption}, /* AJD 16-5-95 */
363 { "magnification", "1", &magstr, "Magnification of image in display", InputOption},
364 { "pensize", "1", &penstr, "Size of plotted lines and dots", InputOption},
365 { "hiddenline", OnOption, &hiddenstr, "Hidden line removal\n", InputOption},
366 { "perspective", "0", &tiltstr, "Perspective view of display (degrees)\n", SilentOption}, /* AJD 16-5-95 */
367 #endif /* X11 */
368
369 { "downchannel", OffOption, &downcstr, "Average adjacent frequency channels\n", InOutOption},
370
371 #ifdef X11
372
373 /* Auditory image cartoon parameters */
374
375 { "erase_ctn", OnOption, &erasestr, "Erase display between cartoon frames", InOutOption},
376 { "animate_ctn", OffOption, &animstr, "Animate cartoon", InOutOption},
377 { "bitmap_ctn", OffOption, &bitmapstr, "Produce cartoon output (.ctn)\n", InputOption},
378 { "mono_ctn", OnOption, &monostr, "Force monochrome (single plane) cartoons.", SilentOption},
379 { "colour_ctn", OffOption, &colourstr, "Force colour (multi-plane) cartoons.", SilentOption},
380 {"planemask_ctn", "1", &planemaskstr, "Planemask for creating cartoons.\n", SilentOption},
381 {"fg_col", "black", &fgcolourstr, "Foreground Colour.\n", SilentOption},
382 {"bg_col", "white", &bgcolourstr, "Background Colour.\n", SilentOption},
383
384
385 /* Postscript options */
386
387 { "postscript", OffOption, &psstr, "Produce postscript output", InputOption},
388 { "rotateaxes", OffOption, &rotateaxesstr, "Rotate the axes labels in .ps output", SilentOption},
389 { "xstart_ps", "", &xstartstr, "Postscript x-axis: start point.", SilentOption},
390 { "xend_ps", "", &xendstr, "Postscript x-axis: end point.", SilentOption},
391 { "ystart_ps", "", &ystartstr, "Postscript y-axis: start point.", SilentOption},
392 { "yend_ps", "", &yendstr, "Postscript y-axis: end point.", SilentOption},
393 { "xtitle_ps", "", &xnewtitlestr, "Postscript x-axis: title.", SilentOption},
394 { "ytitle_ps", "", &ynewtitlestr, "Postscript x-axis: title.", SilentOption},
395 { "portrait_ps", "", &portraitstr, "Use 'portrait' page format", SilentOption},
396 { "landscape_ps", "", &landscapestr, "Use 'landscape' page format (overrides 'portriat)", SilentOption},
397 { "fontname_ps", "Helvetica", &fontnamestr, "Define font", SilentOption},
398 { "fontsize_ps", "12", &fontsizestr, "Define fontsize (points)", SilentOption},
399 { "fonttitlesize_ps", "0", &titlesizestr, "Define fontsize for title (points)", SilentOption},
400 { "axislinewidth_ps", "1", &axislinewidthstr, "Linewidth for axes & tickmarks (points)", SilentOption},
401 { "figurelinewidth_ps", "1", &figurelinewidthstr, "Linewidth for figures (points)", SilentOption},
402 { "xticks_ps", "6", &xticksstr, "Define size of x-axis (big) ticks (points)", SilentOption},
403 { "yticks_ps", "6", &yticksstr, "Define size of y-axis (big) ticks' (points)", SilentOption},
404 { "outsideticks_ps",OnOption, &outsidestr, "Print tick-marks 'outside' figure", SilentOption},
405 { "axistop_ps", OnOption, &axistopstr, "Print tick-marks on top side", SilentOption},
406 { "axisbottom_ps", OnOption, &axisbottomstr, "Print tick-marks on bottom side", SilentOption},
407 { "axisleft_ps", OnOption, &axisleftstr, "Print tick-marks on left side", SilentOption},
408 { "axisright_ps", OnOption, &axisrightstr, "Print tick-marks on right side", SilentOption},
409 { "xmajorticks_ps", "1", &xmajorticksstr, "Relative *spacing* of ticks", SilentOption},
410 { "xminorticks_ps", "1", &xminorticksstr, "Relative *spacing* of ticks", SilentOption},
411 { "ymajorticks_ps", "1", &ymajorticksstr, "Relative *spacing* of ticks", SilentOption},
412 { "yminorticks_ps", "1", &yminorticksstr, "Relative *spacing* of ticks", SilentOption},
413 { "box_ps", OnOption, &boxstr, "Plot a box", SilentOption},
414 #endif /* X11 */
415
416 /* File Output Parameters */
417 { "output", OffOption, &outstr, "Produce output file", InputOption},
418 { "header", OnOption, &headstr, "Add a header to the output file\n", InOutOption},
419 { "bytemax", "255", &bmaxstr, "Maximum value in byte output", SilentOption}, /* AJD 16-5-95 */
420 { "type", "short", &typestr, "Output data type\n", SilentOption}, /* AJD 16-5-95 */
421
422 { "input_wave", NullOption, &filestr, "Default input file name", InputOption},
423 { "start_wave", "0ms", &startstr, "Start point in wave (ms)", InputOption},
424 { "length_wave", LengthStr, &lengthstr, "Length of wave to process (ms)", InputOption},
425
426 ( char * ) 0 } ;
427
428
429 /*********************** Included from stitch directory ********************/
430
431 /* interfaces to stitch system */
432
433 #include "stitch.h"
434 #include "source.h"
435 #include "spiral.h"
436 #include "image.h"
437 #include "model.h"
438 #include "units.h"
439 #include "calc.h"
440 #include "ops.h"
441 #include "io.h"
442
443
444 #ifdef X11
445 #include "draw.h"
446 #include "fill.h"
447 #endif /* X11 */
448
449 /**************************************************************************/
450
451 char *AlterSuffix() ; /* alter suffix of file name. */
452 #ifdef X11
453 void save_frame(), plot_frame() ; /* draw callbacks. */
454 void fast_frame() ;
455 #endif /* X11 */
456
457 extern char *genstate() ;
458 static char *gen_state ;
459
460 Source DownChannel() ; /* reduce channels by averaging. */
461 #ifdef X11
462 Source PackShorts() ; /* pack output into one byte. */
463 #endif /* X11 */
464 Source checkForFile() ; /* create source from file if present. */
465
466 #define POSTSCRIPT_FILE_SUFFIX ".ps"
467 #define CARTOON_FILE_SUFFIX ".ctn"
468
469 #ifdef X11
470 static WindowObject display = 0 ;
471 #endif /* X11 */
472
473 /***************************************************************************/
474
475 /* Return length of the file in bytes */
476 static long fileLength( fp )
477 FILE *fp ;
478 {
479 long posn = ftell( fp ) ;
480 long length = 0 ;
481
482 if( fseek( fp, 0l, 2 ) == 0 ) {
483
484 length = ftell( fp ) ;
485
486 (void) fseek( fp, posn, 0 ) ;
487 }
488
489 return ( length ) ;
490 }
491
492 /* per frame image handling */
493
494 static FILE *inputFilePointer = ( FILE * ) 0 ;
495
496 #ifdef X11
497
498 static FILE *imageFilePointer = ( FILE * ) 0 ;
499 static int images = 0 ;
500 static void (*frame_drawer)() ;
501
502 /***** axis information *****/
503 /*
504 "Axis" is defined in windows.h:143
505 The postscript program for drawing axis stuff is in axis.h
506 */
507
508 static int Top()
509 {
510 return ( atof( topstr ) / atof( magstr ) + 0.5 ) ;
511 }
512
513 static int Bot()
514 {
515 if( atof( botstr ) < 0 )
516 return ( atof( botstr ) / atof( magstr ) - 0.5 ) ;
517 else
518 return ( atof( botstr ) / atof( magstr ) + 0.5 ) ;
519 }
520
521 static struct {
522 double min, max ;
523 char *label ;
524 } xaxis, yaxis ;
525
526
527
528 TimeAxis( min, max, label )
529 double *min, *max ;
530 char **label ;
531 {
532 *min = Samples( startstr, Samplerate() ) / Samplerate() ;
533 *max = Samples( startstr, Samplerate() ) / Samplerate() + Frames() * Framestep() / Samplerate() ;
534
535 if( *max > 1. )
536 *label = "Time [s]" ;
537 else {
538 *label = "Time [ms]" ;
539
540 *min *= 1000. ;
541 *max *= 1000. ;
542 }
543 }
544
545 MagnitudeAxis( min, max, label )
546 double *min, *max ;
547 char **label ;
548 {
549 *min = Bot() ;
550 *max = Top() / ( 1. - atof( headstr ) / 100. ) ;
551
552 *label = "Magnitude" ;
553 }
554
555
556 static void DrawAxes( win )
557 WindowObject win ;
558 {
559 /* frame window with axes */
560
561 Axes( win, titlestr, xaxis.min, xaxis.max, xaxis.label,
562 yaxis.min, yaxis.max, yaxis.label ) ;
563 return ;
564 }
565
566 #endif /* X11 */
567
568 /******************************* main **************************************
569 * The following tables are used extensively:
570 * stage table Arrays of _stage structs, ("envelope", "fine", etc.), defined
571 * in routine FindStage() in model.c.
572 * option table Array of Option structs built at run-time by
573 * constructOptions() from displayopts, (in gen.c), and tables of
574 * model options included from table.c.
575 *
576 * Compiler switches for model versions are:
577 * FLOAT For floating point version, (default uses integer arithmetic).
578 * Defined in calc.h.
579 *
580 * The model version number is the sccs <release-number>.<level-number> of
581 * the file version.c. Refer to that file for incrementing the version number.
582 * The version number is stored in versionstr in routine getversion().
583 ****************************************************************************/
584
585 int argc_save ;
586 char **argv_save ;
587
588 main( argc, argv )
589 int argc ;
590 char *argv[] ;
591 #ifdef THINK_C
592 {
593 static char *realargv[] = { "prog", "", 0 };
594 static char *progs = { "\pgenwav;-;\
595 genfbm;genfbr;genfbc;genfbt;genfbd;gensai;genspl;gensas;-;\
596 genbmm;gennap;gensai;-;gensgm;gencgm;gensas;-;genasa;genepn;gensep;-;Quit/Q" } ;
597
598 extern char *MacMenu(), *MacFile() ;
599
600 MacInit() ;
601
602 realargv[0] = MacMenu(progs) ;
603 realargv[1] = MacFile() ;
604
605 return ( real_main( sizeof( realargv ) / sizeof (*realargv) - 1, realargv ) ) ;
606 }
607
608 real_main( argc, argv )
609 int argc ;
610 char *argv[] ;
611 #endif
612 {
613 int i ;
614 FILE *ofp = 0 ;
615 Source source ;
616 char *which, *psfilename ;
617 char title[256] ;
618 char *programName ;
619 int x, y, pixels, image, time ;
620 long headerSize, fileFramebytes ;
621 double *frequency_scale ;
622 #ifdef X11
623 WindowObject psw = 0 ;
624 char *imageFileName ;
625 #endif /* X11 */
626
627 /**************************************************************************
628 * Determine which version of the model is required.
629 * Set "which" to the last three chars of the program name, (allowing for
630 * a ".exe" extension in the case of a PC version).
631 **************************************************************************/
632
633
634 programName = argv[0] ;
635
636 which = programName + strlen( programName ) - strlen( "xxx" ) ;
637
638 #ifdef PC
639 lowerArgs( argv, argc ) ;
640
641 which -= strlen( ".exe" ) ;
642 #endif
643
644
645 /***************************************************************************
646 * Process arguments, (the model options):
647 * Set option defaults (from option table in model.c).
648 * Then override these by any options in the options file,
649 * (the resource control file, eg .gensairc).
650 * Finally, override these by any options given as command-line arguments.
651 *
652 * offsetOptions() finds the first option, (a ptr to one line of the "res"
653 * array), required by the program. This gives a place mark in the options
654 * table. (Note that the bottom of the options table, a null, corresponds with
655 * the top of the help menu).
656 * This first option appropriate to the program is found by looking it up in
657 * the stage table (in model.c), and then cross-referencing the option name
658 * with the names in the options table.
659 *
660 * Here is an example of an option, showing the members of the Options struct:
661 * name: defaultValue: value: comment: classification:
662 * {"length_wave", LengthStr, &lengthstr, "Length of wave", InputOption},
663 *
664 * getopts() operates on the options between the given place mark and the
665 * bottom of the table.
666 * This is the only call to routine getopts(), which is defined in options.c.
667 * First, each "value" is set to its corresponding "defaultvalue".
668 * Then the options file (the "rc" file) is opened, and any options found there
669 * are assigned to the corresponding "value", (overriding the "defaultvalue").
670 * Then the command-line arguments are examined, and any options found there
671 * are assigned to the corresponding "value", (overriding again).
672 * Special arguments are dealt with:
673 * "help" calls the onLineHelpHandler() routine, (see below).
674 * "update" calls the updateOptionsFile() routine.
675 *
676 * Finally, leave the remainder of the command line (argc and argv).
677 * Anything left on the command line is interpreted as follows:
678 * "filestr" is the input data filename,
679 * "startstr" is the start point in the data,
680 * "lengthstr" is the amount of data to process,
681 * "whichstr" is the last 3 chars of the program name (the program version).
682 *
683 * Note that if no input file has been found by getopts(), (in the "rc" file),
684 * and none remains on the command line, then helpopts() is called.
685 * This is an alias for the onLineHelpHandler() function, which is in turn an
686 * alias for the defaultHelpHandler() routine, (see options.c).
687 *
688 *
689 ***************************************************************************/
690
691 getversion( programName ) ;
692
693 /* The helpstring, defined in model.c, is stored as the comment field */
694 /* of the help option (see table.c). It is accessed in options.c in */
695 /* defaultHelpHandler(), using options[help].comment. */
696
697 (void) sprintf( helpstring, " [file_name]\n Generates %s", modelHelp( which ) ) ;
698
699 options = constructOptions( which, displayopts ) ;
700
701
702 /* Hack to save argc and argv so they don't get mangled by getopts */
703 /* This is so the command line args can override a reused file header */
704
705 argc_save = argc ;
706 argv_save = (char **)malloc( ( argc + 1 ) * sizeof( char *) ) ;
707 for ( i = 0 ; i < argc ; i++ ) {
708 argv_save[i] = (char *)malloc( ( strlen( argv[i] ) + 1 ) * sizeof( char ) ) ;
709 strcpy( argv_save[i], argv[i] ) ;
710 }
711
712 getopts( options, &argc, &argv ) ;
713
714 if( argc == 0 && isNULL( filestr ) ) {
715 (void) helpopts( options, programName ) ;
716 stitch_exit( -1 ) ;
717 }
718
719 if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 )
720 filestr = *argv++ ;
721
722 if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 )
723 startstr = *argv++ ;
724
725 if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 )
726 lengthstr = *argv++ ;
727
728 if( isNULL( whichstr ) )
729 whichstr = which ;
730
731
732 /***************************************************************************
733 * horrrrrrrrible hack for now to try out -envelope option
734 ***************************************************************************/
735
736 if( isON( envstr ) )
737 if( whichstr[1] == 'b' )
738 whichstr[1] = 'e' ;
739 else {
740 /* map sai to sie and sas to sse */
741
742 whichstr[1] = whichstr[2] ;
743 whichstr[2] = 'e' ;
744 }
745
746
747 /***************************************************************************
748 * hack test arguments
749 ***************************************************************************/
750 #if 00
751 test1 = atof( test1str ) ;
752 test2 = atof( test2str ) ;
753 test3 = atof( test3str ) ;
754 test4 = atof( test4str ) ;
755 #endif
756
757 /***************************************************************************
758 * Open input data file, (use stdin if filename "-" is given).
759 ***************************************************************************/
760
761 if( strcmp( filestr, "-" ) == 0 )
762 inputFilePointer = stdin ;
763 else
764 inputFilePointer = fopen( filestr, readBinary ) ;
765
766 /***************************************************************************
767 * Position input data file pointer correctly:
768 * Read any options header at the start of the input file. Set any options.
769 * Skip to the start of the input data, allowing for any offset (ie startstr).
770 * Set "framesstr" to the number of frames in the input data file, (here this
771 * means the number of shorts remaining in the input file).
772 * Create a source for the input data file.
773 * Re-set "framesstr" to allow for a given "lengthstr", (ie not the whole file).
774 ***************************************************************************/
775
776 if( inputFilePointer != (FILE *) 0 ) {
777
778 readopts( options, inputFilePointer ) ;
779
780 headerSize = ftell( inputFilePointer ) ;
781
782 setFrames( fileLength( inputFilePointer ) / sizeof ( short ) - (long) Samples( startstr, Samplerate() ) ) ;
783
784 (void) fseek( inputFilePointer, (long)( headerSize + (long) Samples( startstr, Samplerate() ) * sizeof ( short ) ), 0 ) ;
785
786 source = FileSource( inputFilePointer ) ;
787 }
788
789 /* If a specific processing amount is specifed (other than "remainder") */
790 /* and this amount is less than the remainder of the input file, then */
791 /* override the amount of data to process, (in framesstr). */
792
793 if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) != 0 &&
794 Samples( lengthstr, Samplerate() ) < Frames() )
795 setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ;
796
797
798 /***************************************************************************
799 * Create source with data derived from processing file through model.
800 * This may involve several stages of callback, and will initialize a chain of
801 * objects which will ultimately execute the program, (see SinkSource() below).
802 * If reusestr in "on", the "useprevious" option will use a previously
803 * generated file, (see checkForFile() routine below).
804 * If no input data file is found, report error: "could not open file".
805 *
806 * The routine ModeledSource() first uses Findstage() to find the appropriate
807 * place in the stage table called for by the program, (see model.c).
808 * Then it finds the end of the stage table, and works back up the table to
809 * the stage called for by the program. Each stage in the table is a process
810 * on the way to the program as a whole. The order of the stage table sets the
811 * order of processing.
812 * Immediately below are the only two calls to routine ModeledSource().
813 ***************************************************************************/
814
815 if( isON( reusestr ) )
816 source = ModeledSource( source, checkForFile ) ;
817 else
818 if( inputFilePointer != (FILE *) 0 )
819 source = ModeledSource( source, (Source ( * )()) 0 ) ;
820
821 if( inputFilePointer == (FILE *) 0 )
822 stitch_error( "Could not open file \"%s\" for input\n", filestr ) ;
823
824 /***************************************************************************
825 * If the "downchannel" option is on, reduce channels by averaging.
826 * (See DownChannel() routine below).
827 * Then updateFramebytes sets "framebytesstr" to the total number of bytes
828 * in each frame, (ie the new width * height).
829 ***************************************************************************/
830
831
832 for( time=0 ; time<OptionInt( downcstr ) ; time++ ) {
833 source = DownChannel( source, Frameheight() ) ;
834 setFrameheight( Frameheight() / 2 ) ;
835 }
836 updateFramebytes() ;
837
838 #if 0 /* for debugging */
839 fprintf( stderr, "%d %d %d %d %ld\n",
840 Framewidth(),
841 Frameheight(),
842 Framebytes(),
843 Framestep(),
844 Frames() ) ;
845 #endif
846
847 /***************************************************************************
848 * From here on is concerned with setting up for output, then starting the
849 * processing, and finally cleaning up.
850 ***************************************************************************/
851
852 #ifdef X11
853 /* First sort out window placement. */
854
855 if( strcmp( xstr, CenterStr ) == 0 )
856 x = -1 ;
857 else
858 x = atoi( xstr ) ;
859
860 if( strcmp( ystr, CenterStr ) == 0 )
861 y = -1 ;
862 else
863 y = atoi( ystr ) ;
864
865 if( isGREYSCALE( viewstr ) )
866 pixels = 0 ;
867 else {
868 pixels = atoi( penstr ) ;
869
870 if( isON( hiddenstr ) && Frameheight() > 1 )
871
872 pixels = -abs( pixels ) ;
873
874 /* Convert arguments for line-drawing. See draw.ch */
875 drawTilt = atof( tiltstr ) ;
876 drawDistance = atof( diststr ) ;
877 drawHeadroom = atof( roomstr ) ;
878 drawOverlap = atof( overstr ) / 100. ;
879 #ifdef mips
880 if( pixels == 0 )
881 pixels = 1 ;
882 #endif
883 }
884 #endif /* X11 */
885
886 /* work out title of output */
887
888 (void) strcpy( title, filestr ) ;
889 (void) strcat( title, "." ) ;
890 (void) strncat( title, whichstr, strlen( "xxx" )+1 ) ;
891
892 #ifdef X11
893
894 if( strcmp(titlestr,"filename") == 0) /* was: if(isNULL(titlestr)) */
895 titlestr = title ;
896
897 /* calculate axis information */
898
899 if( isEXCITE( viewstr ) ) {
900 ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
901 MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
902 }
903 else if( isWATERFALL( viewstr ) ) {
904 ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
905 TimeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
906 } /* landscape ones */
907 else if( Framewidth() > 1 ) {
908 DelayAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
909 ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
910 }
911 else {
912 TimeAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
913
914 if( Frameheight() > 1 )
915 ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
916 else
917 MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
918
919 }
920
921
922 /* select outputs... */
923
924
925 /* select sai drawing method */
926
927 /* Hack so spiral parameters are independent of stage and option order */
928 /* (Spiral parameters appear late in options list, so are not known */
929 /* when an earlier stage is specified. So don't process unless sai). */
930
931 if( strncmp(whichstr,"spl",strlen("spl")) == 0 ) {
932
933 frame_drawer = draw_spiral;
934
935 dotthresh_spl = Top() ;
936 dotsize_spl = OptionInt( penstr ) ;
937 }
938 else
939 frame_drawer = draw_frame;
940
941 /* screen output first */
942 /* (set by option: display=on) */
943
944 if( isON( dispstr ) ) {
945
946 display = newDisplayWindow( titlestr, x, y, atoi( widthstr ), atoi( heightstr ), pixels ) ;
947
948 if( !isGREYSCALE( viewstr ) /* && OptionInt( penstr ) != 0 */ ) {
949
950 if( Top() == Bot() )
951 stitch_error( "error: display top and bottom parameters the same value\n" );
952
953 if( isEXCITE( viewstr ) )
954 source = SourceDraw( source, Bot(), Top(), display, Frameheight(), 1, Nwidth(), Frames(), save_frame, frame_drawer ) ;
955 else if( isWATERFALL( viewstr ) )
956 source = SourceDraw( source, Bot(), Top(), display, Frameheight(), Frames(), Nwidth(), 1, save_frame, frame_drawer ) ;
957 else if( !isON( kludgestr ) )
958 source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, frame_drawer ) ;
959 else { /* speed-up for sai */
960 source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, fast_frame ) ;
961 gen_state = genstate( display, Bot(), Top(), Framewidth(), Frameheight(), Nwidth(), Frames(), pixels ) ;
962 frame_drawer=fast_frame ;
963 }
964 }
965 else {
966 if( isON( erasestr ) )
967 Clear( display ) ;
968
969 DrawAxes( display ) ;
970
971 if( isON( linstr ) )
972 frequency_scale = frequencies ;
973 else
974 frequency_scale = (double *) 0 ;
975
976 if( Framewidth() > 1 )
977 source = FillDown( display, source, Top(), Bot(), Framewidth(), Frameheight() ) ;
978 else
979 source = fillAcross( display, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ;
980 }
981 }
982
983 /* postscript output next */
984 /* (set by option: postscript=on) */
985
986 if( isON( psstr ) ) {
987
988 if( isON( psfilestr ) )
989 psfilename = AlterSuffix( filestr, POSTSCRIPT_FILE_SUFFIX ) ;
990 else
991 psfilename = (char *) 0 ;
992
993 /* the extra argument to newPSWindow. MAA> 27-1-1993. */
994 psw = newPSWindow( psfilename, x, y, atoi(widthstr), atoi(heightstr), atoi( penstr ), isON( hiddenstr ) );
995
996 if( !isGREYSCALE( viewstr ) && OptionInt( penstr ) != 0 ) {
997
998 if( isEXCITE( viewstr ) )
999 source = SourceDraw( source, Bot(), Top(), psw, Frameheight(), 1, Nwidth(), Frames(), plot_frame, frame_drawer ) ;
1000 else if( isWATERFALL( viewstr ) )
1001 source = SourceDraw( source, Bot(), Top(), psw, Frameheight(), Frames(), Nwidth(), 1, plot_frame, frame_drawer ) ;
1002 else
1003 source = SourceDraw( source, Bot(), Top(), psw, Framewidth(), Frameheight(), Nwidth(), Frames(), plot_frame, frame_drawer ) ;
1004 }
1005 else { /* greyscale displays */
1006
1007 if( isON( erasestr ) )
1008 Clear( psw ) ;
1009
1010 DrawAxes( psw ) ;
1011
1012 if( isON( linstr ) )
1013 frequency_scale = frequencies ;
1014 else
1015 frequency_scale = (double *) 0 ;
1016
1017 if( Framewidth() > 1 )
1018 source = FillDown( psw, source, Top(), Bot(), Framewidth(), Frameheight() ) ;
1019 else
1020 source = fillAcross( psw, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ;
1021 }
1022 }
1023
1024
1025 if( strcmp( typestr, "char" ) == 0 ) {
1026 source = PackShorts( source ) ;
1027 fileFramebytes = Framebytes() / sizeof ( short ) * sizeof ( char ) ;
1028 }
1029 else
1030
1031 #endif /* X11 */
1032
1033 fileFramebytes = Framebytes() ;
1034
1035 /* output to file */
1036
1037 if( !isOFF( outstr ) ) {
1038
1039 (void) unlink( title ) ;
1040
1041 if( OptionStringsEqual( outstr, OnOption ) )
1042 ofp = fopen( title, writeBinary ) ;
1043 else {
1044 if( strcmp( outstr, "stdout" ) == 0 )
1045 ofp = stdout;
1046 else
1047 ofp = fopen( outstr, writeBinary ) ;
1048 }
1049
1050 if( ofp == (FILE *) 0 )
1051 stitch_error( "Unable to open file %s for output\n", title ) ;
1052 else {
1053 if( isON( headstr ) )
1054 writeopts( options, ofp ) ;
1055
1056 source = FileTap( source, ofp ) ;
1057 }
1058 }
1059
1060 #ifdef X11
1061
1062 /* output of screen "image" files in display format */
1063 if( !isOFF( bitmapstr ) ) {
1064 imageFileName = AlterSuffix(filestr, CARTOON_FILE_SUFFIX ) ;
1065
1066 if( (strcmp( bitmapstr, "stdout" ) == 0 )){
1067 imageFilePointer = stdout;
1068 writeopts( options, imageFilePointer ) ;}
1069 else
1070 if ( ( imageFilePointer = fopen(imageFileName, writeBinary ) ) == (FILE *) 0)
1071 stitch_error( "Unable to open file %s for image output\n", imageFileName ) ;
1072 else
1073 writeopts( options, imageFilePointer ) ;}
1074
1075 if (( ofp == stdout ) && ( imageFilePointer == stdout ))
1076 stitch_error( "Both 'output' and 'bitmap' set to stdout.\n", title);
1077
1078 #endif /* X11 */
1079
1080
1081 /***************************************************************************
1082 * Execute the program by pulling data from the source.
1083 * This is the only call to routine SinkSource(), which is defined in
1084 * stitch/source.c as sinkSource().
1085 * (SinkSource is an alias, defined in stitch/source.h, to cast the arguments).
1086 * Routine sinkSource() executes: "(void) Pull( source, fileFramebytes ) ;"
1087 * for "Frames()" times in succession.
1088 * A chain of source objects, linked by callback-function pointers, was setup
1089 * earlier, (see call to ModeledSource() above).
1090 ***************************************************************************/
1091
1092
1093 SinkSource( source, fileFramebytes, Frames() ) ;
1094
1095
1096 /***************************************************************************
1097 * Clean up and close
1098 ****************************************************************************/
1099
1100 CloseSource( source ) ;
1101
1102 if( ofp != (FILE *) 0 )
1103 (void) fclose( ofp ) ;
1104
1105 #ifdef X11
1106
1107 if( psw != (WindowObject) 0 )
1108 Close( psw ) ;
1109
1110 if( display != (WindowObject) 0 ) {
1111
1112 /* animate sai's if selected */
1113
1114 do
1115 {
1116 for( image=1 ; image <= images ; image++ )
1117 for( time = OptionInt( animstr ) ; time>0 ; time-- )
1118 Recall( display, image ) ;
1119
1120 if( Pause( display ) == 'q' )
1121 break;
1122
1123 } while( isON( animstr ) ) ;
1124
1125 Close( display ) ;
1126 }
1127
1128 #endif /* X11 */
1129
1130 stitch_exit( 0 ) ;
1131 }
1132
1133 /*************************** End main *************************************/
1134
1135 /***************************************************************************
1136 * checkForFile()
1137 * Create source from file if present, to be used if reusestr in "on".
1138 * This is the "useprevious" option to use previously generated files.
1139 ***************************************************************************/
1140
1141 Source checkForFile( which )
1142 char *which ;
1143 {
1144 static Source noSource = { (struct _source *) 0 } ;
1145 long headerSize, fileFramebytes ;
1146 char file_name[200] ;
1147 FILE *tmp ;
1148
1149 (void) strcpy( file_name, filestr ) ;
1150 (void) strcat( file_name, "." ) ;
1151 (void) strcat( file_name, which ) ;
1152
1153 if( ( tmp = fopen( file_name, readBinary ) ) != ( FILE * ) 0 ) {
1154
1155 inputFilePointer = tmp ;
1156
1157 (void) fprintf( stderr, "Using existing file \"%s\"\n", file_name ) ;
1158
1159 readopts( options, inputFilePointer ) ;
1160
1161 /* the saved command line overrides options from file header */
1162
1163 if( isON( reusestr ) )
1164 cmd_line_opts( options, &argc_save, &argv_save ) ;
1165
1166 headerSize = ftell( inputFilePointer ) ;
1167
1168 if( strcmp( typestr, "char" ) == 0 )
1169 fileFramebytes = Framebytes() / 2 ;
1170 else
1171 fileFramebytes = Framebytes() ;
1172
1173 /*
1174 If length=remainder then use the whole file.
1175 Otherwise the length of the reused file is that given on the command
1176 line, or the default length (if no length option is given).
1177 */
1178
1179 if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) == 0 )
1180 setFrames( ( fileLength( inputFilePointer ) - headerSize ) / fileFramebytes - (long) Samples( startstr, Samplerate() ) / Framestep() ) ;
1181 else
1182 setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ;
1183
1184
1185 (void) fseek( inputFilePointer, headerSize + (long) Samples( startstr, Samplerate() ) / Framestep() * fileFramebytes, 0 ) ;
1186
1187 #ifndef PC
1188 if( strcmp( typestr, "char" ) == 0 )
1189 return( CharShortSource( FileSource( inputFilePointer ) ) ) ;
1190 else
1191 #endif
1192 return( FileSource( inputFilePointer ) ) ;
1193 }
1194 else
1195 return( noSource ) ;
1196 }
1197
1198 /***************************************************************************
1199 * AlterSuffix().
1200 * Returns its argument fileName with a newSuffix appended in place of
1201 * any previous suffix it may have had. It should be noted that this
1202 * suffix must include any DOT it wishes to have appended to the name.
1203 ***************************************************************************/
1204
1205 /* File Name Suffix Conversion Parameters */
1206
1207 #define BACKSLASH_CHAR '\\'
1208 #define SLASH_CHARACTER '/'
1209 #define NULL_CHARACTER '\000'
1210 #define DOT_CHARACTER '.'
1211
1212 char *AlterSuffix(fileName, newSuffix)
1213 char *fileName, *newSuffix;
1214 {
1215 char *temp, *temp2, *lastPart;
1216 #if defined( PC )
1217 int i;
1218 #endif
1219
1220 temp = stitch_malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1), "AlterSuffix" );
1221
1222 temp = strcpy(temp, fileName);
1223
1224 #if defined(PC)
1225 /* Change all backslashes to forward slashes */
1226 for (i = 0; temp[i] != NULL_CHARACTER; i++)
1227 if (temp[i] == BACKSLASH_CHAR)
1228 temp[i] = SLASH_CHARACTER;
1229 #endif
1230
1231 if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL)
1232 lastPart = temp;
1233 else
1234 lastPart++; /* Skip over the actual "/" */
1235
1236 /* lastPart points to the tail name of the path */
1237
1238 if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL)
1239 temp = strcat(temp, newSuffix);
1240 else
1241 temp2 = strcpy(temp2, newSuffix);
1242
1243 return (temp);
1244 }
1245
1246 #ifdef X11
1247
1248 /***************************************************************************
1249 * Interceptions for various combinations of drawing.
1250 * An "interception function" is a function inserted into a chain a functions
1251 * linked by function pointers. The inserted function "intercepts" the
1252 * processing, to perform some transformation.
1253 ****************************************************************************/
1254
1255 /* intercept draw to store images for animation */
1256
1257 void save_frame( state, frame, first )
1258 struct _draw_state *state ;
1259 short *frame ;
1260 int first ;
1261 {
1262 if( first ) {
1263 if( isON( erasestr ) )
1264 Clear( state->window ) ;
1265
1266 if( frame_drawer != (void (*)()) draw_spiral && state->framenumber == 1 )
1267 DrawAxes( state->window ) ;
1268 }
1269
1270 frame_drawer( state, frame ) ;
1271
1272 if( isON( animstr ) && isOFF( kludgestr ) )
1273 if( Store( state->window ) )
1274 ++images ;
1275
1276 if( isON( bitmapstr ) )
1277 Write( state->window, imageFilePointer ) ;
1278
1279 return ;
1280 }
1281
1282 /* hacky but effective faster frame drawing routine - for sai only! */
1283
1284 void fast_frame( state, frame, first )
1285 struct _draw_state *state ;
1286 short *frame ;
1287 int first ;
1288 {
1289 if( isON( animstr ) || images == 0 )
1290 if( Store( state->window ) )
1291 ++images ;
1292
1293 /* generate image in current cleared image */
1294
1295 generate( gen_state, frame ) ;
1296
1297 /* then recal the window using the modified image */
1298
1299 Recall( state->window, images );
1300
1301 return ;
1302 }
1303
1304 /* intercept plot to check if page should be output for printing */
1305
1306 static int plot_wanted( state )
1307 struct _draw_state *state ;
1308 {
1309 #if !defined(PC)
1310 if( display != ( WindowObject ) 0 && state->framewidth > 1 && state->frames > 1 ) {
1311 (void) fprintf(stderr, "Hit \"y\" to include this image in the PostScript file: ");
1312
1313 switch ( Pause( display ) ) {
1314
1315 case 'y' : case 'Y' :
1316 case 'p' : case 'P' :
1317 return 1 ;
1318
1319 default :
1320 return 0 ;
1321 }
1322 }
1323 #endif
1324 return 1 ;
1325 }
1326
1327 void plot_frame( state, frame, first )
1328 struct _draw_state *state ;
1329 short *frame ;
1330 int first ;
1331 {
1332 int centering = state->window->entries->x( state->window ) < 0 &&
1333 state->window->entries->y( state->window ) < 0 ;
1334
1335 if( isOFF( erasestr ) || state->framewidth == 1 || plot_wanted( state ) ) {
1336
1337 if( first && ( state->framenumber == 1 || isON( erasestr ) ) ) {
1338 /* *** if( centering ) *** removed the conditional. M.Akeroyd. 22-1-1993.*/
1339 Clear( state->window ) ;
1340
1341 if( frame_drawer != (void (*)()) draw_spiral )
1342 DrawAxes( state->window ) ;
1343 }
1344
1345 frame_drawer( state, frame ) ;
1346 }
1347
1348 return ;
1349 }
1350
1351 #endif /* X11 */
1352
1353 /***************************************************************************
1354 * downchannel: average across channels for output (with special sai version)
1355 ***************************************************************************/
1356
1357 struct _down_channel_state {
1358 struct _fillable_source parent ;
1359 int channels ;
1360 Source input ;
1361 } ;
1362
1363
1364 static Pointer down_channel_callback( state, bytes, buffer )
1365 struct _down_channel_state *state ;
1366 ByteCount *bytes ;
1367 short *buffer ;
1368 {
1369 register int last = *bytes == 0 ;
1370 register int chan, outchans = state->channels >> 1 ;
1371 long frame, frames = ToPoints( short, *bytes ) / outchans ;
1372 register short *iptr = PullItems( state->input, frames * state->channels, short ) ;
1373 register short *bptr = buffer ;
1374
1375 for( frame=0 ; frame<frames ; frame++ ) {
1376 for( chan=0 ; chan<outchans ; chan++ )
1377 *bptr++ = ( *iptr++ + *iptr++ ) / 2 ;
1378
1379 if( ( outchans << 1 ) != state->channels )
1380 iptr++ ;
1381 }
1382
1383 if( !last )
1384 return ( (Pointer) buffer ) ;
1385 else
1386 return ( DeleteFillableSource( state ) ) ;
1387 }
1388
1389 static Pointer down_channel_callback_sai( state, bytes, buffer )
1390 struct _down_channel_state *state ;
1391 ByteCount *bytes ;
1392 short *buffer ;
1393 {
1394 register int last = *bytes == 0 ;
1395 register int chan, outchans = state->channels >> 1 ;
1396 long frame, frames = ToPoints( short, *bytes ) / outchans ;
1397 register short *iptr = PullItems( state->input, frames * state->channels, short ) ;
1398 register short *bptr = buffer ;
1399 register short *iptr2 ;
1400
1401 iptr2 = iptr + frames ;
1402 for( chan=0 ; chan<outchans ; chan++ ) {
1403 for( frame=0 ; frame<frames ; frame++ )
1404 *bptr++ = ( *iptr++ + *iptr2++ ) / 2 ;
1405 }
1406
1407 if( !last )
1408 return ( (Pointer) buffer ) ;
1409 else
1410 return ( DeleteFillableSource( state ) ) ;
1411 }
1412
1413
1414 Source DownChannel( source, channels )
1415 Source source ;
1416 {
1417 DeclareNew( struct _down_channel_state *, state ) ;
1418
1419 state->channels = channels ;
1420 state->input = source ;
1421
1422
1423 /* Hack for special-case downchannel routine to handle format of sai and spl frames (mha: 22/6/93) */
1424
1425 if( strncmp(whichstr,"sai",strlen("sai")) == 0 ||
1426 strncmp(whichstr,"spl",strlen("spl")) == 0 )
1427
1428 return ( SetFillableSource( state, down_channel_callback_sai, "down channeling sai frames" ) ) ;
1429
1430 return ( SetFillableSource( state, down_channel_callback, "down channeling" ) ) ;
1431 }
1432
1433
1434 #ifdef X11
1435
1436 /***************************************************************************
1437 * Pack model output onto a single byte if required,
1438 * using greyscale Top() from display.
1439 ***************************************************************************/
1440
1441 typedef struct { struct _fillable_source parent ; Source input ; } *PackSource ;
1442
1443 static Pointer pack_callback( state, bytes, buffer )
1444 PackSource state ;
1445 ByteCount *bytes ;
1446 Pointer buffer ;
1447 {
1448 register int last = *bytes == 0 ;
1449 register short *iptr = PullShorts( state->input, *bytes ) ;
1450 register Pointer optr = buffer ;
1451 register Pointer eptr = buffer + *bytes ;
1452 register int bytemax = atoi( bmaxstr ) ;
1453 register int max = Top() ;
1454 register int min = Bot() ;
1455
1456 while( optr < eptr )
1457 if( *iptr > max ) {
1458 *optr++ = bytemax ;
1459 iptr++ ;
1460 }
1461 else if( *iptr < min ) {
1462 *optr++ = 0 ;
1463 iptr++ ;
1464 }
1465 else
1466 *optr++ = ( ( ( *iptr++ - min ) * bytemax + ( bytemax >> 1 ) ) / ( max - min ) ) & 0xff ;
1467
1468 if( !last )
1469 return ( buffer ) ;
1470 else
1471 return ( DeleteFillableSource( state ) ) ;
1472 }
1473
1474
1475 Source PackShorts( input )
1476 Source input ;
1477 {
1478 DeclareNew( PackSource, source ) ;
1479
1480 source->input = input ;
1481
1482 return ( SetFillableSource( source, pack_callback, "gen.c packing" ) ) ;
1483 }
1484
1485 #endif /* X11 */
1486
1487 /***************************************************************************/
1488
1489 #ifdef PC
1490 static lowerArgs( argv, argc )
1491 char **argv ;
1492 int argc ;
1493 {
1494 register char *ptr ;
1495 register int arg ;
1496
1497 for( arg=0 ; arg<=argc ; arg++ )
1498 for( ptr=argv[arg] ; *ptr != '\000' ; ptr++ )
1499 if( isupper( *ptr ) )
1500 *ptr = tolower( (int) *ptr ) ;
1501 return ;
1502 }
1503 #endif
1504
1505
1506 /***************************************************************************
1507 * Set the value of versionstr to the model version number and current time.
1508 * The version number is the sccs <release-number>.<level-number> of the file
1509 * version.c. The current time is returned by ctime(time(0)).
1510 * This routine initializes the default version-string (headerstr), which is
1511 * later copied into the version-string (versionstr) during getopts().
1512 * In this way, the version-string is available for output at the head of
1513 * the help and the options (rc) files, and also output as part of the header,
1514 * (when output=on).
1515 * Note, the versionstr has to be quoted, otherwise the routine
1516 * processOptionFile in options.c will report an error (Detected Trailing...)
1517 * when it finds blanks within a line. This happens when trying to read an
1518 * options file, for example when reviewing. The addition of quotes enables
1519 * a line containing blanks to be read complete by the subroutine getName.
1520 ***************************************************************************/
1521
1522 #include "version.c"
1523
1524 getversion( name )
1525 char *name ;
1526 {
1527 char releasestr[8] ;
1528 char levelstr[8] ;
1529 char timestr[32] ;
1530 char *namestr ;
1531 long int timeval ;
1532
1533 sprintf(releasestr, "%d", atoi( version_Id ) ) ;
1534 sprintf(levelstr, "%d", atoi( version_Id + strlen(releasestr) + 1 ) ) ;
1535
1536 if ( ( namestr = strrchr( name, '/' ) ) == (char *)0 ) namestr = name ;
1537 else namestr++ ;
1538
1539 #if defined( PC ) || defined( THINK_C )
1540 sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s]\"", releasestr, levelstr, namestr ) ;
1541 #else
1542 timeval = time(0);
1543 sprintf(timestr,"%s", ctime(&timeval) ) ;
1544 timestr[strlen(timestr) - 1] = '\0'; /* remove newline */
1545 sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s] %s\"", releasestr, levelstr, namestr, timestr ) ;
1546 #endif
1547
1548 }