Mercurial > hg > aim92
comparison model/model.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 model.c | |
19 ===== | |
20 | |
21 APU, ASP model demonstration program. | |
22 | |
23 | |
24 Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit. | |
25 | |
26 | |
27 Author : John Holdsworth | |
28 Written : 22th March, 1989. | |
29 | |
30 Edited : Mike Allerhand, 1990. | |
31 | |
32 Edited : Roy Patterson, 1992. Changed default values from time to time. | |
33 | |
34 Edited : MAA 10th June 1993 | |
35 Allowed pwidth=0 | |
36 | |
37 Edited : Christian Giguere, March 1994. | |
38 - Added tools for manipulating sampling rate and scaling data | |
39 - Added in an Entry Point for the outer/middle ear function | |
40 - Added in an Entry Point for the transmission line filterbank | |
41 - Implemented a completely new version of Meddis(). | |
42 Files "haircell.h, haircell.c " | |
43 - Changed option "scale_at" into "gain_at". | |
44 That option is now passed to newCorti() as a double instead of an integer | |
45 In Corti(), this meant multiplying *optr by state->scale | |
46 - Provided facilities to print filterbank information to stderr via | |
47 option info_afb. This supersedes option erbscale_afb. | |
48 - Changed some default values | |
49 - To locate changes, search for "CG" | |
50 | |
51 Edited : Jay Datta, November 1994. | |
52 Added the stcrit options. | |
53 | |
54 : Jay Datta, March 1995. | |
55 Added a function Nwidth() which returns the number | |
56 of sample points of the nwidth section of a SAI. | |
57 : Silenced ulim_sas and llim_sas. | |
58 : Changed trise_at default to 1000 from 10000. May, 1995. | |
59 : Changed trise_at default to 10000 from 1000. May, 1995. | |
60 : Separated nwidth and strobe lag by creating a new | |
61 option called stlag_ai. May, 1995. | |
62 | |
63 */ | |
64 | |
65 /*************************************************************************** | |
66 * This module contains: | |
67 * Routines to access or modify string values. | |
68 * Unit conversion routines. | |
69 * Model entry-point functions. | |
70 ****************************************************************************/ | |
71 | |
72 #include <string.h> | |
73 #include <stdio.h> | |
74 #include <math.h> | |
75 | |
76 #ifdef THINK_C | |
77 #include <stdlib.h> | |
78 #endif | |
79 | |
80 /* interfaces to stitch system */ | |
81 | |
82 #include "options.h" | |
83 | |
84 #include "stitch.h" | |
85 #include "source.h" | |
86 #include "funcs.h" | |
87 #include "units.h" | |
88 #include "calc.h" | |
89 #if defined( DSP32 ) || defined( PC ) | |
90 #include "oops.h" | |
91 #else | |
92 #include "ops.h" | |
93 #endif | |
94 #include "io.h" | |
95 | |
96 /* interface to model modules */ | |
97 | |
98 #include "gamma_tone.h" | |
99 #include "integrate.h" | |
100 #include "formulae.h" /* CG: removed haircell.h */ | |
101 #include "recurse.h" | |
102 #include "scales.h" | |
103 #include "spiral.h" | |
104 #include "model.h" | |
105 #include "corti.h" | |
106 #include "image.h" | |
107 #include "bank.h" | |
108 | |
109 /* interface to WDF module */ /* CG */ | |
110 | |
111 #include "formulae_tl.h" | |
112 #include "upsample.h" | |
113 #include "bank_tl.h" | |
114 #include "calc_tl.h" | |
115 #include "meddis.h" | |
116 #include "ear.h" | |
117 | |
118 /********************* Model option parameter strings *********************** | |
119 * The strings are defined, allocated static array space, and initialized to | |
120 * default values. | |
121 ****************************************************************************/ | |
122 | |
123 #ifndef lint | |
124 static char *sccs_id = "@(#)model.c 1.49 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 12/23/92" ; | |
125 #endif | |
126 | |
127 /* which model to use */ | |
128 | |
129 char whichdflt[] = "none" , *whichstr = whichdflt ; | |
130 char sampledflt[] = "20000." , *samplestr = sampledflt ; | |
131 | |
132 /* input properties */ | |
133 | |
134 static char dBdflt[] = "60." , *dBstr = dBdflt ; /* CG */ | |
135 static char bitsdflt[] = "12" , *bitstr = bitsdflt ; | |
136 static char swapdflt[] = "off" , *swapstr = swapdflt ; | |
137 | |
138 | |
139 /************************ File-format strings ****************************** | |
140 * The strings are defined, allocated static array space, and initialized to | |
141 * default values. | |
142 ****************************************************************************/ | |
143 | |
144 #define RETURN_SIZE 50l | |
145 | |
146 static char framesbuff[RETURN_SIZE] = "0", *framesstr = framesbuff ; | |
147 static char bytesbuff[RETURN_SIZE] = "1", *framebytesstr = bytesbuff ; | |
148 static char widthbuff[RETURN_SIZE] = "1", *framewidthstr = widthbuff ; | |
149 static char heightbuff[RETURN_SIZE] = "1", *frameheightstr = heightbuff ; | |
150 static char stepbuff[RETURN_SIZE] = "1", *framestepstr = stepbuff ; | |
151 static char nwidthdflt[] = "-5ms" , *nwidthstr = nwidthdflt ; /* roy 23-12-92 */ | |
152 static char stlagdflt[] = "5ms" , *stlagstr = stlagdflt ; /* jay 16-05-95 */ | |
153 static char susldflt[] = "5" , *suslevelstr = susldflt ; /* jay 30-08-95 */ | |
154 /************************ File-format strings ******************************* | |
155 * | |
156 * The data which flows through the model is called a "file". | |
157 * This is in an array which is structured or formatted according to the way | |
158 * data is interpreted as it is pulled from each particular source. | |
159 * The array is formatted into "frames", described by the file-format strings. | |
160 * The format may be as successive points, (in which case each frame is a | |
161 * single point with unit width and height), or the format may be as successive | |
162 * 2-dimensional arrays, (in which case each frame is an array divided into | |
163 * rows and columns). | |
164 * | |
165 * The strings are defined, allocated static array space, and initialized in | |
166 * gen.c. A set of convenience routines (see below) are given to access or to | |
167 * reset the value of a string. This enables the file format to be set up on | |
168 * the fly, depending upon the format of the data passing through the source. | |
169 * | |
170 * string: access: reset: comment: | |
171 * framesstr Frames setFrames num frames in file | |
172 * framebytesstr Framebytes setFramebytes num bytes in frame | |
173 * framewidthstr Framewidth setFramewidth num points along frame width | |
174 * frameheightst Frameheight setFrameheight num points along frame height | |
175 * framestepstr Framestep setFramestep num points between successive frames | |
176 * | |
177 * Access routines for file-format strings: | |
178 * Frames returns value of "framesstr", (initially 0) | |
179 * Framebytes returns value of "framebytesstr", (initially 1) | |
180 * Framewidth returns value of "framewidthstr", (initially 1) | |
181 * Frameheight returns value of "frameheightstr", (initially 1) | |
182 * Framestep returns value of "framestepstr", (initially 1) | |
183 * | |
184 ****************************************************************************/ | |
185 | |
186 long Frames() | |
187 { | |
188 return ( atoi( framesstr ) ) ; | |
189 } | |
190 | |
191 int Framebytes() | |
192 { | |
193 return ( atoi( framebytesstr ) ) ; | |
194 } | |
195 | |
196 int Framewidth() | |
197 { | |
198 return ( atoi( framewidthstr ) ) ; | |
199 } | |
200 | |
201 int Frameheight() | |
202 { | |
203 return ( atoi( frameheightstr ) ) ; | |
204 } | |
205 | |
206 int Framestep() | |
207 { | |
208 return ( atoi( framestepstr ) ) ; | |
209 } | |
210 | |
211 int Nwidth() | |
212 { | |
213 int abc = (Samples(stlagstr, Samplerate())); | |
214 if ( (int)atoi(suslevelstr)>=4) | |
215 /* fprintf(stderr, "Nwidth is %d\n", -abc); */ | |
216 return (-abc); | |
217 else | |
218 return 0; | |
219 } | |
220 | |
221 | |
222 /******************* Value-to-string conversion routines. ******************/ | |
223 char *ltoa( val, buffer ) | |
224 long val ; | |
225 char *buffer ; | |
226 { | |
227 (void) sprintf( buffer, "%ld", val ) ; | |
228 | |
229 return ( buffer ) ; | |
230 } | |
231 | |
232 char *itoa( val, buffer ) | |
233 int val ; | |
234 char *buffer ; | |
235 { | |
236 (void) sprintf( buffer, "%d", val ) ; | |
237 | |
238 return ( buffer ) ; | |
239 } | |
240 | |
241 /******************* Reset routines for file-format strings **************** | |
242 * Convert argument (newval) to a string, and copy into the specific | |
243 * file-format string. | |
244 * setFrames resets "framesstr", (initially 0) | |
245 * setFramebytes resets "framebytesstr", (initially 1) | |
246 * setFramewidth resets "framewidthstr", (initially 1) | |
247 * setFrameheight resets "frameheightstr", (initially 1) | |
248 * setFramestep resets "framestepstr", (initially 1) | |
249 * | |
250 * updateFramebytes sets "framebytesstr" to the total number of bytes in | |
251 * the frame, (ie current width * height). | |
252 * | |
253 * Note: updateFramebytes is automatically done at the end of each call to | |
254 * setFramewidth or setFrameheight, to reset the "framebytesstr" to | |
255 * account for the new frame size. | |
256 ****************************************************************************/ | |
257 | |
258 void setFrames( newval ) | |
259 long newval ; | |
260 { | |
261 framesstr = ltoa( newval, framesbuff ) ; | |
262 return ; | |
263 } | |
264 | |
265 void setFramebytes( newval ) | |
266 int newval ; | |
267 { | |
268 framebytesstr = itoa( newval, bytesbuff ) ; | |
269 return ; | |
270 } | |
271 | |
272 void updateFramebytes() | |
273 { | |
274 setFramebytes( Framewidth() * Frameheight() * sizeof ( short ) ) ; | |
275 return ; | |
276 } | |
277 | |
278 void setFramewidth( newval ) | |
279 int newval ; | |
280 { | |
281 framewidthstr = itoa( newval, widthbuff ) ; | |
282 updateFramebytes() ; | |
283 return ; | |
284 } | |
285 | |
286 void setFrameheight( newval ) | |
287 int newval ; | |
288 { | |
289 frameheightstr = itoa( newval, heightbuff ) ; | |
290 updateFramebytes() ; | |
291 return ; | |
292 } | |
293 | |
294 void setFramestep( newval ) | |
295 int newval ; | |
296 { | |
297 framestepstr = itoa( newval, stepbuff ) ; | |
298 return ; | |
299 } | |
300 | |
301 | |
302 static Option wavopts[] = { | |
303 | |
304 { "framebytes", bytesbuff, &framebytesstr, "framebytes - internal", SilentOption}, | |
305 { "framebytes", bytesbuff, &framebytesstr, "framebytes - internal", OutputOption}, | |
306 { "frameheight", heightbuff, &frameheightstr, "frameheight - internal", SilentOption}, | |
307 { "frameheight", heightbuff, &frameheightstr, "frameheight - internal", OutputOption}, | |
308 { "framewidth", widthbuff, &framewidthstr, "framewidth - internal", SilentOption}, | |
309 { "framewidth", widthbuff, &framewidthstr, "framewidth - internal", OutputOption}, | |
310 { "frameshift", stepbuff, &framestepstr, "framestep - internal", SilentOption}, | |
311 { "frameshift", stepbuff, &framestepstr, "framestep - internal", OutputOption}, | |
312 { "frames", framesbuff, &framesstr, "frames - internal", SilentOption}, | |
313 { "frames", framesbuff, &framesstr, "frames - internal", OutputOption}, | |
314 | |
315 { "samplerate", sampledflt, &samplestr, "Input wave sample rate (Hz)", InOutOption}, | |
316 { "swap_wave", swapdflt, &swapstr, "Swap bytes in input wave", InOutOption}, | |
317 { "bits_wave", bitsdflt, &bitstr, "Significant bits in input wave", SilentOption}, | |
318 { "dB_wave", dBdflt, &dBstr, "Rel. input level (_tlf & _med only)\n", InOutOption}, /* CG */ | |
319 { "what", whichdflt, &whichstr, "Type of model to use required", SilentOption}, | |
320 | |
321 (char *) 0 } ; | |
322 | |
323 | |
324 /***************** Tools for manipulating sampling rate ********************* * CG * | |
325 * This set of two routines allows to change and keep track of the sampling | |
326 * rate of the data which flows through the model. It is the responsability | |
327 * of each entry-point function to update the sampling rate as necessary. | |
328 * | |
329 * routine:- comment:- | |
330 * Samplerate returns the current value of the sampling rate | |
331 * SetSamplerate resets the sampling rate | |
332 ****************************************************************************/ | |
333 | |
334 static double rateCache = 0.0 ; | |
335 | |
336 void setSamplerate( newval ) | |
337 double newval ; | |
338 { | |
339 rateCache = newval ; | |
340 return ; | |
341 } | |
342 | |
343 double Samplerate() | |
344 { | |
345 if( rateCache == 0 ) | |
346 rateCache = Freq( samplestr ) ; | |
347 | |
348 return( rateCache ) ; | |
349 } | |
350 | |
351 /******************* Tools for checking for special strings **************** | |
352 * OptionInt( str ) | |
353 * OptionDouble( str ) | |
354 * OptionStringsEqual( str1, str2 ) -(defined in options.c). | |
355 ****************************************************************************/ | |
356 | |
357 double OptionDouble( str ) | |
358 char *str ; | |
359 { | |
360 if( strcmp( str, "on" ) == 0 ) | |
361 return( 1. ) ; | |
362 else if( strcmp( str, "Not_used" ) == 0 ) | |
363 return( 0. ) ; | |
364 else | |
365 return( atof( str ) ) ; | |
366 } | |
367 | |
368 int OptionInt( str ) | |
369 char *str ; | |
370 { | |
371 if( strcmp( str, "on" ) == 0 ) | |
372 return( 1 ) ; | |
373 else if( strcmp( str, "Not_used" ) == 0 ) | |
374 return( 0 ) ; | |
375 else | |
376 return( atoi( str ) ) ; | |
377 } | |
378 | |
379 int OptionLog ( str ) | |
380 char *str ; | |
381 { | |
382 if ( strcmp( str, "off" ) == 0 ) | |
383 return( 0 ) ; | |
384 else | |
385 return( 1 ) ; | |
386 } | |
387 | |
388 | |
389 | |
390 | |
391 /************************* Tools for scaling data ************************** * CG * | |
392 * This set of two routines allows to keep track of the scaling factor needed | |
393 * to convert the data which flows through the model into absolute units in | |
394 * the cgs system ( 0.0002 dyne/cm2 ==> 0 dB SPL). It is the responsability of | |
395 * each entry-point function to update the correct scaling factor as necessary. | |
396 * The user must initially specify the scaling of the input wave using the | |
397 * "dB_wave" option. The default is "dB_wave=60.". | |
398 * | |
399 * routine:- comment:- | |
400 * Scaling returns a scalar to convert data to cgs units | |
401 * SetScaling resets the scaling factor | |
402 ****************************************************************************/ | |
403 | |
404 static double scalingCache = 0.0 ; | |
405 | |
406 void setScaling( from_rms, from_dB, to_rms, to_dB ) | |
407 double from_rms, from_dB, to_rms, to_dB ; | |
408 { | |
409 scalingCache = pow( 10., ( from_dB - to_dB ) / 20. ) * to_rms / from_rms ; | |
410 } | |
411 | |
412 double Scaling() | |
413 { | |
414 double rms = 200. ; /* the default: 200 rms ==> 60 dB */ | |
415 double dB = 60. ; | |
416 | |
417 if( scalingCache == 0 ) { | |
418 | |
419 if( strcmp( dBstr, "off" ) != 0 ) | |
420 dB = Scalar( dBstr ) ; | |
421 setScaling( rms, dB, 0.0002, 0. ) ; | |
422 } | |
423 | |
424 return( scalingCache ) ; | |
425 } | |
426 | |
427 /************************ entry-point functions *************************** | |
428 * Each entry-point function creates and initializes a "source object", and | |
429 * returns a pointer to this object. Each source set up by one of the routines | |
430 * below is designed to be the entry point for a specialized auditory-modelling | |
431 * process. (See also io.c for sources which read from disk). | |
432 * Source set-up functions always return a Source. They may take one or more | |
433 * sources as arguments, as a specification of the input to the process | |
434 * the source performs. The set up routine intializes the source structure with | |
435 * a pointer to a callback function, which performs the data processing when | |
436 * the source is used. | |
437 * | |
438 * Pointers to the entry-point functions are defined in the stage table, | |
439 * (see FindStage() below). The functions are called, using these pointers, | |
440 * from routine ModeledSource() (see below). The purpose of this is to call the | |
441 * functions, in the order set by the stage table, so as to initialize a chain | |
442 * of objects which can ultimately be used to execute the program. | |
443 * | |
444 * The source set-up routines are analogous to fopen(), (see stitch/source.c). | |
445 * The processing phase, (analogous to fread()), uses pull/fill/roll functions, | |
446 * and this execution is started from gen.c:main() by a call to SinkSource(). | |
447 * | |
448 * routine:- special subroutines:- | |
449 * EarEntry() Ear() * CG * | |
450 * GenericEntry() GenericFilterBank() | |
451 * FilterEntry() GenericEntry() | |
452 * TLF_FilterEntry() TLF_GenBank() * CG * | |
453 * FineEntry() EarEntry() FilterEntry() TLF_FilterEntry() * CG * | |
454 * EnvelopeEntry() GenericEntry() | |
455 * ComplexEntry() GenericEntry() | |
456 * PolarEntry() | |
457 * RectifyEntry() | |
458 * LogEntry() | |
459 * UncompressEntry() | |
460 * SaturateEntry() Saturate() | |
461 * LowpassEntry() LowpassDataTypeSource() | |
462 * ThresholdEntry() Meddis() Mfsai() | |
463 * AdaptEntry() | |
464 * HardEntry() Saturate() | |
465 * IntegralEntry() LowpassDataTypeSource() | |
466 * DownSampleEntry() DownSampleSource() BlockSampleSource() | |
467 * SaiEntry() Sai() | |
468 * SummaryEntry() Summary() | |
469 * NullEntry() | |
470 ****************************************************************************/ | |
471 | |
472 /* As a means of introducing "cgm" as an alias for "fed", this NullEntry point does | |
473 absolutely nothing to the data, but it DOES enable us to enter the queue just above | |
474 the entry point for "fed". */ | |
475 | |
476 static Source NullEntry( source ) | |
477 Source source ; | |
478 { | |
479 return ( source ) ; | |
480 } | |
481 | |
482 | |
483 /***** upsampling parameters *****/ /* CG */ | |
484 | |
485 static char upfdflt[] = "auto" , *upfstr = upfdflt ; /* CG */ | |
486 static char cutoffdflt[] = "1.0" , *cutoffstr = cutoffdflt ; /* CG */ | |
487 static char downfdflt[] = "auto" , *downfstr = downfdflt ; /* CG */ | |
488 | |
489 /***** ear parameters *****/ /* CG */ | |
490 | |
491 static char middledflt[] = "on" , *middlestr = middledflt ; /* CG */ | |
492 static char lconcdflt[] = "0.90" , *lconcstr = lconcdflt ; /* CG */ | |
493 static char rconcdflt[] = "1.00" , *rconcstr = rconcdflt ; /* CG */ | |
494 static char kconcdflt[] = "0.01" , *kconcstr = kconcdflt ; /* CG */ | |
495 static char nconcdflt[] = "2" , *nconcstr = nconcdflt ; /* CG */ | |
496 static char lcanaldflt[] = "2.85" , *lcanalstr = lcanaldflt ; /* CG */ | |
497 static char rcanaldflt[] = "0.35" , *rcanalstr = rcanaldflt ; /* CG */ | |
498 static char kcanaldflt[] = "0.04" , *kcanalstr = kcanaldflt ; /* CG */ | |
499 static char ncanaldflt[] = "4" , *ncanalstr = ncanaldflt ; /* CG */ | |
500 | |
501 static Source EarEntry( source ) /* CG: new entry */ | |
502 Source source ; | |
503 { | |
504 int upfactor, downfactor ; | |
505 double cutoff, gain = OptionDouble( middlestr ) ; | |
506 DeclareNew( struct _tube_info *, concha ) ; | |
507 DeclareNew( struct _tube_info *, canal ) ; | |
508 | |
509 if( gain ) { | |
510 | |
511 /*** set up/downsampling parameters ***/ | |
512 if( strncmp( upfstr, "auto", 4 ) == 0 ) { | |
513 if( strncmp( downfstr, "auto", 4 ) == 0 ) | |
514 upfactor = MIN( AUTO, ( int ) ( ( MAXSIGNALFREQ * AUTO * 2 ) / Samplerate() + 1.0 ) ) ; | |
515 else | |
516 upfactor = ABS( OptionInt( downfstr ) ) ; | |
517 downfactor = upfactor ; | |
518 } | |
519 else { | |
520 upfactor = ABS( OptionInt( upfstr ) ) ; | |
521 if( strncmp( downfstr, "auto", 4 ) == 0 ) | |
522 downfactor = upfactor ; | |
523 else | |
524 downfactor = ABS( OptionInt( downfstr ) ) ; | |
525 } | |
526 | |
527 /*** set cutoff frequency of FIR upsampling filter ***/ | |
528 cutoff = 0.5 * Samplerate() * Scalar( cutoffstr ) ; | |
529 if( downfactor > upfactor ) { | |
530 upfactor = MAX( 1, upfactor ) ; | |
531 cutoff = cutoff * ( double ) upfactor / ( double ) downfactor ; | |
532 } | |
533 | |
534 /*** upsample input wave ***/ | |
535 if( upfactor >= 1 ) { | |
536 source = UpSample( source, Samplerate(), cutoff, upfactor ) ; | |
537 ( void ) setSamplerate( Samplerate() * upfactor ) ; | |
538 ( void ) setFrames( Frames() * upfactor ) ; | |
539 } | |
540 | |
541 /*** outer/middle ear filter ***/ | |
542 concha->Nsegments = atoi( nconcstr ) ; | |
543 concha->length = atof( lconcstr ) ; | |
544 concha->diameter = atof( rconcstr ) * 2. ; | |
545 concha->att_factor = atof( kconcstr ) ; | |
546 canal->Nsegments = atoi( ncanalstr ) ; | |
547 canal->length = atof( lcanalstr ) ; | |
548 canal->diameter = atof( rcanalstr ) * 2. ; | |
549 canal->att_factor = atof( kcanalstr ) ; | |
550 | |
551 source = Ear( source, Samplerate(), gain, concha, canal ) ; | |
552 | |
553 Delete( concha ) ; | |
554 Delete( canal ) ; | |
555 | |
556 /*** downsample output data ***/ | |
557 if( downfactor >= 1 ) { | |
558 source = DownSampleSource( source, downfactor, 1 ) ; | |
559 ( void ) setSamplerate( Samplerate() / downfactor ) ; | |
560 ( void ) setFrames( Frames() / downfactor ) ; | |
561 } | |
562 | |
563 } | |
564 return ( source ) ; | |
565 } | |
566 | |
567 | |
568 /***** frequency scale parameters*****/ | |
569 | |
570 static char qualdflt[] = "9.265" , *qualstr = qualdflt ; | |
571 static char limitdflt[] = "24.7Hz" , *limitstr = limitdflt ; | |
572 static char mmdflt[] = "0.89" , *mmstr = mmdflt ; /* CG */ | |
573 | |
574 static char interpdflt[] = "off" , *interpstr = interpdflt ; | |
575 | |
576 /***** filterbank parameters ****/ | |
577 | |
578 static char maxdflt[] = "6000Hz" , *maxstr = maxdflt ; /* roy 23-12-92 */ | |
579 static char mindflt[] = "100Hz" , *minstr = mindflt ; /* roy 23-12-92 */ | |
580 #ifdef PC | |
581 static char dendflt[] = "off" , *denstr = dendflt ; /* roy 23-12-92 */ | |
582 #else | |
583 static char dendflt[] = "off" , *denstr = dendflt ; /* roy 23-12-92 */ | |
584 #endif | |
585 static char chansdflt[] = "75" , *chansstr = chansdflt ; /* roy 23-12-92 */ | |
586 static char audiodflt[] = "off" , *audiostr = audiodflt ; /* CG */ | |
587 static char infodflt[] = "off" , *infostr = infodflt ; /* CG */ | |
588 | |
589 static char filterdflt[] = "gtf" , *filterstr = filterdflt ; /* CG */ | |
590 | |
591 | |
592 /**************************************************************************** | |
593 * updateFrequencies() | |
594 * Routine called from ModeledSource(), below. | |
595 * It sets the frameheight (number of filter-bank channels), and initializes | |
596 * the array of channel centre-frequencies, (called "frequencies"). | |
597 * These are derived from three basic parameters: | |
598 * option-name: string-value: default: comment: | |
599 * mincf_afb minstr 220Hz Minimum center frequency (Hz) | |
600 * maxcf_afb maxstr 4400Hz Maximum center frequency (Hz) | |
601 * dencf_afb denstr 4. Filter density (filters/critical band) | |
602 * | |
603 * The frameheight is calculated in the routine "NumberCenterFrequencies", | |
604 * and the result is copied into the "frameheightstr" by a call to the routine | |
605 * "setFrameheight". | |
606 * The "frequencies" are calculated in the routine "GenerateCenterFrequencies". | |
607 * (Both CenterFrequency routines are in gamma_tone.c). | |
608 * | |
609 * The frequencies are stored in a global array of center frequencies (below). | |
610 ****************************************************************************/ | |
611 | |
612 double *frequencies ; /* global array of centre frequencies */ | |
613 | |
614 static void reverseFrequencies( freqs, channels ) | |
615 double *freqs ; | |
616 int channels ; | |
617 { | |
618 int i ; | |
619 double d ; | |
620 | |
621 for( i=0 ; i<channels/2 ; i++ ) { | |
622 d = freqs[i] ; | |
623 freqs[i] = freqs[channels-i] ; | |
624 freqs[channels-i] = d ; | |
625 } | |
626 } | |
627 | |
628 | |
629 static void updateFrequencies() /* CG: modified */ | |
630 { | |
631 int chans = OptionInt( chansstr ) ; | |
632 double min, max, density = atof( denstr ) ; | |
633 | |
634 if( frequencies != (double *) 0 ) | |
635 Delete( frequencies ) ; | |
636 | |
637 SetErbParameters( Freq( limitstr ), atof( qualstr ) ) ; | |
638 | |
639 if( strncmp( filterstr, "tlf", 3 ) == 0 ) { | |
640 | |
641 if( chans == 0 && density == 0. ) | |
642 chans = 1 ; | |
643 | |
644 min = adjustCF( Freq( minstr ), Samplerate() ) ; | |
645 max = adjustCF( MAX( Freq( maxstr ), min ), Samplerate() ) ; | |
646 } | |
647 | |
648 else { | |
649 min = Freq( minstr ) ; | |
650 max = Freq( maxstr ) ; | |
651 } | |
652 | |
653 if( chans == 0 ) { | |
654 frequencies = GenerateCenterFrequencies( min, max, density ) ; | |
655 setFrameheight( NumberCenterFrequencies( min, max, density ) ) ; | |
656 } | |
657 else { | |
658 frequencies = NumberedCenterFrequencies( min, max, chans ) ; | |
659 setFrameheight( chans ) ; | |
660 } | |
661 | |
662 /* | |
663 reverseFrequencies( Frequencies, Frameheight() ) ; | |
664 */ | |
665 | |
666 return ; | |
667 } | |
668 | |
669 | |
670 ChannelAxis( min, max, label ) | |
671 double *min, *max ; | |
672 char **label ; | |
673 { | |
674 *min = (int) ( ErbScale( Freq( minstr ) ) * 10. ) / 10. ; | |
675 *max = (int) ( ErbScale( Freq( maxstr ) ) * 10. ) / 10. ; | |
676 | |
677 *label = "Center Frequency [ERBs]" ; | |
678 } | |
679 | |
680 /***** GTF auditory filter parameters *****/ /* CG */ | |
681 | |
682 static char orderdflt[] = "4" , *orderstr = orderdflt ; | |
683 static char phasedflt[] = "0" , *phasestr = phasedflt ; | |
684 static char gaindflt[] = "4." , *gainstr = gaindflt ; | |
685 static char floatdflt[] = "off" , *floatstr = floatdflt ; | |
686 | |
687 static Source GenericEntry( source, proc ) /* CG */ | |
688 Source source ; | |
689 int (*proc)() ; | |
690 { | |
691 int chans ; | |
692 Source ret ; | |
693 | |
694 updateFrequencies() ; | |
695 | |
696 chans = Frameheight() ; | |
697 ret = GenericFilterBank( source, OptionInt( interpstr ), &chans, Samplerate(), | |
698 frequencies, Erb, ErbScale, Scalar( gainstr ), OptionDouble( audiostr ), | |
699 atoi( orderstr ), atoi( phasestr ), atoi( bitstr ), Frames(), proc, | |
700 sizeof ( DataType ), OptionInt( infostr ) ) ; /* CG */ | |
701 | |
702 setFrameheight( chans ) ; | |
703 | |
704 return ( ret ) ; | |
705 } | |
706 | |
707 static Source FilterEntry( source ) | |
708 Source source ; | |
709 { | |
710 switch( OptionInt( floatstr ) ) { | |
711 #ifdef FLOAT | |
712 case 0 : | |
713 case 1 : | |
714 return ( GenericEntry( source, DoRealFilterFloatDataArray ) ) ; | |
715 #else | |
716 case 0 : | |
717 return ( GenericEntry( source, DoFilterShortDataArray ) ) ; | |
718 case 1 : | |
719 return ( GenericEntry( source, DoRealFilterShortDataArray ) ) ; | |
720 #endif | |
721 case 2 : | |
722 return ( GenericEntry( source, DoNewFilterDataArray ) ) ; | |
723 } | |
724 | |
725 return ( source ) ; | |
726 } | |
727 | |
728 /***** TLF auditory filter parameters *****/ /* CG */ | |
729 | |
730 static char tgaindflt[] = "4." , *tgainstr = tgaindflt ; /* CG */ | |
731 static char dsatdflt[] = "5.75e-6" , *dsatstr = dsatdflt ; /* CG */ | |
732 static char feeddflt[] = "0.99" , *feedstr = feeddflt ; /* CG */ | |
733 static char qrefdflt[] = "2." , *qrefstr = qrefdflt ; /* CG */ | |
734 static char outdendflt[] = "4." , *outdenstr = outdendflt ; /* CG */ | |
735 static char motiondflt[] = "vel" , *motionstr = motiondflt ; /* CG */ | |
736 | |
737 static Source TLF_FilterEntry( source ) /* CG: new entry */ | |
738 Source source ; | |
739 { | |
740 int chans ; | |
741 int upfactor, downfactor ; | |
742 double cutoff, dsat ; | |
743 DeclareNew( struct _tube_info *, concha ) ; | |
744 DeclareNew( struct _tube_info *, canal ) ; | |
745 | |
746 /*** set up/downsampling parameters ***/ | |
747 if( strncmp( upfstr, "auto", 4 ) == 0 ) { | |
748 if( strncmp( downfstr, "auto", 4 ) == 0 ) | |
749 upfactor = MIN( AUTO, ( int ) ( ( MAXSIGNALFREQ * AUTO * 2 ) / Samplerate() +1.0 ) ) ; | |
750 else | |
751 upfactor = ABS( OptionInt( downfstr ) ) ; | |
752 downfactor = upfactor ; | |
753 } | |
754 else { | |
755 upfactor = ABS( OptionInt( upfstr ) ) ; | |
756 if( strncmp( downfstr, "auto", 4 ) == 0 ) | |
757 downfactor = upfactor ; | |
758 else | |
759 downfactor = ABS( OptionInt( downfstr ) ) ; | |
760 } | |
761 | |
762 /*** set cutoff frequency of FIR upsampling filter ***/ | |
763 cutoff = 0.5 * Samplerate() * Scalar( cutoffstr ) ; | |
764 if( downfactor > upfactor ) { | |
765 upfactor = MAX( 1, upfactor ) ; | |
766 cutoff = cutoff * ( double ) upfactor / ( double ) downfactor ; | |
767 } | |
768 | |
769 /*** upsample input wave ***/ | |
770 if( upfactor >= 1 ) { | |
771 source = UpSample( source, Samplerate(), cutoff, upfactor ) ; | |
772 ( void ) setSamplerate( Samplerate() * upfactor ) ; | |
773 ( void ) setFrames( Frames() * upfactor ) ; | |
774 } | |
775 | |
776 /*** set outer/middle ear parameters ***/ | |
777 concha->Nsegments = atoi( nconcstr ) ; | |
778 concha->length = atof( lconcstr ) ; | |
779 concha->diameter = atof( rconcstr ) * 2. ; | |
780 concha->att_factor = atof( kconcstr ) ; | |
781 canal->Nsegments = atoi( ncanalstr ) ; | |
782 canal->length = atof( lcanalstr ) ; | |
783 canal->diameter = atof( rcanalstr ) * 2. ; | |
784 canal->att_factor = atof( kcanalstr ) ; | |
785 | |
786 /*** set bank parameters ***/ | |
787 updateFrequencies() ; | |
788 SetERBscaling( atof( mmstr ) ) ; | |
789 chans = Frameheight() ; | |
790 | |
791 /*** OHC normalization: converts from cgs units (0 dB SPL=>0.0002 dynes/cm2) to input wave units ***/ | |
792 dsat = atof( dsatstr ) / Scaling() ; | |
793 | |
794 /*** process data and downsample output ***/ | |
795 source = TLF_GenBank( source, OptionInt( interpstr ), OptionInt( infostr ), &chans, &downfactor, | |
796 Samplerate(), frequencies, Scalar( tgainstr ), atof( outdenstr ), | |
797 atof( qrefstr ), atof( feedstr ), dsat, motionstr, concha, canal ) ; | |
798 | |
799 /*** reset sampling rate and file-format strings ***/ | |
800 ( void ) setFrameheight( chans ) ; | |
801 ( void ) setSamplerate ( Samplerate() / downfactor ) ; | |
802 ( void ) setFrames( Frames() / downfactor ) ; | |
803 | |
804 Delete( concha ) ; | |
805 Delete( canal ) ; | |
806 | |
807 return ( source ) ; | |
808 } | |
809 | |
810 static Source FineEntry(source ) /* CG: new Entry */ | |
811 Source source ; | |
812 { | |
813 if( strncmp( filterstr, "off", 3 ) == 0 ) | |
814 source = EarEntry( source ) ; | |
815 | |
816 else { | |
817 | |
818 if( strncmp( filterstr, "tlf", 3 ) == 0 ) | |
819 source = TLF_FilterEntry( source ) ; | |
820 | |
821 else { | |
822 source = EarEntry( source ) ; | |
823 source = FilterEntry( source ) ; | |
824 } | |
825 } | |
826 | |
827 return( source ) ; | |
828 } | |
829 | |
830 static Source EnvelopeEntry( source ) | |
831 Source source ; | |
832 { | |
833 #ifdef FLOAT | |
834 return ( GenericEntry( source, DoRealEnvelopeFloatDataArray ) ) ; | |
835 #else | |
836 if( OptionInt( floatstr ) != 0 ) | |
837 return ( GenericEntry( source, DoRealEnvelopeShortDataArray ) ) ; | |
838 else | |
839 return ( GenericEntry( source, DoEnvelopeShortDataArray ) ) ; | |
840 #endif | |
841 } | |
842 | |
843 static Source ComplexEntry( source ) | |
844 Source source ; | |
845 { | |
846 Source ret ; | |
847 | |
848 #ifdef FLOAT | |
849 ret = GenericEntry( source, DoComplexFilterFloatDataArray ) ; | |
850 #else | |
851 ret = GenericEntry( source, DoComplexFilterShortDataArray ) ; | |
852 #endif | |
853 setFrameheight( Frameheight() * 2 ) ; | |
854 | |
855 return ( ret ) ; | |
856 } | |
857 | |
858 /******* [fbm] [bmm] [fcp,fcr] stage: "auditory filter output" ************/ | |
859 | |
860 static Option fbmopts[] = { | |
861 | |
862 { "upfactor", upfdflt, &upfstr, "Upsampling factor (off, auto, int)", SilentOption}, /* CG */ | |
863 { "cutoff", cutoffdflt, &cutoffstr, "LP cutoff as a fraction of Nyquist freq.", SilentOption}, /* CG */ | |
864 { "downfactor", downfdflt, &downfstr, "Downsampling factor (off, auto, int)\n", SilentOption}, /* CG */ | |
865 | |
866 { "middle_ear", middledflt, &middlestr, "Enable outer/middle ear function\n", InOutOption}, /* CG */ | |
867 { "nconcha_ear", nconcdflt, &nconcstr, "Number of segments in concha", SilentOption}, /* CG */ | |
868 { "lconcha_ear", lconcdflt, &lconcstr, "Total length of concha (cm)", SilentOption}, /* CG */ | |
869 { "rconcha_ear", rconcdflt, &rconcstr, "Radius of concha (cm)", SilentOption}, /* CG */ | |
870 { "kconcha_ear", kconcdflt, &kconcstr, "Attn. constant of concha (1/cm)", SilentOption}, /* CG */ | |
871 { "ncanal_ear", ncanaldflt, &ncanalstr, "Number of segments in ear canal", SilentOption}, /* CG */ | |
872 { "lcanal_ear", lcanaldflt, &lcanalstr, "Length of ear canal (cm)", SilentOption}, /* CG */ | |
873 { "rcanal_ear", rcanaldflt, &rcanalstr, "Radius of ear canal (cm)", SilentOption}, /* CG */ | |
874 { "kcanal_ear", kcanaldflt, &kcanalstr, "Attn. constant of ear canal (1/cm)\n", SilentOption}, /* CG */ | |
875 | |
876 { "channels_afb", chansdflt, &chansstr, "Number of channels in filter", InOutOption}, | |
877 { "mincf_afb", mindflt, &minstr, "Minimum center frequency (Hz)", InOutOption}, | |
878 { "maxcf_afb", maxdflt, &maxstr, "Maximum center frequency (Hz)", InOutOption}, | |
879 { "dencf_afb", dendflt, &denstr, "Filter density (filters/critical band)", InOutOption}, | |
880 { "info_afb", infodflt, &infostr, "Prints filterbank information (to stderr).", InputOption}, /* CG */ | |
881 { "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply", OutputOption}, | |
882 { "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply", SilentOption}, | |
883 {"audiogram_afb", audiodflt, &audiostr, "Audiogram equalisation parameter", SilentOption}, /* CG */ | |
884 { "bwmin_afb", limitdflt, &limitstr, "Minimum filter bandwith", InOutOption}, | |
885 { "quality_afb", qualdflt, &qualstr, "Ultimate qualtity factor of filters", InOutOption}, | |
886 { "mmerb_afb", mmdflt, &mmstr, "Length of 1 erb-rate unit along BM (mm)\n", InOutOption}, /* CG */ | |
887 | |
888 { "filter", filterdflt, &filterstr, "Select auditory filter (gtf, tlf, off)\n", InOutOption}, /* CG */ | |
889 | |
890 { "float_gtf", floatdflt, &floatstr, "Floating point filter calculations", OutputOption}, | |
891 { "float_gtf", floatdflt, &floatstr, "Floating point filter calculations", SilentOption}, | |
892 { "phase_gtf", phasedflt, &phasestr, "Phase compensation option", InOutOption}, | |
893 { "order_gtf", orderdflt, &orderstr, "Filter order", InOutOption}, | |
894 { "gain_gtf", gaindflt, &gainstr, "Filter output amplification\n", InOutOption}, /* CG */ | |
895 | |
896 { "motion_tlf", motiondflt, &motionstr, "BM output motion (disp, vel)", InOutOption}, /* CG */ | |
897 { "outdencf_tlf", outdendflt, &outdenstr, "Filter density outside display range", InOutOption}, /* CG */ | |
898 { "qref_tlf", qrefdflt, &qrefstr, "Local Q-factor of BM segment", InOutOption}, /* CG */ | |
899 { "feedback_tlf", feeddflt, &feedstr, "Feedback gain of OHCs (0 to 0.999)", InOutOption}, /* CG */ | |
900 { "dsat_tlf", dsatdflt, &dsatstr, "Half-saturation displacement (cm)", InOutOption}, /* CG */ | |
901 { "gain_tlf", tgaindflt, &tgainstr, "Filter output amplification\n", InOutOption}, /* CG */ | |
902 | |
903 ( char * ) 0 } ; | |
904 | |
905 static void polar_callback( state, bytes, output, end, input ) | |
906 Source state ; | |
907 ByteCount *bytes ; | |
908 scomplex *output, *end, *input ; | |
909 { | |
910 register scomplex *iptr = input ; | |
911 register scomplex *optr = output ; | |
912 register scomplex *eptr = end ; | |
913 | |
914 while( optr < eptr ) { | |
915 optr->real = imB( (long) iptr->real * iptr->real + (long) iptr->imag * iptr->imag ) >> 1 ; | |
916 optr->imag = iatan2( iptr->imag, iptr->real ) ; | |
917 iptr++ ; | |
918 optr++ ; | |
919 } | |
920 | |
921 return ; | |
922 } | |
923 | |
924 static Source PolarEntry( source ) | |
925 Source source ; | |
926 { | |
927 return ( NewSimpleProcessingSource( polar_callback, source, "model.c polar conversion" ) ) ; | |
928 } | |
929 | |
930 static void fullwave_callback( state, bytes, buffer, end, input ) | |
931 Source state ; | |
932 ByteCount *bytes ; | |
933 DataType *buffer, *end, *input ; | |
934 { | |
935 register DataType *iptr = input ; | |
936 register DataType *optr = buffer ; | |
937 register DataType *eptr = end ; | |
938 | |
939 if( optr < eptr ) | |
940 do | |
941 if( *iptr > 0 ) | |
942 *optr++ = *iptr++ ; | |
943 else | |
944 *optr++ = -*iptr++ ; | |
945 | |
946 while( optr < eptr ) ; | |
947 | |
948 return ; | |
949 } | |
950 | |
951 | |
952 /* rectification */ | |
953 | |
954 static char rectdflt[] = "off", *rectstr = rectdflt ; | |
955 | |
956 /************** [fbr] stage: "rectified filter output" ******************/ | |
957 | |
958 static Option fbropts[] = { | |
959 | |
960 { "rectify", rectdflt, &rectstr, "Rectify filter output", InOutOption}, | |
961 | |
962 ( char * ) 0 } ; | |
963 | |
964 | |
965 static void halfwave_callback( state, bytes, buffer, end, input ) | |
966 Source state ; | |
967 ByteCount *bytes ; | |
968 DataType *buffer, *end, *input ; | |
969 { | |
970 register DataType *iptr = input ; | |
971 register DataType *optr = buffer ; | |
972 register DataType *eptr = end ; | |
973 | |
974 if( optr < eptr ) | |
975 do | |
976 if( *iptr > 0 ) | |
977 *optr++ = *iptr++ ; | |
978 else | |
979 *optr++ =0,*iptr++ ; | |
980 | |
981 while( optr < eptr ) ; | |
982 | |
983 return ; | |
984 } | |
985 | |
986 static Source RectifyEntry( source ) | |
987 Source source ; | |
988 { | |
989 switch( OptionInt( rectstr ) ) { | |
990 | |
991 case 1 : | |
992 return ( SharingSource( NewSimpleProcessingSource( halfwave_callback, source, "model.c recification" ), source ) ) ; | |
993 | |
994 case 2: | |
995 return ( SharingSource( NewSimpleProcessingSource( fullwave_callback, source, "model.c recification" ), source ) ) ; | |
996 | |
997 default : | |
998 return ( source ) ; | |
999 } | |
1000 } | |
1001 | |
1002 | |
1003 /*********** [fbc] [fec] stage: "compressed filter output" **************/ | |
1004 | |
1005 /* logaritmic compression function */ | |
1006 | |
1007 static char logdflt[] = "log", *logstr = logdflt ; | |
1008 static char powdflt[] = "off", *powstr = powdflt ; | |
1009 | |
1010 static Option fbcopts[] = { | |
1011 | |
1012 { "compress", logdflt, &logstr, "Compression (log, power value [0-1], off)", InOutOption}, | |
1013 ( char * ) 0 } ; | |
1014 | |
1015 | |
1016 #ifdef FLOAT | |
1017 static void mB_callback( state, bytes, buffer, end, input ) | |
1018 Pointer state ; | |
1019 ByteCount *bytes ; | |
1020 DataType *buffer, *end, *input ; | |
1021 { | |
1022 register DataType *iptr = input ; | |
1023 register DataType *optr = buffer ; | |
1024 register DataType *eptr = end ; | |
1025 double pw; | |
1026 | |
1027 if (!strcmp(logstr, "log") || !strcmp(logstr, "on")) | |
1028 ; | |
1029 else | |
1030 { | |
1031 pw=(double)atof(logstr); | |
1032 strcpy(powstr, "on"); | |
1033 if (pw > 1.0) { | |
1034 fprintf(stderr, "The value of power compression cannot be more than 1.0\n"); | |
1035 exit(-125);} | |
1036 } | |
1037 | |
1038 if( optr < eptr ) | |
1039 do{ | |
1040 if( *iptr >= 1. ){ | |
1041 if (!(strcmp(powstr, "off"))){ | |
1042 *optr = log10( *iptr ) * 2000. ;} | |
1043 else{ | |
1044 *optr = (float) pow((double)*iptr, (double) pw) * 100./(pw); } | |
1045 } | |
1046 else | |
1047 *optr = 0. ; /* -10. Changed from -10, AJD 29th August, 1995. */ | |
1048 iptr++; optr++; } | |
1049 while( optr < eptr ) ; | |
1050 | |
1051 return ; | |
1052 | |
1053 } | |
1054 #endif | |
1055 | |
1056 static Source LogEntry( source ) | |
1057 Source source ; | |
1058 { | |
1059 if( OptionLog( logstr ) != 0 ) | |
1060 #ifdef FLOAT | |
1061 return ( SharingSource( NewSimpleProcessingSource( mB_callback, source, "model.c compression" ), source ) ) ; | |
1062 #else | |
1063 return ( SharingSource( milliBellShortSource( source ), source ) ) ; | |
1064 #endif | |
1065 else | |
1066 return ( source ) ; | |
1067 } | |
1068 | |
1069 /*********** [fbu] [feu] stage: "uncompressed filter output" **************/ | |
1070 | |
1071 /***** uncompress data by raising to a power *****/ | |
1072 | |
1073 static char powerdflt[] = "off", *powerstr = powerdflt ; | |
1074 | |
1075 static Option fbuopts[] = { | |
1076 | |
1077 { "power", powerdflt, &powerstr, "Power of Compression", SilentOption}, | |
1078 | |
1079 ( char * ) 0 } ; | |
1080 | |
1081 | |
1082 struct _uncompress_state { double power ; } ; | |
1083 | |
1084 static void uncompress_callback( state, bytes, buffer, end, input ) | |
1085 struct _uncompress_state *state ; | |
1086 ByteCount *bytes ; | |
1087 DataType *buffer, *end, *input ; | |
1088 { | |
1089 register DataType *iptr = input ; | |
1090 register DataType *optr = buffer ; | |
1091 register DataType *eptr = end ; | |
1092 register double power = state->power ; | |
1093 | |
1094 if( optr < eptr ) | |
1095 do | |
1096 *optr++ = pow( 10., *iptr++ * power ) ; | |
1097 while( optr < eptr ) ; | |
1098 | |
1099 return ; | |
1100 } | |
1101 static Source UncompressEntry( source ) | |
1102 Source source ; | |
1103 { | |
1104 DeclareNew( struct _uncompress_state *, state ) ; | |
1105 | |
1106 if( OptionDouble( powerstr ) != 0.0 ) { | |
1107 | |
1108 state->power = OptionDouble( powerstr ) / 2000. ; | |
1109 | |
1110 return ( SharingSource (NewProcessingSource( state, uncompress_callback, stitch_free, source, "model.c compression" ), source ) ) ; | |
1111 } | |
1112 else | |
1113 return ( source ) ; | |
1114 } | |
1115 | |
1116 /*********** [fbs] [fes] stage: "saturated filter output" **************/ | |
1117 | |
1118 /***** provide for possible saturation at this point *****/ | |
1119 | |
1120 static char satdflt[] = "off", *satstr = satdflt ; | |
1121 | |
1122 static Option fbsopts[] = { | |
1123 | |
1124 { "saturate", satdflt, &satstr, "Introduce Saturation of non-linearity\n", SilentOption}, | |
1125 | |
1126 ( char * ) 0 } ; | |
1127 | |
1128 | |
1129 struct _sat_state { int saturation ; } ; | |
1130 | |
1131 static void sat_callback( state, bytes, buffer, end, input ) | |
1132 struct _sat_state *state ; | |
1133 ByteCount *bytes ; | |
1134 DataType *buffer, *end, *input ; | |
1135 { | |
1136 register DataType *iptr = input ; | |
1137 register DataType *optr = buffer ; | |
1138 register DataType *eptr = end ; | |
1139 | |
1140 if( optr < eptr ) | |
1141 do { | |
1142 | |
1143 if( *iptr > 0 ) | |
1144 *optr++ = SCALE( *iptr ) / ( SCALE( 1 ) + SCALE( *iptr ) / state->saturation ) ; | |
1145 else | |
1146 *optr++ = SCALE( *iptr ) / ( SCALE( 1 ) - SCALE( *iptr ) / state->saturation ) ; | |
1147 iptr++ ; | |
1148 | |
1149 } while( optr < eptr ) ; | |
1150 | |
1151 return ; | |
1152 } | |
1153 | |
1154 static Source Saturate( source, str ) | |
1155 Source source ; | |
1156 char *str ; | |
1157 { | |
1158 DeclareNew( struct _sat_state *, state ) ; | |
1159 | |
1160 if( OptionInt( str ) != 0 ) { | |
1161 | |
1162 state->saturation = OptionInt( str ) ; | |
1163 | |
1164 return ( SharingSource( NewProcessingSource( (Pointer) state, sat_callback, stitch_free, source, "model.c stauration" ), source ) ) ; | |
1165 } | |
1166 else | |
1167 return ( source ) ; | |
1168 } | |
1169 | |
1170 static Source SaturateEntry( source ) | |
1171 Source source ; | |
1172 { | |
1173 return( Saturate( source, satstr ) ) ; | |
1174 } | |
1175 | |
1176 #if 00 | |
1177 /***** new processing entry *****/ | |
1178 | |
1179 static char zongdflt[] = "off", *zongstr = zongdflt ; /* parameter default for table.c */ | |
1180 | |
1181 static Source ZongEntry( source ) | |
1182 Source source ; | |
1183 { | |
1184 int i, chans = Frameheight() ; | |
1185 DeclareNewArray( WuState *, states, chans, "model.c for states" ) ; | |
1186 | |
1187 /* for all of the channels create a new wu cels object */ | |
1188 | |
1189 for( i=0 ; i<chans ; i++ ) | |
1190 states[ i ] = NewWu( zongstr ) ; /* call constructor of new wu cell */ | |
1191 | |
1192 /* use general purpose source for processing multiplexed files with these cells */ | |
1193 | |
1194 return (source ) ; | |
1195 return ( NewMultiplexedSource( states, WuMultiplexedDataArray, DeleteWu, chans, source, "model.c wu" ) ) ; | |
1196 } | |
1197 #endif | |
1198 | |
1199 /*********** [fbl] [fel] stage: "low-pass filtered filter output ***********/ | |
1200 | |
1201 /* low pass filtering */ | |
1202 | |
1203 static char lstagedflt[] = "off", *lstagestr = lstagedflt ; | |
1204 static char lupdflt[] = "0.5ms", *lupstr = lupdflt ; | |
1205 static char ldowndflt[] = "1", *ldownstr = ldowndflt ; | |
1206 static char llossdflt[] = "1", *llossstr = llossdflt ; | |
1207 static char lvlossdflt[] = "0", *lvlossstr = lvlossdflt ; | |
1208 static char ligaindflt[] = "1", *ligainstr = ligaindflt ; | |
1209 | |
1210 static Option fblopts[] = { | |
1211 | |
1212 { "ligain_lpf", ligaindflt, &ligainstr, "Gain of integration stage\n", OutputOption}, | |
1213 { "ligain_lpf", ligaindflt, &ligainstr, "Gain of integration stage\n", SilentOption}, | |
1214 { "lvloss_lpf", lvlossdflt, &lvlossstr, "Rest level for loss", OutputOption}, | |
1215 { "lvloss_lpf", lvlossdflt, &lvlossstr, "Rest level for loss", SilentOption}, | |
1216 { "lloss_lpf", llossdflt, &llossstr, "Loss time constant", OutputOption}, | |
1217 { "lloss_lpf", llossdflt, &llossstr, "Loss time constant", SilentOption}, | |
1218 { "ltdown_lpf", ldowndflt, &ldownstr, "Downward time constant in ms", OutputOption}, | |
1219 { "ltdown_lpf", ldowndflt, &ldownstr, "Downward time constant in ms", SilentOption}, | |
1220 { "ltup_lpf", lupdflt, &lupstr, "Upward time constant in ms", SilentOption}, | |
1221 { "lstages_lpf", lstagedflt, &lstagestr, "Stages of integration\n", SilentOption}, | |
1222 | |
1223 ( char * ) 0 } ; | |
1224 | |
1225 static Source LowpassEntry( source ) | |
1226 Source source ; | |
1227 { | |
1228 return ( LowpassDataTypeSource( source, OptionInt( lstagestr ), Frameheight(), Samples( lupstr, Samplerate() ), Samples( ldownstr, Samplerate() ), Scalar( ligainstr ) ) ) ; | |
1229 } | |
1230 | |
1231 | |
1232 /*********** [nap,fbt] [fet] stage: "neural activity pattern" **************/ | |
1233 | |
1234 /***** transduction switch *****/ /* CG */ | |
1235 | |
1236 static char transdflt[] = "at", *transstr = transdflt ; /* CG */ | |
1237 | |
1238 | |
1239 /***** meddis inner haircell model *****/ /* CG */ | |
1240 | |
1241 static char meddisdflt[] = "1.", *meddisstr = meddisdflt ; | |
1242 static char fibredflt[] ="medium", *fibrestr = fibredflt ; /* CG */ | |
1243 static char thresdflt[] = "0.", *thresstr = thresdflt ; /* CG */ | |
1244 | |
1245 Source Meddis( input, chans, samplerate, scalar ) /* CG: modified */ | |
1246 Source input ; | |
1247 int chans ; | |
1248 double samplerate, scalar ; | |
1249 { | |
1250 char *state ; | |
1251 double coupling = 100. / pow( 10., atof( thresstr ) / 20. ) ; | |
1252 | |
1253 /*** convert from filterbank units to meddis units (30 dB => 1 rms ) ***/ | |
1254 | |
1255 /* first convert from filterbank output units to cgs units (0 dB SPL => 0.0002 dynes/cm2) ***/ | |
1256 ( void ) setScaling( 0.0002 / Scaling() * FILTERBANK_SCALE * 4.0, 0., 0.0002, 0. ) ; | |
1257 | |
1258 /* second convert from cgs units to meddis units (30 dB => 1 rms) ***/ | |
1259 ( void ) setScaling( 0.0002 / Scaling(), 0., MEDDIS_RMS, MEDDIS_dB ) ; | |
1260 | |
1261 /*** start array of Meddis hair cells ***/ | |
1262 coupling = coupling * Scaling() ; | |
1263 state = NewHaircells( chans, samplerate, scalar, coupling, fibrestr ) ; | |
1264 return ( NewProcessingSource( state, DoHaircells, CloseHaircells, input, "model.c meddis" ) ) ; | |
1265 } | |
1266 | |
1267 /***** adaptive thresholding *****/ | |
1268 | |
1269 static char stxdflt[] = "1.", *stxstr = stxdflt ; /* CG 23-03-94 */ | |
1270 static char risedflt[] = "10000.", *risestr = risedflt ; | |
1271 static char rapiddflt[] = "0.6", *rapidstr = rapiddflt ; | |
1272 static char fastdflt[] = "0.2", *faststr = fastdflt ; | |
1273 static char propdflt[] = "0.5", *propstr = propdflt ; | |
1274 static char latdflt[] = "20.", *latstr = latdflt ; /* roy 23-12-92 */ | |
1275 static char vdraindflt[] = "5", *vdrainstr = vdraindflt ; | |
1276 static char timesdflt[] = "2", *timesstr = timesdflt ; | |
1277 | |
1278 static char compdflt[] = "on", *compstr = compdflt ; /* mha 22/1/93 */ | |
1279 | |
1280 | |
1281 static Option fbtopts[] = { | |
1282 | |
1283 { "transduction", transdflt, &transstr, "Select transduction function (at, meddis, off)\n",InOutOption}, /* CG */ | |
1284 | |
1285 { "trise_at", risedflt, &risestr, "Threshold adaptation rate (upwards)", InOutOption}, | |
1286 {"t1recovery_at", rapiddflt, &rapidstr, "Initial recovery rate relative to filter", InOutOption}, | |
1287 {"t2recovery_at", fastdflt, &faststr, "Secondary recovery rate relative to filter", InOutOption}, | |
1288 { "propt2t1_at", propdflt, &propstr, "Relative height of secondary adaptation", InOutOption}, | |
1289 { "frecovery_at", latdflt, &latstr, "Recovery rate across frequency", InOutOption}, | |
1290 { "reclimit_at", vdraindflt, &vdrainstr, "Limitation on recovery level", InOutOption}, | |
1291 { "times_at", timesdflt, ×str, "Oversampling of calculation of threshold", OutputOption}, | |
1292 { "times_at", timesdflt, ×str, "Oversampling of calculation of threshold", SilentOption}, | |
1293 {"compensate_at", compdflt, &compstr, "Cochlea output compensation", SilentOption}, | |
1294 { "gain_at", stxdflt, &stxstr, "Adaptive thresholding output gain\n", InOutOption}, /* CG */ | |
1295 | |
1296 { "fibre_med", fibredflt, &fibrestr, "Spont-rate fibre type (medium, high)", InOutOption}, /* CG */ | |
1297 { "thresh_med", thresdflt, &thresstr, "Haircell threshold shift (dB)", InOutOption}, /* CG */ | |
1298 { "gain_med", meddisdflt, &meddisstr, "Meddis haircell model output gain\n", InOutOption}, /* CG */ | |
1299 | |
1300 ( char * ) 0 } ; | |
1301 | |
1302 static Source ThresholdEntry( source ) /* CG: modified */ | |
1303 Source source ; | |
1304 { | |
1305 double density ; | |
1306 | |
1307 if( OptionInt( chansstr ) == 0 ) | |
1308 density = OptionDouble( denstr ) ; | |
1309 else | |
1310 density = OptionInt( chansstr ) / ( ErbScale( Freq( maxstr ) ) - ErbScale( Freq( minstr ) ) ) ; | |
1311 | |
1312 if( strncmp( transstr, "off", 3 ) == 0 ) | |
1313 source = source ; | |
1314 | |
1315 else { | |
1316 | |
1317 if( strncmp( transstr, "med", 3 ) == 0 ) | |
1318 source = Meddis( source, Frameheight(), Samplerate(), OptionDouble( meddisstr ) ) ; | |
1319 | |
1320 else { | |
1321 compensate = OptionDouble( compstr ) ; | |
1322 | |
1323 source = NewProcessingSource( | |
1324 newCorti( | |
1325 Frameheight(), Samplerate(), frequencies, Erb, | |
1326 atof( risestr ), atof( latstr ) * density, | |
1327 atof( rapidstr ), atof( faststr ), atof( propstr ), | |
1328 log10( Scalar( vdrainstr ) ) * 2000., | |
1329 (int) ( density * atof( latstr ) / Samplerate() + 1. ) * atoi( timesstr ), | |
1330 OptionDouble( stxstr ) | |
1331 ), (void ( * )()) Corti, closeCorti, | |
1332 source, | |
1333 "model.c thresholding" | |
1334 ) ; | |
1335 | |
1336 } | |
1337 } | |
1338 return ( source ) ; | |
1339 } | |
1340 | |
1341 /* modulation frequency image */ | |
1342 | |
1343 static char stepmfdflt[] = "250Hz", *stepmfstr = stepmfdflt ; | |
1344 static char maxmfdflt[] = "250Hz", *maxmfstr = maxmfdflt ; | |
1345 static char minmfdflt[] = "50Hz", *minmfstr = minmfdflt ; | |
1346 static char denmfdflt[] = "off", *denmfstr = denmfdflt ; | |
1347 | |
1348 #ifndef DSP32 | |
1349 | |
1350 Source Mfsai( source, segment ) /* CG */ | |
1351 Source source ; | |
1352 int segment ; | |
1353 { | |
1354 extern char *filestr ; | |
1355 Source mfsource = FileNameSource( filestr ) ; | |
1356 int frameheight = Frameheight() ; | |
1357 int i ; | |
1358 | |
1359 frequencies = GenerateCenterFrequencies( Freq( minmfstr ), Freq( maxmfstr ), OptionDouble( denmfstr ) ) ; | |
1360 setFrameheight( NumberCenterFrequencies( Freq( minmfstr ), Freq( maxmfstr ), OptionDouble( denmfstr ) ) ) ; | |
1361 | |
1362 mfsource = GenericEntry( mfsource, DoFilterShortDataArray ) ; | |
1363 /* mfsource = GenericEntry( mfsource, DoNewFilterDataArray ) ; */ | |
1364 mfsource = NewProcessingSource( | |
1365 newCorti( | |
1366 Frameheight(), Samplerate(), frequencies, Erb, | |
1367 atof( risestr ), atof( latstr ) * OptionDouble( denmfstr ), | |
1368 atof( rapidstr ), atof( faststr ), atof( propstr ), | |
1369 log10( Scalar( vdrainstr ) ) * 2000., /* convert to millibells */ | |
1370 (int) ( OptionDouble( denmfstr ) * atof( latstr ) / Samplerate() + 1. ) * atoi( timesstr ), | |
1371 0 | |
1372 ), (void ( * )()) Corti, closeCorti, | |
1373 mfsource, | |
1374 "model.c thresholding" | |
1375 ) ; | |
1376 | |
1377 return ( mfsource ) ; | |
1378 } | |
1379 | |
1380 #endif | |
1381 /***** long term adaptation - not implemented - used to sneak in modulation frequency thing *****/ | |
1382 | |
1383 static char adapdflt[] = "0", *adapstr = adapdflt ; | |
1384 | |
1385 static Source AdaptEntry( source ) | |
1386 Source source ; | |
1387 { | |
1388 #ifndef DSP32 | |
1389 if( OptionDouble( denmfstr ) > 0 ) | |
1390 source = Mfsai( source ) ; | |
1391 #endif | |
1392 return( source ) ; | |
1393 } | |
1394 | |
1395 /*********** [fba] [fea] stage: "adapted transduced filter output" *********/ | |
1396 | |
1397 static Option fbaopts[] = { | |
1398 | |
1399 { "mmincf_mfb", minmfdflt, &minmfstr, "Minimum modulation frequency (Hz)", SilentOption}, | |
1400 { "mmaxcf_mfb", maxmfdflt, &maxmfstr, "Maximum modulation frequency (Hz)", SilentOption}, | |
1401 { "mdencf_mfb", denmfdflt, &denmfstr, "Modulation filter density ", SilentOption}, | |
1402 { "stepcf_mfb", stepmfdflt, &stepmfstr, "Step between images\n", SilentOption}, | |
1403 | |
1404 { "tadaptation", adapdflt, &adapstr, "Time constant of long term adaptation\n", SilentOption}, | |
1405 | |
1406 ( char * ) 0 } ; | |
1407 | |
1408 | |
1409 | |
1410 /***** hard limiting *****/ | |
1411 | |
1412 static char harddflt[] = "off", *hardstr = harddflt ; | |
1413 | |
1414 static Source HardEntry( source ) | |
1415 Source source ; | |
1416 { | |
1417 return( Saturate( source, hardstr ) ) ; | |
1418 } | |
1419 | |
1420 /*********** [fbh] [feh] stage: "hard limited filter output" **************/ | |
1421 | |
1422 static Option fbhopts[] = { | |
1423 | |
1424 { "hard_limit", harddflt, &hardstr, "Hardlimit firing rate before integration\n",OutputOption}, | |
1425 { "hard_limit", harddflt, &hardstr, "Hardlimit firing rate before integration\n",SilentOption}, | |
1426 | |
1427 ( char * ) 0 } ; | |
1428 | |
1429 | |
1430 /***** [sgm,cgm,fbd,fbi] [fed,fei] stage: "integrated filter output" *******/ | |
1431 | |
1432 /***** temporal integration *****/ | |
1433 | |
1434 static char stagedflt[] = "off", *stagestr = stagedflt ; | |
1435 static char updflt[] = "8ms", *upstr = updflt ; | |
1436 static char downdflt[] = "1", *downstr = downdflt ; | |
1437 static char lossdflt[] = "1", *lossstr = lossdflt ; | |
1438 static char vlossdflt[] = "0", *vlossstr = vlossdflt ; | |
1439 static char igaindflt[] = "1", *igainstr = igaindflt ; | |
1440 | |
1441 static Option fbiopts[] = { | |
1442 | |
1443 { "stages_idt", stagedflt, &stagestr, "Stages of integration", InOutOption}, | |
1444 { "igain_idt", igaindflt, &igainstr, "Gain of integration stage\n", OutputOption}, | |
1445 { "igain_idt", igaindflt, &igainstr, "Gain of integration stage\n", SilentOption}, | |
1446 | |
1447 { "vloss_idt", vlossdflt, &vlossstr, "Rest level for loss", OutputOption}, | |
1448 { "vloss_idt", vlossdflt, &vlossstr, "Rest level for loss", SilentOption}, | |
1449 { "loss_idt", lossdflt, &lossstr, "Loss time constant", OutputOption}, | |
1450 { "loss_idt", lossdflt, &lossstr, "Loss time constant", SilentOption}, | |
1451 { "tdown_idt", downdflt, &downstr, "Downward time constant in ms", OutputOption}, | |
1452 { "tdown_idt", downdflt, &downstr, "Downward time constant in ms", SilentOption}, | |
1453 { "tup_idt", updflt, &upstr, "Low-pass filter time constant", InOutOption}, | |
1454 | |
1455 ( char * ) 0 } ; | |
1456 | |
1457 static Source IntegralEntry( source ) | |
1458 Source source ; | |
1459 { | |
1460 return ( LowpassDataTypeSource( source, OptionInt( stagestr ), Frameheight(), Samples( upstr, Samplerate() ), Samples( downstr, Samplerate() ), Scalar( igainstr ) ) ) ; | |
1461 } | |
1462 | |
1463 | |
1464 /* downsampling */ | |
1465 | |
1466 static char downsdflt[] = "off", *downsstr = downsdflt ; | |
1467 | |
1468 static Option dwnopts[] = { | |
1469 | |
1470 { "downsample", downsdflt, &downsstr, "Downsampling over time", InOutOption}, | |
1471 { "frstep_epn", downsdflt, &downsstr, "Downsampling over time\n", InOutOption}, | |
1472 | |
1473 (char *) 0 } ; | |
1474 | |
1475 static Source DownSampleEntry( source ) | |
1476 Source source ; | |
1477 { | |
1478 int spacing = Samples( downsstr, Samplerate() ) ; | |
1479 int channels = Frameheight() * Framewidth() ; | |
1480 | |
1481 if( spacing != 0 ) { | |
1482 | |
1483 #if defined( PC ) || defined( DSP32 ) | |
1484 source = NewSegmentingSource( source, Frameheight() * Framewidth() * sizeof ( DataType ) * 4 ) ; | |
1485 #endif | |
1486 | |
1487 if( spacing > 0 ) | |
1488 source = DownSampleSource( source, spacing, channels ) ; | |
1489 else { | |
1490 spacing = -spacing ; | |
1491 source = BlockSampleSource( source, spacing, channels ) ; | |
1492 } | |
1493 | |
1494 setFramestep( spacing ) ; | |
1495 | |
1496 setFrames( Frames() / spacing ) ; | |
1497 } | |
1498 | |
1499 return( source ) ; | |
1500 } | |
1501 | |
1502 | |
1503 /* stabilised image defaults */ | |
1504 | |
1505 static char llimdflt[] = "1.5c" , *llimstr = llimdflt ; | |
1506 static char ulimdflt[] = "24ms" , *ulimstr = ulimdflt ; | |
1507 | |
1508 static char saidflt[] = "1" , *saistr = saidflt ; | |
1509 #ifdef PC | |
1510 static char pwidthdflt[] = "20ms" , *pwidthstr = pwidthdflt ; | |
1511 #else | |
1512 static char pwidthdflt[] = "35ms" , *pwidthstr = pwidthdflt ; /* roy 23-12-92 */ | |
1513 #endif | |
1514 /* static char nwidthdflt[] = "-5ms" , *nwidthstr = nwidthdflt ; roy 23-12-92 */ | |
1515 | |
1516 static char ltlimdflt[] = "150Hz" , *ltlimstr = ltlimdflt ; | |
1517 static char utlimdflt[] = "20Hz" , *utlimstr = utlimdflt ; | |
1518 static char decaydflt[] = "30ms" , *decaystr = decaydflt ; | |
1519 static char cgmdflt[] = "2.5" , *cgmstr = cgmdflt ; /* 30ms > 1.25 roy 23-12-92 */ | |
1520 static char ttdflt[] = "5" , *ttstr = ttdflt ; /* 8ms > 10 roy 23-12-92 */ | |
1521 | |
1522 static char sustdflt[] = "0" , *susthreshstr = sustdflt ; | |
1523 | |
1524 static char swdflt[] = "off" , *swstr = swdflt ; | |
1525 | |
1526 #ifdef PC | |
1527 static char stepdflt[] = "15.25ms" , *stepstr = stepdflt ; | |
1528 #else | |
1529 static char stepdflt[] = "16ms" , *stepstr = stepdflt ; | |
1530 #endif | |
1531 | |
1532 /* spiral parameters */ | |
1533 | |
1534 static char zerodflt[] = "off" , *zerostr = zerodflt ; | |
1535 static char formdflt[] = "arch" , *formstr = formdflt ; | |
1536 static char origdflt[] = "3.072" , *origstr = origdflt ; | |
1537 | |
1538 static char ArchStr[] = "arch" ; | |
1539 static char LogStr[] = "log" ; | |
1540 | |
1541 static char expodflt[] = "off" , *expostr = expodflt ; | |
1542 | |
1543 /*********** [spl,sai] [sie] stage: "stabilized auditory image" ************/ | |
1544 | |
1545 static Option saiopts[] = { | |
1546 | |
1547 { "frstep_aid", stepdflt, &stepstr, "Step between frames of the auditory image (ms)",InOutOption}, | |
1548 { "pwidth_aid", pwidthdflt, &pwidthstr, "Positive width of auditory image (ms)", InOutOption}, | |
1549 { "nwidth_aid", nwidthdflt, &nwidthstr, "Negative width of auditory image (ms)", InOutOption}, | |
1550 | |
1551 { "form_spd", formdflt, &formstr, "Form of spiral: Archemedian or log", InputOption}, | |
1552 { "zeroline_spd", zerodflt, &zerostr, "Draw zero axis of spiral", InOutOption}, | |
1553 { "orig_spd", origdflt, &origstr, "Spiral rotation and circuit removal\n", InOutOption}, | |
1554 | |
1555 { "napdecay_ai", cgmdflt, &cgmstr, "Neural activity decay rate in %/ms", InOutOption}, | |
1556 { "stdecay_ai", ttdflt, &ttstr, "Strobe-threshold decay rate in %/ms", InOutOption}, | |
1557 {"stcrit_ai", susldflt, &suslevelstr,"Strobe criterion (1 to 5) ", InOutOption}, | |
1558 {"stlag_ai" , stlagdflt, &stlagstr, "Auditory image strobe lag time (in ms)", InOutOption}, | |
1559 { "stthresh_ai", sustdflt, &susthreshstr, "Strobe threshold set to all points above this", SilentOption}, | |
1560 { "decay_ai", decaydflt, &decaystr, "Auditory image decay time constant", InOutOption}, | |
1561 { "stinfo_ai", swdflt, &swstr, "Strobe information (off, on, filename)\n", InOutOption}, | |
1562 | |
1563 { "utrate_ai", utlimdflt, &utlimstr, "Disconnected in R5.6", SilentOption}, | |
1564 { "ltrate_ai", ltlimdflt, <limstr, "Disconnected in R5.6", SilentOption}, | |
1565 { "ulim_sas", ulimdflt, &ulimstr, "Upper integration limit for auditory image", SilentOption}, | |
1566 { "llim_sas", llimdflt, &llimstr, "Lower integration limit for auditory image\n", SilentOption}, | |
1567 | |
1568 { "exponential_decay" , expodflt, &expostr , "Exponential trigger Decay", SilentOption}, | |
1569 | |
1570 ( char * ) 0 } ; | |
1571 | |
1572 /* generate Stabilised image in image.c */ | |
1573 | |
1574 static Source SaiEntry( source ) /* CG */ | |
1575 Source source ; | |
1576 { | |
1577 int framestep = Samples( stepstr, Samplerate() ) / Framestep() ; | |
1578 int pwidth = Samples( pwidthstr, Samplerate() ) / Framestep() ; | |
1579 int nwidth = Samples( nwidthstr, Samplerate() ) / Framestep() ; | |
1580 int stlag = Samples( stlagstr, Samplerate() ) / Framestep() ; | |
1581 | |
1582 | |
1583 /* Convert arguments for spiral drawing. See spiral.ch */ | |
1584 | |
1585 #ifndef DSP32 | |
1586 if (strncmp(formstr, ArchStr, strlen( formstr) ) == 0) form_spl = 'A'; | |
1587 else if (strncmp(formstr, LogStr, strlen( formstr) ) == 0) form_spl = 'L'; | |
1588 else stitch_error("gensai: unknown form_spl\n"); | |
1589 | |
1590 axis_spl = OptionInt( zerostr ) ; | |
1591 zero_spl = OptionDouble( origstr ) ; | |
1592 #endif | |
1593 | |
1594 /* Hack so that spirals never include transient info. */ | |
1595 if (strncmp(whichstr,"spl", strlen("spl")) == 0) | |
1596 { nwidth=0; | |
1597 if ( (int)atoi(suslevelstr)>=4) | |
1598 suslevelstr="3"; | |
1599 /* if ( (int)atoi(suslevelstr)>=4) | |
1600 pwidth+=stlag; | |
1601 else | |
1602 stlag=0; */ | |
1603 } | |
1604 /* Hack so that sas and sep have pwidth=max(ulim) and nwidth=min(llim) */ | |
1605 | |
1606 if ( strcmp(whichstr, "sas") == 0 || strcmp(whichstr, "sep") == 0 ) { | |
1607 pwidth = Cycles( ulimstr, frequencies[0], Samplerate() ) ; | |
1608 nwidth = Cycles( llimstr, frequencies[0], Samplerate() ) ; | |
1609 if (nwidth > 0) nwidth=0; | |
1610 } | |
1611 | |
1612 /* Check ranges of pwidth and nwidth, and quit if invalid */ | |
1613 if (pwidth < 0) | |
1614 stitch_error("Warning: gensai pwidth_aid should be positive\n"); | |
1615 if (nwidth > 0) | |
1616 stitch_error("Warning: gensai nwidth_aid should be zero or negative\n"); | |
1617 | |
1618 /* nwidth is given as a -ve value, but is used internally as +ve */ | |
1619 nwidth = -(nwidth); | |
1620 | |
1621 source = Sai( source, Frameheight(), framestep, pwidth, nwidth, | |
1622 (int)Samples(decaystr, Samplerate())/Framestep(), | |
1623 (int)Samplerate(), frequencies, | |
1624 (double)atof(ttstr), | |
1625 Samples(cgmstr,Samplerate())/Framestep(), | |
1626 (int)Freq(utlimstr), (int)Freq(ltlimstr), (int)atoi(suslevelstr), | |
1627 susthreshstr, swstr, expostr, stlag); | |
1628 | |
1629 setFramewidth( pwidth+nwidth ) ; | |
1630 setFramestep( framestep ) ; | |
1631 setFrames( Frames()/framestep ) ; | |
1632 | |
1633 return( source ) ; | |
1634 } | |
1635 | |
1636 DelayAxis( min, max, label ) | |
1637 double *min, *max ; | |
1638 char **label ; | |
1639 { | |
1640 *min = -Samples( pwidthstr, Samplerate() ) / Samplerate() * 1000. ; | |
1641 *max = -Samples( nwidthstr, Samplerate() ) / Samplerate() * 1000. ; | |
1642 | |
1643 *label = "Integration Interval [ms]" ; | |
1644 } | |
1645 | |
1646 | |
1647 | |
1648 #if 0 /* where did this come from? */ | |
1649 /* table of default model options */ | |
1650 | |
1651 static char llimdflt[] = "3.5", *llimstr = llimdflt ; | |
1652 static char ulimdflt[] = "imagedurn", *ulimstr = ulimdflt ; | |
1653 static char saidflt[] = "0.25", *saistr = saidflt ; | |
1654 /* static char susldflt[] = "1", *suslevelstr = susldflt ; AJD 13-3-95 | |
1655 static char sustdflt[] = "0", *susthreshstr = sustdflt; */ | |
1656 #endif | |
1657 | |
1658 | |
1659 | |
1660 /*********** [sas] [sse] stage: "stabilized auditory spectrogram" **********/ | |
1661 | |
1662 /* summarise spectrogram by adding across rows */ | |
1663 | |
1664 static Option sasopts[] = { | |
1665 | |
1666 ( char * ) 0 } ; | |
1667 | |
1668 static Source SummaryEntry( source ) /* CG */ | |
1669 Source source ; | |
1670 { | |
1671 source = Summary( source, Frameheight(), Scalar( saistr ), frequencies, Samplerate(), llimstr, ulimstr ) ; | |
1672 | |
1673 setFramewidth( 1 ) ; | |
1674 | |
1675 return( source ) ; | |
1676 } | |
1677 | |
1678 #if defined(DSP32) || defined( THINK_C ) | |
1679 static void swab( in, out, bytes ) | |
1680 char *in, *out ; | |
1681 int bytes ; | |
1682 { | |
1683 register int i ; | |
1684 | |
1685 for( i=0 ; i<bytes ; i+=2 ) { | |
1686 out[i+1] = in[i] ; | |
1687 out[i] = in[i+1] ; | |
1688 } | |
1689 | |
1690 return ; | |
1691 } | |
1692 #endif | |
1693 | |
1694 static void swab_callback( state, bytes, buffer, end, input ) | |
1695 Source state ; | |
1696 ByteCount *bytes ; | |
1697 DataType *buffer, *end, *input ; | |
1698 { | |
1699 extern void swab() ; | |
1700 | |
1701 swab( (char *) input, (char *) buffer, *bytes ) ; | |
1702 | |
1703 return ; | |
1704 } | |
1705 | |
1706 static Source SwabEntry( source ) | |
1707 Source source ; | |
1708 { | |
1709 return ( NewSimpleProcessingSource( swab_callback, source, "model.c byte swapping" ) ) ; | |
1710 } | |
1711 | |
1712 struct _test_state { struct _fillable_source parent ; Source source ; unsigned chans ; } ; | |
1713 | |
1714 static Pointer test_callback( state, bytes, buffer ) | |
1715 struct _test_state *state ; | |
1716 ByteCount *bytes ; | |
1717 DataType *buffer ; | |
1718 { | |
1719 register DataType input ; | |
1720 register DataType *optr = buffer ; | |
1721 register Pointer eptr = (Pointer) buffer + *bytes ; | |
1722 register int last = *bytes == 0 ; | |
1723 register int chan ; | |
1724 | |
1725 while( (Pointer) optr < eptr ) { | |
1726 | |
1727 input = *PullItems( state->source, 1, DataType ) ; | |
1728 | |
1729 for( chan=0 ; chan<state->chans ; chan++ ) | |
1730 *optr++ = input ; | |
1731 } | |
1732 | |
1733 if( !last ) | |
1734 return ( (Pointer) buffer ) ; | |
1735 else | |
1736 return ( DeleteFillableSource( state ) ) ; | |
1737 } | |
1738 | |
1739 static Source TestEntry( source ) | |
1740 Source source ; | |
1741 { | |
1742 DeclareNew( struct _test_state *, state ) ; | |
1743 | |
1744 state->source = source ; | |
1745 state->chans = Frameheight() ; | |
1746 | |
1747 return( SetFillableSource( state, test_callback, "test model.c" ) ) ; | |
1748 } | |
1749 | |
1750 /********************* Option defaults (application specific) *************** | |
1751 * Each application may have its own set of option defaults. | |
1752 * These override the generic defaults defined for each option, when the | |
1753 * options table is constructed, (see constructOptions()). | |
1754 * Note that options must have their full names. Abbreviations won't do here. | |
1755 ****************************************************************************/ | |
1756 | |
1757 /* Wave and excitation pattern modules */ | |
1758 | |
1759 #ifndef DSP32 | |
1760 static char zerobotstr[] = "bottom=0" ; | |
1761 static char excitestr[] = "view=excitation" ; | |
1762 static char nohiding[] = "hiddenline=off" ; | |
1763 static char downsample[] = "downsample=10ms" ; | |
1764 static char turn_on_idt[] = "stages_idt=2" ; | |
1765 static char mincfdflt[] = "mincf_afb=50" ; | |
1766 static char maxcfdflt[] = "maxcf_afb=5000" ; | |
1767 static char chandflt[] = "channels_afb=128" ; | |
1768 static char lengthdflt[] = "length=32ms" ; | |
1769 static char greyscalestr[] = "view=greyscale" ; | |
1770 #endif | |
1771 | |
1772 char *wavdflts[] = { | |
1773 #ifndef DSP32 | |
1774 "view=wave", | |
1775 #endif | |
1776 (char *)0 } ; | |
1777 | |
1778 char *stpdflts[] = { /* CG */ | |
1779 #ifndef DSP32 | |
1780 "view=wave", | |
1781 "filter=off", | |
1782 #endif | |
1783 (char *)0 } ; | |
1784 | |
1785 char *asadflts[] = { | |
1786 #ifndef DSP32 | |
1787 excitestr, | |
1788 "top=2500", zerobotstr, | |
1789 nohiding, | |
1790 chandflt, /* CG */ | |
1791 "transduction=off", /* CG */ | |
1792 turn_on_idt, /* CG */ | |
1793 downsample, /* CG */ | |
1794 #endif | |
1795 (char *)0 } ; | |
1796 | |
1797 char *epndflts[] = { | |
1798 #ifndef DSP32 | |
1799 excitestr, | |
1800 "top=1000", zerobotstr, /* CG */ | |
1801 nohiding, | |
1802 chandflt, /* CG */ | |
1803 turn_on_idt, | |
1804 downsample, | |
1805 #endif | |
1806 (char *)0 } ; | |
1807 | |
1808 char *sepdflts[] = { | |
1809 #ifndef DSP32 | |
1810 excitestr, | |
1811 "top=200", zerobotstr, | |
1812 nohiding, | |
1813 chandflt, /* CG */ | |
1814 "ulim_sas=16ms", "llim_sas=-4ms", | |
1815 #endif | |
1816 (char *)0 } ; | |
1817 | |
1818 /* Auditory (ie landscape) modules */ | |
1819 | |
1820 char *bmmdflts[] = { | |
1821 #ifndef DSP32 | |
1822 lengthdflt, | |
1823 "top=100", "bottom=-100", | |
1824 #endif | |
1825 (char *)0 } ; | |
1826 | |
1827 char *napdflts[] = { | |
1828 #ifndef DSP32 | |
1829 lengthdflt, | |
1830 "top=2000", zerobotstr, /* CG */ | |
1831 chandflt, /* CG */ | |
1832 "stages_idt=2", | |
1833 "tup_idt=0.133ms", | |
1834 "downsample=1p", | |
1835 #endif | |
1836 (char *)0 } ; | |
1837 | |
1838 | |
1839 char *saidflts[] = { | |
1840 #ifndef DSP32 | |
1841 "top=500", zerobotstr, /* CG */ | |
1842 "stages_idt=2", | |
1843 "tup_idt=0.133ms", | |
1844 "downsample=1p", | |
1845 "frstep_epn=1p", | |
1846 #endif | |
1847 (char *)0 } ; | |
1848 | |
1849 char *spldflts[] = { | |
1850 #ifndef DSP32 | |
1851 "view=spiral", | |
1852 #ifdef PC | |
1853 "width_win=300", "height_win=300", | |
1854 #else | |
1855 "width_win=500", "height_win=500", | |
1856 #endif | |
1857 "box_ps=off", /* MAA 6/9/1995 */ | |
1858 "figurelinewidth_ps=0.25", /* MAA 6/9/1995 */ | |
1859 "top=26", "bottom=25", | |
1860 "dencf=1", "pen=2", | |
1861 "nwidth_aid=0ms", "pwidth_aid=35ms", | |
1862 "stlag=5ms", "stcrit=5", /* AJD */ | |
1863 #endif | |
1864 (char *)0 } ; | |
1865 | |
1866 /* Speech (ie greyscale) modules */ | |
1867 | |
1868 char *sgmdflts[] = { | |
1869 #ifndef DSP32 | |
1870 greyscalestr, | |
1871 "top=2500", zerobotstr, | |
1872 chandflt, /* CG */ | |
1873 "transduction=off", /* CG */ | |
1874 turn_on_idt, | |
1875 downsample, | |
1876 #endif | |
1877 (char *)0 } ; | |
1878 | |
1879 char *cgmdflts[] = { | |
1880 #ifndef DSP32 | |
1881 greyscalestr, | |
1882 "top=1000", zerobotstr, /* CG */ | |
1883 chandflt, /* CG */ | |
1884 turn_on_idt, | |
1885 downsample, | |
1886 #endif | |
1887 (char *)0 } ; | |
1888 | |
1889 char *sasdflts[] = { | |
1890 #ifndef DSP32 | |
1891 greyscalestr, | |
1892 "top=300", zerobotstr, /* CG */ | |
1893 chandflt, /* CG */ | |
1894 "stages_idt=off", | |
1895 "frstep_epn=off", | |
1896 "downsample=off", | |
1897 "ulim_sas=16ms", "llim_sas=-4ms", | |
1898 #endif | |
1899 (char *)0 } ; | |
1900 | |
1901 | |
1902 | |
1903 /******************************* stage table ******************************** | |
1904 * | |
1905 * The "stages" are application names. | |
1906 * A stage identifier name is the last three chars of the program name. | |
1907 * (Eg "sai" is the stage identifier for the stabilized auditory image | |
1908 * application, which is a program called "gensai". This is an alias for | |
1909 * the "gen" program, provided by one of the set of symbolic links). | |
1910 * The stages are grouped into "models" (each an array of structs below): | |
1911 * envelope: calculation of the envelope of the underlying function. | |
1912 * fine: calculation of the whole ("fine structure") of the function. | |
1913 * complex | |
1914 * nonmult | |
1915 * noncalc | |
1916 * | |
1917 * FindStage( which ) - find a place in the stage table for the program goal. | |
1918 * Take a stage identifier, (contained in the "which" string), and return a ptr | |
1919 * to the corresponding stage structure, (one line of one of the arrays below). | |
1920 * | |
1921 * The returned goal stage is the final processing stage of the sequence of | |
1922 * stages which make up the program. | |
1923 * The sequential order of processing is dictated by the stage table. | |
1924 * The sequence of stages is from the first stage (texually at the bottom of | |
1925 * each "model" group in the stage table), through each stage back up the table | |
1926 * to the goal stage. | |
1927 * | |
1928 * The stage structure (defined below) is as follows: | |
1929 * struct _stage { | |
1930 * char *ident ; Stage identifier name | |
1931 * Source (*entry)() ; Pointer to function for entry to stage | |
1932 * Option *options ; Model options for stage (see table.c) | |
1933 * char **defaults ; Option defaults for stage (see gen.c) | |
1934 * char *help ; Description of stage | |
1935 * }; | |
1936 * | |
1937 * For example, the sai stage (found when gensai is asked for) is: | |
1938 * "sai", SaiEntry, saiopts, saidflts, "stabilized auditory image", | |
1939 * | |
1940 * The stage struct fields are: | |
1941 * | |
1942 * *ident | |
1943 * Stage identifier name used by FindStage() to match a stage struct to the | |
1944 * application. The stage is found by matching the ident string against those | |
1945 * stored in the model arrays of stages. The default stage is "wav". | |
1946 * | |
1947 * (*entry)() | |
1948 * The name of the entry-point function for the stage. Most entry-point | |
1949 * functions are defned in model.c. The entry-point function name is only | |
1950 * accessed by a call to FindStage() from ModeledSource() in gen.c. | |
1951 * | |
1952 * *options | |
1953 * The options field of a stage is used by the constructOptions() routine | |
1954 * to include the model options for that stage in the complete options table | |
1955 * which it constructs. This is composed of the display options, (which are | |
1956 * common to all applications, and are listed in array displayopts[] in gen.c), | |
1957 * the model options for the stage, (which are listed in table.c), AND all the | |
1958 * model options given for each of the stages back to the start stage, (at the | |
1959 * bottom of the stage table, within a model group of stages). | |
1960 * | |
1961 * **defaults | |
1962 * The defaults field is used by the constructOptions() routine to override the | |
1963 * defaults defined for the options which have been included in the complete | |
1964 * options table. The reason for this is so that each application can have its | |
1965 * own set of option defaults, if necessary. (If defaults are not given | |
1966 * or the set is not complete, then the original defaults still apply). | |
1967 * The defaults fields contain option defaults which override the generic | |
1968 * defaults defined for each option. | |
1969 * After the complete options table has been constructed, (constructOptions()), | |
1970 * all options in the table will be: | |
1971 * a) initialized to their default values (in getnopts()). | |
1972 * b) re-initialized by any corresponding options in "rc" files. | |
1973 * c) displayed as a help menu (if asked for). | |
1974 * | |
1975 * *help | |
1976 * This message is printed at the top of the help menu. The help field is only | |
1977 * accessed by modelHelp(which), called from gen.c, which takes a stage | |
1978 * identifier and returns the "help" string of the stage struct which has a | |
1979 * matching ident field, to assign it to "helpstring". | |
1980 * | |
1981 * | |
1982 * Its important to note that the options field refers to model options, and | |
1983 * these are cumulative over the sequential stages of processing. | |
1984 * The defaults field refers to the defaults to be used for the goal stage | |
1985 * only, (ie the application), and these are not cumulative. | |
1986 * The complete options table (constructed at run time) consists of the display | |
1987 * options, and the accumulated model options (one group per processing stage). | |
1988 * | |
1989 * The NullEntry routine is a dummy which does no processing, and is used to | |
1990 * introduce aliases into the stage sequence. | |
1991 * | |
1992 * Routines which call FindStage(), and access the stage table: | |
1993 * | |
1994 * main() | |
1995 * | | |
1996 * +----------------------+-----------------+ | |
1997 * | | | | |
1998 * | | | | |
1999 * constructOptions() ModeledSource() modelHelp() | |
2000 * | | | | |
2001 * | | | | |
2002 * +----------------------+-----------------+ | |
2003 * | | |
2004 * FindStage() | |
2005 * | |
2006 ****************************************************************************/ | |
2007 | |
2008 | |
2009 #define NO_OPTS (Option *) 0 | |
2010 #define NO_DFLTS (char **) 0 | |
2011 | |
2012 struct _stage *FindStage( which ) | |
2013 char *which ; | |
2014 { | |
2015 static struct _stage envelope[] = { | |
2016 "sse", SummaryEntry, sasopts, sasdflts, "stabilized auditory spectrogram", | |
2017 "sie", SaiEntry, saiopts, saidflts, "stabilized auditory image", | |
2018 "sem", NullEntry, NO_OPTS, NO_DFLTS, "spectrogram", | |
2019 "fed", DownSampleEntry, dwnopts, NO_DFLTS, "downsampled filter envelope", | |
2020 "fei", IntegralEntry, fbiopts, NO_DFLTS, "integrated filter envelope", | |
2021 "feh", HardEntry, fbhopts, NO_DFLTS, "hard limited filter envelope", | |
2022 "fea", AdaptEntry, fbaopts, NO_DFLTS, "adapted filter envelope", | |
2023 "fet", ThresholdEntry, fbtopts, NO_DFLTS, "thresholded filter envelope", | |
2024 "fel", LowpassEntry, fblopts, NO_DFLTS, "low-pass filtered filter envelope", | |
2025 "fes", SaturateEntry, fbsopts, NO_DFLTS, "saturated filter envelope", | |
2026 "feu", UncompressEntry, fbuopts, NO_DFLTS, "uncompressed filter envelope", | |
2027 "fec", EnvelopeEntry, fbcopts, NO_DFLTS, "compressed filter envelope", | |
2028 "fem", NullEntry, fbmopts, NO_DFLTS, "dummy entry to get options through", | |
2029 "wav", NullEntry, wavopts, wavdflts, "picture of wave", | |
2030 ( char * ) 0 } ; | |
2031 | |
2032 static struct _stage fine[] = { | |
2033 "sep", NullEntry, NO_OPTS, sepdflts, "stabilized excitation pattern", | |
2034 "sas", SummaryEntry, sasopts, sasdflts, "stabilized auditory spectrogram", | |
2035 "spl", NullEntry, NO_OPTS, spldflts, "spiral stabilized auditory image", | |
2036 "sai", SaiEntry, saiopts, saidflts, "stabilized auditory image", | |
2037 "sgm", NullEntry, NO_OPTS, sgmdflts, "spectrogram", | |
2038 "cgm", NullEntry, NO_OPTS, cgmdflts, "cochleogram", | |
2039 "nap", NullEntry, NO_OPTS, napdflts, "neural activity pattern", | |
2040 "asa", NullEntry, NO_OPTS, asadflts, "auditory spectral analysis", | |
2041 "epn", NullEntry, NO_OPTS, epndflts, "excitation pattern", | |
2042 "fbd", DownSampleEntry, dwnopts, NO_DFLTS, "downsampled filter output", | |
2043 "fbi", IntegralEntry, fbiopts, NO_DFLTS, "integrated filter output", | |
2044 "fbh", HardEntry, fbhopts, NO_DFLTS, "hard limited filter output", | |
2045 "fba", AdaptEntry, fbaopts, NO_DFLTS, "adapted transduced filter output", | |
2046 "fbt", ThresholdEntry, fbtopts, NO_DFLTS, "thresholded filter output", | |
2047 "fbl", LowpassEntry, fblopts, NO_DFLTS, "low-pass filtered filter output", | |
2048 "fbs", SaturateEntry, fbsopts, NO_DFLTS, "saturated filter output", | |
2049 "fbu", UncompressEntry, fbuopts, NO_DFLTS, "uncompressed filter output", | |
2050 "fbc", LogEntry, fbcopts, NO_DFLTS, "compressed filter output", | |
2051 "fbr", RectifyEntry, fbropts, NO_DFLTS, "rectified filter output", | |
2052 "fbm", NullEntry, NO_OPTS, NO_DFLTS, "auditory filter output", /* CG */ | |
2053 "stp", FineEntry, fbmopts, stpdflts, "stapes vibration output", /* CG */ | |
2054 "wav", NullEntry, wavopts, wavdflts, "picture of wave", | |
2055 ( char * ) 0 } ; | |
2056 | |
2057 static struct _stage complex[] = { | |
2058 "fcp", PolarEntry, NO_OPTS, NO_DFLTS, "polar co-ordinate complex output", | |
2059 "fcr", ComplexEntry, fbmopts, NO_DFLTS, "rectangular co-ordinate complex output", | |
2060 "wav", NullEntry, wavopts, wavdflts, "picture of wave", | |
2061 ( char * ) 0 } ; | |
2062 | |
2063 static struct _stage nonmult[] = { | |
2064 "bmm", NullEntry, NO_OPTS, bmmdflts, "basilar membrane motion", /* CG */ | |
2065 "stp", FineEntry, fbmopts, stpdflts, "stapes vibration output", /* CG */ | |
2066 "wav", NullEntry, wavopts, wavdflts, "draw wave", | |
2067 ( char * ) 0 } ; | |
2068 | |
2069 static struct _stage noncalc[] = { | |
2070 "tst", TestEntry, NO_OPTS, NO_DFLTS, "Test system", | |
2071 "wav", NullEntry, wavopts, wavdflts, "draw wave", | |
2072 ( char * ) 0 } ; | |
2073 | |
2074 static struct _stage *models[] = { envelope, fine, complex, nonmult, noncalc, ( struct _stage * ) 0 } ; | |
2075 | |
2076 struct _stage *stage ; | |
2077 int model ; | |
2078 | |
2079 /* for each type of model */ | |
2080 for( model=0 ; models[ model ] != ( struct _stage * ) 0 ; model++ ) | |
2081 /* for each stage in the model */ | |
2082 for( stage=models[ model ] ; stage->ident != ( char * ) 0 ; stage++ ) | |
2083 if( strncmp( which, stage->ident, strlen( stage->ident ) ) == 0 ) { | |
2084 | |
2085 /* kludge to fix bug (see fixchans routine below) */ | |
2086 if ( strcmp( which, "nap" ) == 0 ) | |
2087 fixchans( stage->defaults ) ; | |
2088 | |
2089 return ( stage ) ; | |
2090 } | |
2091 | |
2092 return ( FindStage( "wav" ) ) ; | |
2093 } | |
2094 | |
2095 /* Return the "help" string for the given stage identifier */ | |
2096 /* This routine is called once from gen.c:main() */ | |
2097 char *modelHelp( which ) | |
2098 char *which ; | |
2099 { | |
2100 return( FindStage( which )->help ) ; | |
2101 } | |
2102 | |
2103 | |
2104 /* | |
2105 This routine is a hack to fix a bug we caused earlier! | |
2106 We changed the order of entry points in Findstage, so that nap was able | |
2107 to use the lp filter. But this caused nap to inherit the defaults of all | |
2108 the other entry points which use that filter. In particular, the number of | |
2109 channels for nap was changed as a result of this. This hack is designed to | |
2110 restore the number chans, in the case of gennap only, to their default | |
2111 value. | |
2112 */ | |
2113 | |
2114 fixchans( str ) | |
2115 char **str ; | |
2116 { | |
2117 while ( *str != (char *)0 ) { | |
2118 if ( strncmp( *str, "channels_afb", 12 ) == 0 ) { | |
2119 strcpy( (*str)+13, chansdflt ) ; | |
2120 /* fprintf(stderr, "fixchans: %s\n", *str ) ; */ | |
2121 break ; | |
2122 } | |
2123 *str++ ; | |
2124 } | |
2125 } | |
2126 | |
2127 | |
2128 /*********************** Strings for use in DSP version ********************/ | |
2129 | |
2130 #if defined(DSPHOST) || defined(DSP32) | |
2131 #if 00 | |
2132 char **shared[] = { &llimstr, &ulimstr, &saistr, &pwidthstr, | |
2133 &nwidthstr, <limstr, &utlimstr, &ttstr, | |
2134 &cgmstr, &decaystr, &stepstr, &downsstr, | |
2135 &stagestr, &upstr, &downstr, &lossstr, | |
2136 &vlossstr, &igainstr, &hardstr, &adapstr, | |
2137 ×str, &vdrainstr, &propstr, &faststr, | |
2138 &latstr, &rapidstr, &risestr, &stxstr, | |
2139 &lstagestr, &lupstr, &ldownstr, &llossstr, | |
2140 &lvlossstr, &ligainstr, &meddisstr, &satstr, | |
2141 &logstr, &rectstr, &qualstr, &limitstr, | |
2142 &interpstr, &minstr, &maxstr, &denstr, | |
2143 &chansstr, &orderstr, &phasestr, &gainstr, | |
2144 &audiostr, &floatstr, &samplestr, &bitstr, | |
2145 &envstr, &whichstr, &framesstr, &framebytesstr, | |
2146 &framewidthstr, &frameheightstr, &framestepstr, | |
2147 ( char ** ) 0 } ; | |
2148 #endif | |
2149 char **returned[] = { &framesstr, &framebytesstr, &framewidthstr, | |
2150 &frameheightstr, &framestepstr, | |
2151 ( char ** ) 0 } ; | |
2152 | |
2153 #endif | |
2154 | |
2155 | |
2156 /******* support for DSP32 C ******************/ | |
2157 | |
2158 #ifdef DSP32 | |
2159 void receiveParameters( parameters, psize ) | |
2160 char *parameters ; | |
2161 short psize ; | |
2162 { | |
2163 struct _stage *stage = FindStage( "sas" ), *sptr ; | |
2164 char *bptr ; | |
2165 int c ; | |
2166 | |
2167 for( sptr = stage ; sptr->ident != (char *) 0 ; sptr++ ) | |
2168 ; | |
2169 | |
2170 sptr-- ; | |
2171 | |
2172 for( bptr = parameters ; bptr < parameters + psize ; sptr-- ) | |
2173 if( sptr->options != (Option *) 0 ) | |
2174 for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) { | |
2175 *(sptr->options[c].value) = bptr ; | |
2176 bptr += strlen( bptr ) + 1 ; | |
2177 } | |
2178 | |
2179 return ; | |
2180 } | |
2181 #endif | |
2182 | |
2183 #ifdef DSPHOST | |
2184 #include "utils.h" | |
2185 #define DSP_BIN_VAR "DSPBIN" | |
2186 #define DEFAULT_DSP_BIN "c:\\bin\\dspmain" | |
2187 extern char *getenv() ; | |
2188 | |
2189 void sendParameters( which ) | |
2190 char *which ; | |
2191 { | |
2192 register struct _stage *stage = FindStage( which ), *sptr ; | |
2193 unsigned c, bytes = 0 ; | |
2194 char *buffer, *bptr ; | |
2195 long paddr, baddr ; | |
2196 | |
2197 for( sptr = stage ; sptr->ident != (char *) 0 ; sptr++ ) | |
2198 if( sptr->options != (Option *) 0 ) | |
2199 for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) | |
2200 bytes += strlen( *(sptr->options[c].value) ) + 1 ; | |
2201 | |
2202 sptr-- ; | |
2203 | |
2204 buffer = Allocate( bytes, "argument array model.c" ) ; | |
2205 | |
2206 for( bptr = buffer ; sptr >= stage ; sptr-- ) | |
2207 if( sptr->options != (Option *) 0 ) | |
2208 for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) { | |
2209 (void) strcpy( bptr, *(sptr->options[c].value) ) ; | |
2210 bptr += strlen( bptr ) + 1 ; | |
2211 } | |
2212 | |
2213 | |
2214 paddr = find_label_name( "psize" ) ; | |
2215 | |
2216 dsp_dl_int( paddr, (int) ( bptr - buffer ) ) ; | |
2217 | |
2218 baddr = find_label_name( "params" ) ; | |
2219 | |
2220 while( dsp_up_long( baddr ) == 0 ) | |
2221 ; | |
2222 | |
2223 dsp_dl_bytes( deref( baddr ), (long) ( bptr - buffer ), buffer ) ; | |
2224 | |
2225 dsp_dl_int( paddr, 0 ) ; | |
2226 | |
2227 return ; | |
2228 } | |
2229 | |
2230 | |
2231 struct _dsp_state { unsigned long needed_addr, output_addr, errno_addr ; } ; | |
2232 | |
2233 static void dsp_callback( state, bytes, buffer ) | |
2234 struct _dsp_state *state ; | |
2235 ByteCount bytes ; | |
2236 Pointer buffer ; | |
2237 { | |
2238 char errbuff[200] ; | |
2239 | |
2240 /* tell dsp how much you want */ | |
2241 | |
2242 dsp_dl_int( state->needed_addr, bytes ) ; | |
2243 | |
2244 /* wait for it to provide it */ | |
2245 | |
2246 while( dsp_up_int( state->needed_addr ) != 0 ) | |
2247 if( dsp_up_int( state->errno_addr ) != 0 ) { | |
2248 /* | |
2249 if( dispw != ( WindowObject ) 0 ) Close( dispw ) ; | |
2250 */ | |
2251 dsp_up_bytes( find_label_name( "errstr" ), (long) sizeof ( errbuff ), errbuff ) ; | |
2252 printf( "freemem %ld stackmax %lx\n", | |
2253 dsp_up_long( find_label_name( "freemem" ) ), | |
2254 dsp_up_long( find_label_name( "stackmax" ) ) ) ; | |
2255 stitch_error( errbuff, dsp_up_int( find_label_name( "errno" ) ) ) ; | |
2256 } | |
2257 | |
2258 /* upload it into PC buffer */ | |
2259 | |
2260 dsp_up_bytes( deref( state->output_addr ), (long) bytes, buffer ) ; | |
2261 | |
2262 return ; | |
2263 } | |
2264 | |
2265 Source DspSource( source ) | |
2266 Source source ; | |
2267 { | |
2268 DeclareNew( struct _dsp_state *, state ) ; | |
2269 unsigned long addr ; | |
2270 char errbuff[200] ; | |
2271 char ***param ; | |
2272 char *binary_path = getenv( DSP_BIN_VAR ) ; | |
2273 | |
2274 if( binary_path == ( char * ) 0 ) | |
2275 binary_path = DEFAULT_DSP_BIN ; | |
2276 | |
2277 /* load dsp */ | |
2278 | |
2279 (void) fprintf( stderr, "Downloading %s to DSP32 at i/o addres 0x%x\n", binary_path, default_addr() ) ; | |
2280 | |
2281 if( dsp_dl_exec( binary_path ) == 0 ) | |
2282 stitch_error( "\nDSP load failed\n" ) ; | |
2283 | |
2284 /* start dsp */ | |
2285 | |
2286 dsp_run() ; | |
2287 | |
2288 /* send parameters down to model */ | |
2289 | |
2290 sendParameters( whichstr ) ; | |
2291 | |
2292 /* send down input if required */ | |
2293 | |
2294 if( whichstr[0] != 'i' ) { | |
2295 | |
2296 addr = find_label_name( "input" ) ; | |
2297 | |
2298 while( dsp_up_long( addr ) == 0 ) | |
2299 ; | |
2300 | |
2301 (void) fprintf( stderr, "Downloading input file of %ld points to dsp addres 0x%lx\n", Frames(), deref( addr ) ) ; | |
2302 | |
2303 dsp_dl_array( deref( addr ), Frames(), PullInts( source, Frames() ) ) ; | |
2304 } | |
2305 | |
2306 /* wait for model setup */ | |
2307 | |
2308 state->needed_addr = find_label_name( "needed" ) ; | |
2309 state->output_addr = find_label_name( "output" ) ; | |
2310 state->errno_addr = find_label_name( "errno" ) ; | |
2311 | |
2312 addr = find_label_name( "source" ) ; | |
2313 | |
2314 while( dsp_up_long( addr ) == 0l && dsp_up_int( state->errno_addr ) == 0 ) | |
2315 (void) fprintf( stderr, "Waiting for dsp (status:%d)\r", dsp_up_long( addr ) ) ; | |
2316 | |
2317 if( dsp_up_int( state->errno_addr ) != 0 ) { | |
2318 dsp_up_bytes( find_label_name( "errstr" ), (long) sizeof ( errbuff ), errbuff ) ; | |
2319 (void) fprintf( stderr, "dsp error: %s\n", errbuff ) ; | |
2320 stitch_error( "so there" ) ; | |
2321 } | |
2322 | |
2323 (void) fprintf( stderr, "DSP setup (source=0x%lx)\n", dsp_up_long( addr ) ) ; | |
2324 | |
2325 addr = find_label_name( "returned" ) ; | |
2326 | |
2327 for( param=returned ; *param != ( char ** ) 0 ; param++ ) { | |
2328 | |
2329 dsp_up_bytes( deref( deref( addr ) ), RETURN_SIZE, **param ) ; | |
2330 addr += 4 ; | |
2331 } | |
2332 #if 0 | |
2333 fprintf( stderr, "Frames %ld - %d %d %d\n\nType Return\n", Frames(), Frameheight(), Framewidth(), Framebytes() ) ; | |
2334 getchar() ; | |
2335 #endif | |
2336 return ( stdAutoSource( ( Pointer ) state, dsp_callback ) ) ; | |
2337 } | |
2338 | |
2339 #endif | |
2340 | |
2341 /*************************************************************************** | |
2342 * ModeledSource() | |
2343 * Called from main() in gen.c to initialize a chain of objects which will | |
2344 * ultimately execute the program, (see also SinkSource() in gen.c:main). | |
2345 * | |
2346 * The routine ModeledSource() first uses Findstage() to find the appropriate | |
2347 * place in the stage table, called for by the program, (and indicated by | |
2348 * "whichstr", the last three chars of the program's name). | |
2349 * Then it finds the end of the table, and works back up to the stage called | |
2350 * for by the program. | |
2351 * At each stage, call the corresponding entry-point function, (provided it's | |
2352 * not a null pointer), to create and initialize a source object. | |
2353 * (Each stage in the table is a process on the way to the program as a whole. | |
2354 * The order of the stage table sets the order of processing). | |
2355 * | |
2356 * The "check" argument is used when the "useprevious" option is on, | |
2357 * (see main() and checkForFile() in gen.c), otherwise it will be a null ptr. | |
2358 ***************************************************************************/ | |
2359 | |
2360 Source ModeledSource( source, check ) | |
2361 Source source ; | |
2362 Source (*check)() ; | |
2363 { | |
2364 /* Find the place in the stage table called for by the program */ | |
2365 register struct _stage *sptr, *stage = FindStage( whichstr ) ; | |
2366 Source stmp ; | |
2367 | |
2368 #if !defined( DSP32 ) && !defined( THINK_C ) | |
2369 if( OptionInt( swapstr ) != 0 ) | |
2370 source = SwabEntry( source ) ; | |
2371 #endif | |
2372 | |
2373 #ifdef DSPHOST | |
2374 if( getenv( "DSP32" ) != ( char * ) 0 ) | |
2375 return ( DspSource( source ) ) ; | |
2376 else | |
2377 (void) fprintf( stderr, "Not using DSP card\n" ) ; | |
2378 #endif | |
2379 | |
2380 if( stage->entry == ( Source ( * )() ) 0 ) | |
2381 return ( source ) ; | |
2382 #if 00 | |
2383 /* Set frameheight (channels) and centre-frequencies array */ | |
2384 updateFrequencies() ; | |
2385 #endif | |
2386 | |
2387 #ifdef FLOAT | |
2388 source = ShortFloatSource( source ) ; | |
2389 #endif | |
2390 | |
2391 /* Find the end of the stage table */ | |
2392 for( sptr = stage ; sptr->ident != ( char * ) 0 ; sptr++ ) | |
2393 ; | |
2394 | |
2395 /* Work back up the stage table to the stage called for by the program */ | |
2396 /* At each stage, call the entry-point function (if it's not null) */ | |
2397 while( sptr-- > stage ) { | |
2398 | |
2399 if( sptr->entry != (Source ( * )()) 0 ) | |
2400 source = sptr->entry( source ) ; | |
2401 | |
2402 if( check != ( Source ( * )() ) 0 ) { | |
2403 stmp = check( sptr->ident ) ; | |
2404 if( _SPTR( stmp ) != (struct _source *) 0 ) { | |
2405 | |
2406 #ifdef FLOAT | |
2407 source = ShortFloatSource( stmp ) ; | |
2408 #else | |
2409 source = stmp ; | |
2410 #endif | |
2411 /* Set frameheight (channels) and centre-frequencies array */ | |
2412 updateFrequencies() ; | |
2413 } | |
2414 } | |
2415 } | |
2416 | |
2417 #ifdef FLOAT | |
2418 source = FloatShortSource( source ) ; | |
2419 #endif | |
2420 | |
2421 setFrames( Frames() ) ; | |
2422 | |
2423 return ( source ) ; | |
2424 } | |
2425 | |
2426 |