tomwalters@0: /* tomwalters@0: Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 tomwalters@0: =========================================================================== tomwalters@0: tomwalters@0: Permission to use, copy, modify, and distribute this software without fee tomwalters@0: is hereby granted for research purposes, provided that this copyright tomwalters@0: notice appears in all copies and in all supporting documentation, and that tomwalters@0: the software is not redistributed for any fee (except for a nominal shipping tomwalters@0: charge). Anyone wanting to incorporate all or part of this software in a tomwalters@0: commercial product must obtain a license from the Medical Research Council. tomwalters@0: tomwalters@0: The MRC makes no representations about the suitability of this tomwalters@0: software for any purpose. It is provided "as is" without express or implied tomwalters@0: warranty. tomwalters@0: */ tomwalters@0: tomwalters@0: /* tomwalters@0: model.c tomwalters@0: ===== tomwalters@0: tomwalters@0: APU, ASP model demonstration program. tomwalters@0: tomwalters@0: tomwalters@0: Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit. tomwalters@0: tomwalters@0: tomwalters@0: Author : John Holdsworth tomwalters@0: Written : 22th March, 1989. tomwalters@0: tomwalters@0: Edited : Mike Allerhand, 1990. tomwalters@0: tomwalters@0: Edited : Roy Patterson, 1992. Changed default values from time to time. tomwalters@0: tomwalters@0: Edited : MAA 10th June 1993 tomwalters@0: Allowed pwidth=0 tomwalters@0: tomwalters@0: Edited : Christian Giguere, March 1994. tomwalters@0: - Added tools for manipulating sampling rate and scaling data tomwalters@0: - Added in an Entry Point for the outer/middle ear function tomwalters@0: - Added in an Entry Point for the transmission line filterbank tomwalters@0: - Implemented a completely new version of Meddis(). tomwalters@0: Files "haircell.h, haircell.c " tomwalters@0: - Changed option "scale_at" into "gain_at". tomwalters@0: That option is now passed to newCorti() as a double instead of an integer tomwalters@0: In Corti(), this meant multiplying *optr by state->scale tomwalters@0: - Provided facilities to print filterbank information to stderr via tomwalters@0: option info_afb. This supersedes option erbscale_afb. tomwalters@0: - Changed some default values tomwalters@0: - To locate changes, search for "CG" tomwalters@0: tomwalters@0: Edited : Jay Datta, November 1994. tomwalters@0: Added the stcrit options. tomwalters@0: tomwalters@0: : Jay Datta, March 1995. tomwalters@0: Added a function Nwidth() which returns the number tomwalters@0: of sample points of the nwidth section of a SAI. tomwalters@0: : Silenced ulim_sas and llim_sas. tomwalters@0: : Changed trise_at default to 1000 from 10000. May, 1995. tomwalters@0: : Changed trise_at default to 10000 from 1000. May, 1995. tomwalters@0: : Separated nwidth and strobe lag by creating a new tomwalters@0: option called stlag_ai. May, 1995. tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: /*************************************************************************** tomwalters@0: * This module contains: tomwalters@0: * Routines to access or modify string values. tomwalters@0: * Unit conversion routines. tomwalters@0: * Model entry-point functions. tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: #include tomwalters@0: #include tomwalters@0: #include tomwalters@0: tomwalters@0: #ifdef THINK_C tomwalters@0: #include tomwalters@0: #endif tomwalters@0: tomwalters@0: /* interfaces to stitch system */ tomwalters@0: tomwalters@0: #include "options.h" tomwalters@0: tomwalters@0: #include "stitch.h" tomwalters@0: #include "source.h" tomwalters@0: #include "funcs.h" tomwalters@0: #include "units.h" tomwalters@0: #include "calc.h" tomwalters@0: #if defined( DSP32 ) || defined( PC ) tomwalters@0: #include "oops.h" tomwalters@0: #else tomwalters@0: #include "ops.h" tomwalters@0: #endif tomwalters@0: #include "io.h" tomwalters@0: tomwalters@0: /* interface to model modules */ tomwalters@0: tomwalters@0: #include "gamma_tone.h" tomwalters@0: #include "integrate.h" tomwalters@0: #include "formulae.h" /* CG: removed haircell.h */ tomwalters@0: #include "recurse.h" tomwalters@0: #include "scales.h" tomwalters@0: #include "spiral.h" tomwalters@0: #include "model.h" tomwalters@0: #include "corti.h" tomwalters@0: #include "image.h" tomwalters@0: #include "bank.h" tomwalters@0: tomwalters@0: /* interface to WDF module */ /* CG */ tomwalters@0: tomwalters@0: #include "formulae_tl.h" tomwalters@0: #include "upsample.h" tomwalters@0: #include "bank_tl.h" tomwalters@0: #include "calc_tl.h" tomwalters@0: #include "meddis.h" tomwalters@0: #include "ear.h" tomwalters@0: tomwalters@0: /********************* Model option parameter strings *********************** tomwalters@0: * The strings are defined, allocated static array space, and initialized to tomwalters@0: * default values. tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: #ifndef lint tomwalters@0: static char *sccs_id = "@(#)model.c 1.49 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 12/23/92" ; tomwalters@0: #endif tomwalters@0: tomwalters@0: /* which model to use */ tomwalters@0: tomwalters@0: char whichdflt[] = "none" , *whichstr = whichdflt ; tomwalters@0: char sampledflt[] = "20000." , *samplestr = sampledflt ; tomwalters@0: tomwalters@0: /* input properties */ tomwalters@0: tomwalters@0: static char dBdflt[] = "60." , *dBstr = dBdflt ; /* CG */ tomwalters@0: static char bitsdflt[] = "12" , *bitstr = bitsdflt ; tomwalters@0: static char swapdflt[] = "off" , *swapstr = swapdflt ; tomwalters@0: tomwalters@0: tomwalters@0: /************************ File-format strings ****************************** tomwalters@0: * The strings are defined, allocated static array space, and initialized to tomwalters@0: * default values. tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: #define RETURN_SIZE 50l tomwalters@0: tomwalters@0: static char framesbuff[RETURN_SIZE] = "0", *framesstr = framesbuff ; tomwalters@0: static char bytesbuff[RETURN_SIZE] = "1", *framebytesstr = bytesbuff ; tomwalters@0: static char widthbuff[RETURN_SIZE] = "1", *framewidthstr = widthbuff ; tomwalters@0: static char heightbuff[RETURN_SIZE] = "1", *frameheightstr = heightbuff ; tomwalters@0: static char stepbuff[RETURN_SIZE] = "1", *framestepstr = stepbuff ; tomwalters@0: static char nwidthdflt[] = "-5ms" , *nwidthstr = nwidthdflt ; /* roy 23-12-92 */ tomwalters@0: static char stlagdflt[] = "5ms" , *stlagstr = stlagdflt ; /* jay 16-05-95 */ tomwalters@0: static char susldflt[] = "5" , *suslevelstr = susldflt ; /* jay 30-08-95 */ tomwalters@0: /************************ File-format strings ******************************* tomwalters@0: * tomwalters@0: * The data which flows through the model is called a "file". tomwalters@0: * This is in an array which is structured or formatted according to the way tomwalters@0: * data is interpreted as it is pulled from each particular source. tomwalters@0: * The array is formatted into "frames", described by the file-format strings. tomwalters@0: * The format may be as successive points, (in which case each frame is a tomwalters@0: * single point with unit width and height), or the format may be as successive tomwalters@0: * 2-dimensional arrays, (in which case each frame is an array divided into tomwalters@0: * rows and columns). tomwalters@0: * tomwalters@0: * The strings are defined, allocated static array space, and initialized in tomwalters@0: * gen.c. A set of convenience routines (see below) are given to access or to tomwalters@0: * reset the value of a string. This enables the file format to be set up on tomwalters@0: * the fly, depending upon the format of the data passing through the source. tomwalters@0: * tomwalters@0: * string: access: reset: comment: tomwalters@0: * framesstr Frames setFrames num frames in file tomwalters@0: * framebytesstr Framebytes setFramebytes num bytes in frame tomwalters@0: * framewidthstr Framewidth setFramewidth num points along frame width tomwalters@0: * frameheightst Frameheight setFrameheight num points along frame height tomwalters@0: * framestepstr Framestep setFramestep num points between successive frames tomwalters@0: * tomwalters@0: * Access routines for file-format strings: tomwalters@0: * Frames returns value of "framesstr", (initially 0) tomwalters@0: * Framebytes returns value of "framebytesstr", (initially 1) tomwalters@0: * Framewidth returns value of "framewidthstr", (initially 1) tomwalters@0: * Frameheight returns value of "frameheightstr", (initially 1) tomwalters@0: * Framestep returns value of "framestepstr", (initially 1) tomwalters@0: * tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: long Frames() tomwalters@0: { tomwalters@0: return ( atoi( framesstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int Framebytes() tomwalters@0: { tomwalters@0: return ( atoi( framebytesstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int Framewidth() tomwalters@0: { tomwalters@0: return ( atoi( framewidthstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int Frameheight() tomwalters@0: { tomwalters@0: return ( atoi( frameheightstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int Framestep() tomwalters@0: { tomwalters@0: return ( atoi( framestepstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int Nwidth() tomwalters@0: { tomwalters@0: int abc = (Samples(stlagstr, Samplerate())); tomwalters@0: if ( (int)atoi(suslevelstr)>=4) tomwalters@0: /* fprintf(stderr, "Nwidth is %d\n", -abc); */ tomwalters@0: return (-abc); tomwalters@0: else tomwalters@0: return 0; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /******************* Value-to-string conversion routines. ******************/ tomwalters@0: char *ltoa( val, buffer ) tomwalters@0: long val ; tomwalters@0: char *buffer ; tomwalters@0: { tomwalters@0: (void) sprintf( buffer, "%ld", val ) ; tomwalters@0: tomwalters@0: return ( buffer ) ; tomwalters@0: } tomwalters@0: tomwalters@0: char *itoa( val, buffer ) tomwalters@0: int val ; tomwalters@0: char *buffer ; tomwalters@0: { tomwalters@0: (void) sprintf( buffer, "%d", val ) ; tomwalters@0: tomwalters@0: return ( buffer ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /******************* Reset routines for file-format strings **************** tomwalters@0: * Convert argument (newval) to a string, and copy into the specific tomwalters@0: * file-format string. tomwalters@0: * setFrames resets "framesstr", (initially 0) tomwalters@0: * setFramebytes resets "framebytesstr", (initially 1) tomwalters@0: * setFramewidth resets "framewidthstr", (initially 1) tomwalters@0: * setFrameheight resets "frameheightstr", (initially 1) tomwalters@0: * setFramestep resets "framestepstr", (initially 1) tomwalters@0: * tomwalters@0: * updateFramebytes sets "framebytesstr" to the total number of bytes in tomwalters@0: * the frame, (ie current width * height). tomwalters@0: * tomwalters@0: * Note: updateFramebytes is automatically done at the end of each call to tomwalters@0: * setFramewidth or setFrameheight, to reset the "framebytesstr" to tomwalters@0: * account for the new frame size. tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: void setFrames( newval ) tomwalters@0: long newval ; tomwalters@0: { tomwalters@0: framesstr = ltoa( newval, framesbuff ) ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: void setFramebytes( newval ) tomwalters@0: int newval ; tomwalters@0: { tomwalters@0: framebytesstr = itoa( newval, bytesbuff ) ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: void updateFramebytes() tomwalters@0: { tomwalters@0: setFramebytes( Framewidth() * Frameheight() * sizeof ( short ) ) ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: void setFramewidth( newval ) tomwalters@0: int newval ; tomwalters@0: { tomwalters@0: framewidthstr = itoa( newval, widthbuff ) ; tomwalters@0: updateFramebytes() ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: void setFrameheight( newval ) tomwalters@0: int newval ; tomwalters@0: { tomwalters@0: frameheightstr = itoa( newval, heightbuff ) ; tomwalters@0: updateFramebytes() ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: void setFramestep( newval ) tomwalters@0: int newval ; tomwalters@0: { tomwalters@0: framestepstr = itoa( newval, stepbuff ) ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: static Option wavopts[] = { tomwalters@0: tomwalters@0: { "framebytes", bytesbuff, &framebytesstr, "framebytes - internal", SilentOption}, tomwalters@0: { "framebytes", bytesbuff, &framebytesstr, "framebytes - internal", OutputOption}, tomwalters@0: { "frameheight", heightbuff, &frameheightstr, "frameheight - internal", SilentOption}, tomwalters@0: { "frameheight", heightbuff, &frameheightstr, "frameheight - internal", OutputOption}, tomwalters@0: { "framewidth", widthbuff, &framewidthstr, "framewidth - internal", SilentOption}, tomwalters@0: { "framewidth", widthbuff, &framewidthstr, "framewidth - internal", OutputOption}, tomwalters@0: { "frameshift", stepbuff, &framestepstr, "framestep - internal", SilentOption}, tomwalters@0: { "frameshift", stepbuff, &framestepstr, "framestep - internal", OutputOption}, tomwalters@0: { "frames", framesbuff, &framesstr, "frames - internal", SilentOption}, tomwalters@0: { "frames", framesbuff, &framesstr, "frames - internal", OutputOption}, tomwalters@0: tomwalters@0: { "samplerate", sampledflt, &samplestr, "Input wave sample rate (Hz)", InOutOption}, tomwalters@0: { "swap_wave", swapdflt, &swapstr, "Swap bytes in input wave", InOutOption}, tomwalters@0: { "bits_wave", bitsdflt, &bitstr, "Significant bits in input wave", SilentOption}, tomwalters@0: { "dB_wave", dBdflt, &dBstr, "Rel. input level (_tlf & _med only)\n", InOutOption}, /* CG */ tomwalters@0: { "what", whichdflt, &whichstr, "Type of model to use required", SilentOption}, tomwalters@0: tomwalters@0: (char *) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: /***************** Tools for manipulating sampling rate ********************* * CG * tomwalters@0: * This set of two routines allows to change and keep track of the sampling tomwalters@0: * rate of the data which flows through the model. It is the responsability tomwalters@0: * of each entry-point function to update the sampling rate as necessary. tomwalters@0: * tomwalters@0: * routine:- comment:- tomwalters@0: * Samplerate returns the current value of the sampling rate tomwalters@0: * SetSamplerate resets the sampling rate tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: static double rateCache = 0.0 ; tomwalters@0: tomwalters@0: void setSamplerate( newval ) tomwalters@0: double newval ; tomwalters@0: { tomwalters@0: rateCache = newval ; tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: double Samplerate() tomwalters@0: { tomwalters@0: if( rateCache == 0 ) tomwalters@0: rateCache = Freq( samplestr ) ; tomwalters@0: tomwalters@0: return( rateCache ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /******************* Tools for checking for special strings **************** tomwalters@0: * OptionInt( str ) tomwalters@0: * OptionDouble( str ) tomwalters@0: * OptionStringsEqual( str1, str2 ) -(defined in options.c). tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: double OptionDouble( str ) tomwalters@0: char *str ; tomwalters@0: { tomwalters@0: if( strcmp( str, "on" ) == 0 ) tomwalters@0: return( 1. ) ; tomwalters@0: else if( strcmp( str, "Not_used" ) == 0 ) tomwalters@0: return( 0. ) ; tomwalters@0: else tomwalters@0: return( atof( str ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int OptionInt( str ) tomwalters@0: char *str ; tomwalters@0: { tomwalters@0: if( strcmp( str, "on" ) == 0 ) tomwalters@0: return( 1 ) ; tomwalters@0: else if( strcmp( str, "Not_used" ) == 0 ) tomwalters@0: return( 0 ) ; tomwalters@0: else tomwalters@0: return( atoi( str ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: int OptionLog ( str ) tomwalters@0: char *str ; tomwalters@0: { tomwalters@0: if ( strcmp( str, "off" ) == 0 ) tomwalters@0: return( 0 ) ; tomwalters@0: else tomwalters@0: return( 1 ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /************************* Tools for scaling data ************************** * CG * tomwalters@0: * This set of two routines allows to keep track of the scaling factor needed tomwalters@0: * to convert the data which flows through the model into absolute units in tomwalters@0: * the cgs system ( 0.0002 dyne/cm2 ==> 0 dB SPL). It is the responsability of tomwalters@0: * each entry-point function to update the correct scaling factor as necessary. tomwalters@0: * The user must initially specify the scaling of the input wave using the tomwalters@0: * "dB_wave" option. The default is "dB_wave=60.". tomwalters@0: * tomwalters@0: * routine:- comment:- tomwalters@0: * Scaling returns a scalar to convert data to cgs units tomwalters@0: * SetScaling resets the scaling factor tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: static double scalingCache = 0.0 ; tomwalters@0: tomwalters@0: void setScaling( from_rms, from_dB, to_rms, to_dB ) tomwalters@0: double from_rms, from_dB, to_rms, to_dB ; tomwalters@0: { tomwalters@0: scalingCache = pow( 10., ( from_dB - to_dB ) / 20. ) * to_rms / from_rms ; tomwalters@0: } tomwalters@0: tomwalters@0: double Scaling() tomwalters@0: { tomwalters@0: double rms = 200. ; /* the default: 200 rms ==> 60 dB */ tomwalters@0: double dB = 60. ; tomwalters@0: tomwalters@0: if( scalingCache == 0 ) { tomwalters@0: tomwalters@0: if( strcmp( dBstr, "off" ) != 0 ) tomwalters@0: dB = Scalar( dBstr ) ; tomwalters@0: setScaling( rms, dB, 0.0002, 0. ) ; tomwalters@0: } tomwalters@0: tomwalters@0: return( scalingCache ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /************************ entry-point functions *************************** tomwalters@0: * Each entry-point function creates and initializes a "source object", and tomwalters@0: * returns a pointer to this object. Each source set up by one of the routines tomwalters@0: * below is designed to be the entry point for a specialized auditory-modelling tomwalters@0: * process. (See also io.c for sources which read from disk). tomwalters@0: * Source set-up functions always return a Source. They may take one or more tomwalters@0: * sources as arguments, as a specification of the input to the process tomwalters@0: * the source performs. The set up routine intializes the source structure with tomwalters@0: * a pointer to a callback function, which performs the data processing when tomwalters@0: * the source is used. tomwalters@0: * tomwalters@0: * Pointers to the entry-point functions are defined in the stage table, tomwalters@0: * (see FindStage() below). The functions are called, using these pointers, tomwalters@0: * from routine ModeledSource() (see below). The purpose of this is to call the tomwalters@0: * functions, in the order set by the stage table, so as to initialize a chain tomwalters@0: * of objects which can ultimately be used to execute the program. tomwalters@0: * tomwalters@0: * The source set-up routines are analogous to fopen(), (see stitch/source.c). tomwalters@0: * The processing phase, (analogous to fread()), uses pull/fill/roll functions, tomwalters@0: * and this execution is started from gen.c:main() by a call to SinkSource(). tomwalters@0: * tomwalters@0: * routine:- special subroutines:- tomwalters@0: * EarEntry() Ear() * CG * tomwalters@0: * GenericEntry() GenericFilterBank() tomwalters@0: * FilterEntry() GenericEntry() tomwalters@0: * TLF_FilterEntry() TLF_GenBank() * CG * tomwalters@0: * FineEntry() EarEntry() FilterEntry() TLF_FilterEntry() * CG * tomwalters@0: * EnvelopeEntry() GenericEntry() tomwalters@0: * ComplexEntry() GenericEntry() tomwalters@0: * PolarEntry() tomwalters@0: * RectifyEntry() tomwalters@0: * LogEntry() tomwalters@0: * UncompressEntry() tomwalters@0: * SaturateEntry() Saturate() tomwalters@0: * LowpassEntry() LowpassDataTypeSource() tomwalters@0: * ThresholdEntry() Meddis() Mfsai() tomwalters@0: * AdaptEntry() tomwalters@0: * HardEntry() Saturate() tomwalters@0: * IntegralEntry() LowpassDataTypeSource() tomwalters@0: * DownSampleEntry() DownSampleSource() BlockSampleSource() tomwalters@0: * SaiEntry() Sai() tomwalters@0: * SummaryEntry() Summary() tomwalters@0: * NullEntry() tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: /* As a means of introducing "cgm" as an alias for "fed", this NullEntry point does tomwalters@0: absolutely nothing to the data, but it DOES enable us to enter the queue just above tomwalters@0: the entry point for "fed". */ tomwalters@0: tomwalters@0: static Source NullEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /***** upsampling parameters *****/ /* CG */ tomwalters@0: tomwalters@0: static char upfdflt[] = "auto" , *upfstr = upfdflt ; /* CG */ tomwalters@0: static char cutoffdflt[] = "1.0" , *cutoffstr = cutoffdflt ; /* CG */ tomwalters@0: static char downfdflt[] = "auto" , *downfstr = downfdflt ; /* CG */ tomwalters@0: tomwalters@0: /***** ear parameters *****/ /* CG */ tomwalters@0: tomwalters@0: static char middledflt[] = "on" , *middlestr = middledflt ; /* CG */ tomwalters@0: static char lconcdflt[] = "0.90" , *lconcstr = lconcdflt ; /* CG */ tomwalters@0: static char rconcdflt[] = "1.00" , *rconcstr = rconcdflt ; /* CG */ tomwalters@0: static char kconcdflt[] = "0.01" , *kconcstr = kconcdflt ; /* CG */ tomwalters@0: static char nconcdflt[] = "2" , *nconcstr = nconcdflt ; /* CG */ tomwalters@0: static char lcanaldflt[] = "2.85" , *lcanalstr = lcanaldflt ; /* CG */ tomwalters@0: static char rcanaldflt[] = "0.35" , *rcanalstr = rcanaldflt ; /* CG */ tomwalters@0: static char kcanaldflt[] = "0.04" , *kcanalstr = kcanaldflt ; /* CG */ tomwalters@0: static char ncanaldflt[] = "4" , *ncanalstr = ncanaldflt ; /* CG */ tomwalters@0: tomwalters@0: static Source EarEntry( source ) /* CG: new entry */ tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: int upfactor, downfactor ; tomwalters@0: double cutoff, gain = OptionDouble( middlestr ) ; tomwalters@0: DeclareNew( struct _tube_info *, concha ) ; tomwalters@0: DeclareNew( struct _tube_info *, canal ) ; tomwalters@0: tomwalters@0: if( gain ) { tomwalters@0: tomwalters@0: /*** set up/downsampling parameters ***/ tomwalters@0: if( strncmp( upfstr, "auto", 4 ) == 0 ) { tomwalters@0: if( strncmp( downfstr, "auto", 4 ) == 0 ) tomwalters@0: upfactor = MIN( AUTO, ( int ) ( ( MAXSIGNALFREQ * AUTO * 2 ) / Samplerate() + 1.0 ) ) ; tomwalters@0: else tomwalters@0: upfactor = ABS( OptionInt( downfstr ) ) ; tomwalters@0: downfactor = upfactor ; tomwalters@0: } tomwalters@0: else { tomwalters@0: upfactor = ABS( OptionInt( upfstr ) ) ; tomwalters@0: if( strncmp( downfstr, "auto", 4 ) == 0 ) tomwalters@0: downfactor = upfactor ; tomwalters@0: else tomwalters@0: downfactor = ABS( OptionInt( downfstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*** set cutoff frequency of FIR upsampling filter ***/ tomwalters@0: cutoff = 0.5 * Samplerate() * Scalar( cutoffstr ) ; tomwalters@0: if( downfactor > upfactor ) { tomwalters@0: upfactor = MAX( 1, upfactor ) ; tomwalters@0: cutoff = cutoff * ( double ) upfactor / ( double ) downfactor ; tomwalters@0: } tomwalters@0: tomwalters@0: /*** upsample input wave ***/ tomwalters@0: if( upfactor >= 1 ) { tomwalters@0: source = UpSample( source, Samplerate(), cutoff, upfactor ) ; tomwalters@0: ( void ) setSamplerate( Samplerate() * upfactor ) ; tomwalters@0: ( void ) setFrames( Frames() * upfactor ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*** outer/middle ear filter ***/ tomwalters@0: concha->Nsegments = atoi( nconcstr ) ; tomwalters@0: concha->length = atof( lconcstr ) ; tomwalters@0: concha->diameter = atof( rconcstr ) * 2. ; tomwalters@0: concha->att_factor = atof( kconcstr ) ; tomwalters@0: canal->Nsegments = atoi( ncanalstr ) ; tomwalters@0: canal->length = atof( lcanalstr ) ; tomwalters@0: canal->diameter = atof( rcanalstr ) * 2. ; tomwalters@0: canal->att_factor = atof( kcanalstr ) ; tomwalters@0: tomwalters@0: source = Ear( source, Samplerate(), gain, concha, canal ) ; tomwalters@0: tomwalters@0: Delete( concha ) ; tomwalters@0: Delete( canal ) ; tomwalters@0: tomwalters@0: /*** downsample output data ***/ tomwalters@0: if( downfactor >= 1 ) { tomwalters@0: source = DownSampleSource( source, downfactor, 1 ) ; tomwalters@0: ( void ) setSamplerate( Samplerate() / downfactor ) ; tomwalters@0: ( void ) setFrames( Frames() / downfactor ) ; tomwalters@0: } tomwalters@0: tomwalters@0: } tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /***** frequency scale parameters*****/ tomwalters@0: tomwalters@0: static char qualdflt[] = "9.265" , *qualstr = qualdflt ; tomwalters@0: static char limitdflt[] = "24.7Hz" , *limitstr = limitdflt ; tomwalters@0: static char mmdflt[] = "0.89" , *mmstr = mmdflt ; /* CG */ tomwalters@0: tomwalters@0: static char interpdflt[] = "off" , *interpstr = interpdflt ; tomwalters@0: tomwalters@0: /***** filterbank parameters ****/ tomwalters@0: tomwalters@0: static char maxdflt[] = "6000Hz" , *maxstr = maxdflt ; /* roy 23-12-92 */ tomwalters@0: static char mindflt[] = "100Hz" , *minstr = mindflt ; /* roy 23-12-92 */ tomwalters@0: #ifdef PC tomwalters@0: static char dendflt[] = "off" , *denstr = dendflt ; /* roy 23-12-92 */ tomwalters@0: #else tomwalters@0: static char dendflt[] = "off" , *denstr = dendflt ; /* roy 23-12-92 */ tomwalters@0: #endif tomwalters@0: static char chansdflt[] = "75" , *chansstr = chansdflt ; /* roy 23-12-92 */ tomwalters@0: static char audiodflt[] = "off" , *audiostr = audiodflt ; /* CG */ tomwalters@0: static char infodflt[] = "off" , *infostr = infodflt ; /* CG */ tomwalters@0: tomwalters@0: static char filterdflt[] = "gtf" , *filterstr = filterdflt ; /* CG */ tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * updateFrequencies() tomwalters@0: * Routine called from ModeledSource(), below. tomwalters@0: * It sets the frameheight (number of filter-bank channels), and initializes tomwalters@0: * the array of channel centre-frequencies, (called "frequencies"). tomwalters@0: * These are derived from three basic parameters: tomwalters@0: * option-name: string-value: default: comment: tomwalters@0: * mincf_afb minstr 220Hz Minimum center frequency (Hz) tomwalters@0: * maxcf_afb maxstr 4400Hz Maximum center frequency (Hz) tomwalters@0: * dencf_afb denstr 4. Filter density (filters/critical band) tomwalters@0: * tomwalters@0: * The frameheight is calculated in the routine "NumberCenterFrequencies", tomwalters@0: * and the result is copied into the "frameheightstr" by a call to the routine tomwalters@0: * "setFrameheight". tomwalters@0: * The "frequencies" are calculated in the routine "GenerateCenterFrequencies". tomwalters@0: * (Both CenterFrequency routines are in gamma_tone.c). tomwalters@0: * tomwalters@0: * The frequencies are stored in a global array of center frequencies (below). tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: double *frequencies ; /* global array of centre frequencies */ tomwalters@0: tomwalters@0: static void reverseFrequencies( freqs, channels ) tomwalters@0: double *freqs ; tomwalters@0: int channels ; tomwalters@0: { tomwalters@0: int i ; tomwalters@0: double d ; tomwalters@0: tomwalters@0: for( i=0 ; i upfactor ) { tomwalters@0: upfactor = MAX( 1, upfactor ) ; tomwalters@0: cutoff = cutoff * ( double ) upfactor / ( double ) downfactor ; tomwalters@0: } tomwalters@0: tomwalters@0: /*** upsample input wave ***/ tomwalters@0: if( upfactor >= 1 ) { tomwalters@0: source = UpSample( source, Samplerate(), cutoff, upfactor ) ; tomwalters@0: ( void ) setSamplerate( Samplerate() * upfactor ) ; tomwalters@0: ( void ) setFrames( Frames() * upfactor ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*** set outer/middle ear parameters ***/ tomwalters@0: concha->Nsegments = atoi( nconcstr ) ; tomwalters@0: concha->length = atof( lconcstr ) ; tomwalters@0: concha->diameter = atof( rconcstr ) * 2. ; tomwalters@0: concha->att_factor = atof( kconcstr ) ; tomwalters@0: canal->Nsegments = atoi( ncanalstr ) ; tomwalters@0: canal->length = atof( lcanalstr ) ; tomwalters@0: canal->diameter = atof( rcanalstr ) * 2. ; tomwalters@0: canal->att_factor = atof( kcanalstr ) ; tomwalters@0: tomwalters@0: /*** set bank parameters ***/ tomwalters@0: updateFrequencies() ; tomwalters@0: SetERBscaling( atof( mmstr ) ) ; tomwalters@0: chans = Frameheight() ; tomwalters@0: tomwalters@0: /*** OHC normalization: converts from cgs units (0 dB SPL=>0.0002 dynes/cm2) to input wave units ***/ tomwalters@0: dsat = atof( dsatstr ) / Scaling() ; tomwalters@0: tomwalters@0: /*** process data and downsample output ***/ tomwalters@0: source = TLF_GenBank( source, OptionInt( interpstr ), OptionInt( infostr ), &chans, &downfactor, tomwalters@0: Samplerate(), frequencies, Scalar( tgainstr ), atof( outdenstr ), tomwalters@0: atof( qrefstr ), atof( feedstr ), dsat, motionstr, concha, canal ) ; tomwalters@0: tomwalters@0: /*** reset sampling rate and file-format strings ***/ tomwalters@0: ( void ) setFrameheight( chans ) ; tomwalters@0: ( void ) setSamplerate ( Samplerate() / downfactor ) ; tomwalters@0: ( void ) setFrames( Frames() / downfactor ) ; tomwalters@0: tomwalters@0: Delete( concha ) ; tomwalters@0: Delete( canal ) ; tomwalters@0: tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source FineEntry(source ) /* CG: new Entry */ tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: if( strncmp( filterstr, "off", 3 ) == 0 ) tomwalters@0: source = EarEntry( source ) ; tomwalters@0: tomwalters@0: else { tomwalters@0: tomwalters@0: if( strncmp( filterstr, "tlf", 3 ) == 0 ) tomwalters@0: source = TLF_FilterEntry( source ) ; tomwalters@0: tomwalters@0: else { tomwalters@0: source = EarEntry( source ) ; tomwalters@0: source = FilterEntry( source ) ; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: return( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source EnvelopeEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: #ifdef FLOAT tomwalters@0: return ( GenericEntry( source, DoRealEnvelopeFloatDataArray ) ) ; tomwalters@0: #else tomwalters@0: if( OptionInt( floatstr ) != 0 ) tomwalters@0: return ( GenericEntry( source, DoRealEnvelopeShortDataArray ) ) ; tomwalters@0: else tomwalters@0: return ( GenericEntry( source, DoEnvelopeShortDataArray ) ) ; tomwalters@0: #endif tomwalters@0: } tomwalters@0: tomwalters@0: static Source ComplexEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: Source ret ; tomwalters@0: tomwalters@0: #ifdef FLOAT tomwalters@0: ret = GenericEntry( source, DoComplexFilterFloatDataArray ) ; tomwalters@0: #else tomwalters@0: ret = GenericEntry( source, DoComplexFilterShortDataArray ) ; tomwalters@0: #endif tomwalters@0: setFrameheight( Frameheight() * 2 ) ; tomwalters@0: tomwalters@0: return ( ret ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /******* [fbm] [bmm] [fcp,fcr] stage: "auditory filter output" ************/ tomwalters@0: tomwalters@0: static Option fbmopts[] = { tomwalters@0: tomwalters@0: { "upfactor", upfdflt, &upfstr, "Upsampling factor (off, auto, int)", SilentOption}, /* CG */ tomwalters@0: { "cutoff", cutoffdflt, &cutoffstr, "LP cutoff as a fraction of Nyquist freq.", SilentOption}, /* CG */ tomwalters@0: { "downfactor", downfdflt, &downfstr, "Downsampling factor (off, auto, int)\n", SilentOption}, /* CG */ tomwalters@0: tomwalters@0: { "middle_ear", middledflt, &middlestr, "Enable outer/middle ear function\n", InOutOption}, /* CG */ tomwalters@0: { "nconcha_ear", nconcdflt, &nconcstr, "Number of segments in concha", SilentOption}, /* CG */ tomwalters@0: { "lconcha_ear", lconcdflt, &lconcstr, "Total length of concha (cm)", SilentOption}, /* CG */ tomwalters@0: { "rconcha_ear", rconcdflt, &rconcstr, "Radius of concha (cm)", SilentOption}, /* CG */ tomwalters@0: { "kconcha_ear", kconcdflt, &kconcstr, "Attn. constant of concha (1/cm)", SilentOption}, /* CG */ tomwalters@0: { "ncanal_ear", ncanaldflt, &ncanalstr, "Number of segments in ear canal", SilentOption}, /* CG */ tomwalters@0: { "lcanal_ear", lcanaldflt, &lcanalstr, "Length of ear canal (cm)", SilentOption}, /* CG */ tomwalters@0: { "rcanal_ear", rcanaldflt, &rcanalstr, "Radius of ear canal (cm)", SilentOption}, /* CG */ tomwalters@0: { "kcanal_ear", kcanaldflt, &kcanalstr, "Attn. constant of ear canal (1/cm)\n", SilentOption}, /* CG */ tomwalters@0: tomwalters@0: { "channels_afb", chansdflt, &chansstr, "Number of channels in filter", InOutOption}, tomwalters@0: { "mincf_afb", mindflt, &minstr, "Minimum center frequency (Hz)", InOutOption}, tomwalters@0: { "maxcf_afb", maxdflt, &maxstr, "Maximum center frequency (Hz)", InOutOption}, tomwalters@0: { "dencf_afb", dendflt, &denstr, "Filter density (filters/critical band)", InOutOption}, tomwalters@0: { "info_afb", infodflt, &infostr, "Prints filterbank information (to stderr).", InputOption}, /* CG */ tomwalters@0: { "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply", OutputOption}, tomwalters@0: { "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply", SilentOption}, tomwalters@0: {"audiogram_afb", audiodflt, &audiostr, "Audiogram equalisation parameter", SilentOption}, /* CG */ tomwalters@0: { "bwmin_afb", limitdflt, &limitstr, "Minimum filter bandwith", InOutOption}, tomwalters@0: { "quality_afb", qualdflt, &qualstr, "Ultimate qualtity factor of filters", InOutOption}, tomwalters@0: { "mmerb_afb", mmdflt, &mmstr, "Length of 1 erb-rate unit along BM (mm)\n", InOutOption}, /* CG */ tomwalters@0: tomwalters@0: { "filter", filterdflt, &filterstr, "Select auditory filter (gtf, tlf, off)\n", InOutOption}, /* CG */ tomwalters@0: tomwalters@0: { "float_gtf", floatdflt, &floatstr, "Floating point filter calculations", OutputOption}, tomwalters@0: { "float_gtf", floatdflt, &floatstr, "Floating point filter calculations", SilentOption}, tomwalters@0: { "phase_gtf", phasedflt, &phasestr, "Phase compensation option", InOutOption}, tomwalters@0: { "order_gtf", orderdflt, &orderstr, "Filter order", InOutOption}, tomwalters@0: { "gain_gtf", gaindflt, &gainstr, "Filter output amplification\n", InOutOption}, /* CG */ tomwalters@0: tomwalters@0: { "motion_tlf", motiondflt, &motionstr, "BM output motion (disp, vel)", InOutOption}, /* CG */ tomwalters@0: { "outdencf_tlf", outdendflt, &outdenstr, "Filter density outside display range", InOutOption}, /* CG */ tomwalters@0: { "qref_tlf", qrefdflt, &qrefstr, "Local Q-factor of BM segment", InOutOption}, /* CG */ tomwalters@0: { "feedback_tlf", feeddflt, &feedstr, "Feedback gain of OHCs (0 to 0.999)", InOutOption}, /* CG */ tomwalters@0: { "dsat_tlf", dsatdflt, &dsatstr, "Half-saturation displacement (cm)", InOutOption}, /* CG */ tomwalters@0: { "gain_tlf", tgaindflt, &tgainstr, "Filter output amplification\n", InOutOption}, /* CG */ tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static void polar_callback( state, bytes, output, end, input ) tomwalters@0: Source state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: scomplex *output, *end, *input ; tomwalters@0: { tomwalters@0: register scomplex *iptr = input ; tomwalters@0: register scomplex *optr = output ; tomwalters@0: register scomplex *eptr = end ; tomwalters@0: tomwalters@0: while( optr < eptr ) { tomwalters@0: optr->real = imB( (long) iptr->real * iptr->real + (long) iptr->imag * iptr->imag ) >> 1 ; tomwalters@0: optr->imag = iatan2( iptr->imag, iptr->real ) ; tomwalters@0: iptr++ ; tomwalters@0: optr++ ; tomwalters@0: } tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source PolarEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: return ( NewSimpleProcessingSource( polar_callback, source, "model.c polar conversion" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: static void fullwave_callback( state, bytes, buffer, end, input ) tomwalters@0: Source state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: DataType *buffer, *end, *input ; tomwalters@0: { tomwalters@0: register DataType *iptr = input ; tomwalters@0: register DataType *optr = buffer ; tomwalters@0: register DataType *eptr = end ; tomwalters@0: tomwalters@0: if( optr < eptr ) tomwalters@0: do tomwalters@0: if( *iptr > 0 ) tomwalters@0: *optr++ = *iptr++ ; tomwalters@0: else tomwalters@0: *optr++ = -*iptr++ ; tomwalters@0: tomwalters@0: while( optr < eptr ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* rectification */ tomwalters@0: tomwalters@0: static char rectdflt[] = "off", *rectstr = rectdflt ; tomwalters@0: tomwalters@0: /************** [fbr] stage: "rectified filter output" ******************/ tomwalters@0: tomwalters@0: static Option fbropts[] = { tomwalters@0: tomwalters@0: { "rectify", rectdflt, &rectstr, "Rectify filter output", InOutOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: static void halfwave_callback( state, bytes, buffer, end, input ) tomwalters@0: Source state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: DataType *buffer, *end, *input ; tomwalters@0: { tomwalters@0: register DataType *iptr = input ; tomwalters@0: register DataType *optr = buffer ; tomwalters@0: register DataType *eptr = end ; tomwalters@0: tomwalters@0: if( optr < eptr ) tomwalters@0: do tomwalters@0: if( *iptr > 0 ) tomwalters@0: *optr++ = *iptr++ ; tomwalters@0: else tomwalters@0: *optr++ =0,*iptr++ ; tomwalters@0: tomwalters@0: while( optr < eptr ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source RectifyEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: switch( OptionInt( rectstr ) ) { tomwalters@0: tomwalters@0: case 1 : tomwalters@0: return ( SharingSource( NewSimpleProcessingSource( halfwave_callback, source, "model.c recification" ), source ) ) ; tomwalters@0: tomwalters@0: case 2: tomwalters@0: return ( SharingSource( NewSimpleProcessingSource( fullwave_callback, source, "model.c recification" ), source ) ) ; tomwalters@0: tomwalters@0: default : tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /*********** [fbc] [fec] stage: "compressed filter output" **************/ tomwalters@0: tomwalters@0: /* logaritmic compression function */ tomwalters@0: tomwalters@0: static char logdflt[] = "log", *logstr = logdflt ; tomwalters@0: static char powdflt[] = "off", *powstr = powdflt ; tomwalters@0: tomwalters@0: static Option fbcopts[] = { tomwalters@0: tomwalters@0: { "compress", logdflt, &logstr, "Compression (log, power value [0-1], off)", InOutOption}, tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: #ifdef FLOAT tomwalters@0: static void mB_callback( state, bytes, buffer, end, input ) tomwalters@0: Pointer state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: DataType *buffer, *end, *input ; tomwalters@0: { tomwalters@0: register DataType *iptr = input ; tomwalters@0: register DataType *optr = buffer ; tomwalters@0: register DataType *eptr = end ; tomwalters@0: double pw; tomwalters@0: tomwalters@0: if (!strcmp(logstr, "log") || !strcmp(logstr, "on")) tomwalters@0: ; tomwalters@0: else tomwalters@0: { tomwalters@0: pw=(double)atof(logstr); tomwalters@0: strcpy(powstr, "on"); tomwalters@0: if (pw > 1.0) { tomwalters@0: fprintf(stderr, "The value of power compression cannot be more than 1.0\n"); tomwalters@0: exit(-125);} tomwalters@0: } tomwalters@0: tomwalters@0: if( optr < eptr ) tomwalters@0: do{ tomwalters@0: if( *iptr >= 1. ){ tomwalters@0: if (!(strcmp(powstr, "off"))){ tomwalters@0: *optr = log10( *iptr ) * 2000. ;} tomwalters@0: else{ tomwalters@0: *optr = (float) pow((double)*iptr, (double) pw) * 100./(pw); } tomwalters@0: } tomwalters@0: else tomwalters@0: *optr = 0. ; /* -10. Changed from -10, AJD 29th August, 1995. */ tomwalters@0: iptr++; optr++; } tomwalters@0: while( optr < eptr ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: tomwalters@0: } tomwalters@0: #endif tomwalters@0: tomwalters@0: static Source LogEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: if( OptionLog( logstr ) != 0 ) tomwalters@0: #ifdef FLOAT tomwalters@0: return ( SharingSource( NewSimpleProcessingSource( mB_callback, source, "model.c compression" ), source ) ) ; tomwalters@0: #else tomwalters@0: return ( SharingSource( milliBellShortSource( source ), source ) ) ; tomwalters@0: #endif tomwalters@0: else tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*********** [fbu] [feu] stage: "uncompressed filter output" **************/ tomwalters@0: tomwalters@0: /***** uncompress data by raising to a power *****/ tomwalters@0: tomwalters@0: static char powerdflt[] = "off", *powerstr = powerdflt ; tomwalters@0: tomwalters@0: static Option fbuopts[] = { tomwalters@0: tomwalters@0: { "power", powerdflt, &powerstr, "Power of Compression", SilentOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: struct _uncompress_state { double power ; } ; tomwalters@0: tomwalters@0: static void uncompress_callback( state, bytes, buffer, end, input ) tomwalters@0: struct _uncompress_state *state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: DataType *buffer, *end, *input ; tomwalters@0: { tomwalters@0: register DataType *iptr = input ; tomwalters@0: register DataType *optr = buffer ; tomwalters@0: register DataType *eptr = end ; tomwalters@0: register double power = state->power ; tomwalters@0: tomwalters@0: if( optr < eptr ) tomwalters@0: do tomwalters@0: *optr++ = pow( 10., *iptr++ * power ) ; tomwalters@0: while( optr < eptr ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: static Source UncompressEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: DeclareNew( struct _uncompress_state *, state ) ; tomwalters@0: tomwalters@0: if( OptionDouble( powerstr ) != 0.0 ) { tomwalters@0: tomwalters@0: state->power = OptionDouble( powerstr ) / 2000. ; tomwalters@0: tomwalters@0: return ( SharingSource (NewProcessingSource( state, uncompress_callback, stitch_free, source, "model.c compression" ), source ) ) ; tomwalters@0: } tomwalters@0: else tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*********** [fbs] [fes] stage: "saturated filter output" **************/ tomwalters@0: tomwalters@0: /***** provide for possible saturation at this point *****/ tomwalters@0: tomwalters@0: static char satdflt[] = "off", *satstr = satdflt ; tomwalters@0: tomwalters@0: static Option fbsopts[] = { tomwalters@0: tomwalters@0: { "saturate", satdflt, &satstr, "Introduce Saturation of non-linearity\n", SilentOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: struct _sat_state { int saturation ; } ; tomwalters@0: tomwalters@0: static void sat_callback( state, bytes, buffer, end, input ) tomwalters@0: struct _sat_state *state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: DataType *buffer, *end, *input ; tomwalters@0: { tomwalters@0: register DataType *iptr = input ; tomwalters@0: register DataType *optr = buffer ; tomwalters@0: register DataType *eptr = end ; tomwalters@0: tomwalters@0: if( optr < eptr ) tomwalters@0: do { tomwalters@0: tomwalters@0: if( *iptr > 0 ) tomwalters@0: *optr++ = SCALE( *iptr ) / ( SCALE( 1 ) + SCALE( *iptr ) / state->saturation ) ; tomwalters@0: else tomwalters@0: *optr++ = SCALE( *iptr ) / ( SCALE( 1 ) - SCALE( *iptr ) / state->saturation ) ; tomwalters@0: iptr++ ; tomwalters@0: tomwalters@0: } while( optr < eptr ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source Saturate( source, str ) tomwalters@0: Source source ; tomwalters@0: char *str ; tomwalters@0: { tomwalters@0: DeclareNew( struct _sat_state *, state ) ; tomwalters@0: tomwalters@0: if( OptionInt( str ) != 0 ) { tomwalters@0: tomwalters@0: state->saturation = OptionInt( str ) ; tomwalters@0: tomwalters@0: return ( SharingSource( NewProcessingSource( (Pointer) state, sat_callback, stitch_free, source, "model.c stauration" ), source ) ) ; tomwalters@0: } tomwalters@0: else tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source SaturateEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: return( Saturate( source, satstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: #if 00 tomwalters@0: /***** new processing entry *****/ tomwalters@0: tomwalters@0: static char zongdflt[] = "off", *zongstr = zongdflt ; /* parameter default for table.c */ tomwalters@0: tomwalters@0: static Source ZongEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: int i, chans = Frameheight() ; tomwalters@0: DeclareNewArray( WuState *, states, chans, "model.c for states" ) ; tomwalters@0: tomwalters@0: /* for all of the channels create a new wu cels object */ tomwalters@0: tomwalters@0: for( i=0 ; i 1 rms ) ***/ tomwalters@0: tomwalters@0: /* first convert from filterbank output units to cgs units (0 dB SPL => 0.0002 dynes/cm2) ***/ tomwalters@0: ( void ) setScaling( 0.0002 / Scaling() * FILTERBANK_SCALE * 4.0, 0., 0.0002, 0. ) ; tomwalters@0: tomwalters@0: /* second convert from cgs units to meddis units (30 dB => 1 rms) ***/ tomwalters@0: ( void ) setScaling( 0.0002 / Scaling(), 0., MEDDIS_RMS, MEDDIS_dB ) ; tomwalters@0: tomwalters@0: /*** start array of Meddis hair cells ***/ tomwalters@0: coupling = coupling * Scaling() ; tomwalters@0: state = NewHaircells( chans, samplerate, scalar, coupling, fibrestr ) ; tomwalters@0: return ( NewProcessingSource( state, DoHaircells, CloseHaircells, input, "model.c meddis" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /***** adaptive thresholding *****/ tomwalters@0: tomwalters@0: static char stxdflt[] = "1.", *stxstr = stxdflt ; /* CG 23-03-94 */ tomwalters@0: static char risedflt[] = "10000.", *risestr = risedflt ; tomwalters@0: static char rapiddflt[] = "0.6", *rapidstr = rapiddflt ; tomwalters@0: static char fastdflt[] = "0.2", *faststr = fastdflt ; tomwalters@0: static char propdflt[] = "0.5", *propstr = propdflt ; tomwalters@0: static char latdflt[] = "20.", *latstr = latdflt ; /* roy 23-12-92 */ tomwalters@0: static char vdraindflt[] = "5", *vdrainstr = vdraindflt ; tomwalters@0: static char timesdflt[] = "2", *timesstr = timesdflt ; tomwalters@0: tomwalters@0: static char compdflt[] = "on", *compstr = compdflt ; /* mha 22/1/93 */ tomwalters@0: tomwalters@0: tomwalters@0: static Option fbtopts[] = { tomwalters@0: tomwalters@0: { "transduction", transdflt, &transstr, "Select transduction function (at, meddis, off)\n",InOutOption}, /* CG */ tomwalters@0: tomwalters@0: { "trise_at", risedflt, &risestr, "Threshold adaptation rate (upwards)", InOutOption}, tomwalters@0: {"t1recovery_at", rapiddflt, &rapidstr, "Initial recovery rate relative to filter", InOutOption}, tomwalters@0: {"t2recovery_at", fastdflt, &faststr, "Secondary recovery rate relative to filter", InOutOption}, tomwalters@0: { "propt2t1_at", propdflt, &propstr, "Relative height of secondary adaptation", InOutOption}, tomwalters@0: { "frecovery_at", latdflt, &latstr, "Recovery rate across frequency", InOutOption}, tomwalters@0: { "reclimit_at", vdraindflt, &vdrainstr, "Limitation on recovery level", InOutOption}, tomwalters@0: { "times_at", timesdflt, ×str, "Oversampling of calculation of threshold", OutputOption}, tomwalters@0: { "times_at", timesdflt, ×str, "Oversampling of calculation of threshold", SilentOption}, tomwalters@0: {"compensate_at", compdflt, &compstr, "Cochlea output compensation", SilentOption}, tomwalters@0: { "gain_at", stxdflt, &stxstr, "Adaptive thresholding output gain\n", InOutOption}, /* CG */ tomwalters@0: tomwalters@0: { "fibre_med", fibredflt, &fibrestr, "Spont-rate fibre type (medium, high)", InOutOption}, /* CG */ tomwalters@0: { "thresh_med", thresdflt, &thresstr, "Haircell threshold shift (dB)", InOutOption}, /* CG */ tomwalters@0: { "gain_med", meddisdflt, &meddisstr, "Meddis haircell model output gain\n", InOutOption}, /* CG */ tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static Source ThresholdEntry( source ) /* CG: modified */ tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: double density ; tomwalters@0: tomwalters@0: if( OptionInt( chansstr ) == 0 ) tomwalters@0: density = OptionDouble( denstr ) ; tomwalters@0: else tomwalters@0: density = OptionInt( chansstr ) / ( ErbScale( Freq( maxstr ) ) - ErbScale( Freq( minstr ) ) ) ; tomwalters@0: tomwalters@0: if( strncmp( transstr, "off", 3 ) == 0 ) tomwalters@0: source = source ; tomwalters@0: tomwalters@0: else { tomwalters@0: tomwalters@0: if( strncmp( transstr, "med", 3 ) == 0 ) tomwalters@0: source = Meddis( source, Frameheight(), Samplerate(), OptionDouble( meddisstr ) ) ; tomwalters@0: tomwalters@0: else { tomwalters@0: compensate = OptionDouble( compstr ) ; tomwalters@0: tomwalters@0: source = NewProcessingSource( tomwalters@0: newCorti( tomwalters@0: Frameheight(), Samplerate(), frequencies, Erb, tomwalters@0: atof( risestr ), atof( latstr ) * density, tomwalters@0: atof( rapidstr ), atof( faststr ), atof( propstr ), tomwalters@0: log10( Scalar( vdrainstr ) ) * 2000., tomwalters@0: (int) ( density * atof( latstr ) / Samplerate() + 1. ) * atoi( timesstr ), tomwalters@0: OptionDouble( stxstr ) tomwalters@0: ), (void ( * )()) Corti, closeCorti, tomwalters@0: source, tomwalters@0: "model.c thresholding" tomwalters@0: ) ; tomwalters@0: tomwalters@0: } tomwalters@0: } tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /* modulation frequency image */ tomwalters@0: tomwalters@0: static char stepmfdflt[] = "250Hz", *stepmfstr = stepmfdflt ; tomwalters@0: static char maxmfdflt[] = "250Hz", *maxmfstr = maxmfdflt ; tomwalters@0: static char minmfdflt[] = "50Hz", *minmfstr = minmfdflt ; tomwalters@0: static char denmfdflt[] = "off", *denmfstr = denmfdflt ; tomwalters@0: tomwalters@0: #ifndef DSP32 tomwalters@0: tomwalters@0: Source Mfsai( source, segment ) /* CG */ tomwalters@0: Source source ; tomwalters@0: int segment ; tomwalters@0: { tomwalters@0: extern char *filestr ; tomwalters@0: Source mfsource = FileNameSource( filestr ) ; tomwalters@0: int frameheight = Frameheight() ; tomwalters@0: int i ; tomwalters@0: tomwalters@0: frequencies = GenerateCenterFrequencies( Freq( minmfstr ), Freq( maxmfstr ), OptionDouble( denmfstr ) ) ; tomwalters@0: setFrameheight( NumberCenterFrequencies( Freq( minmfstr ), Freq( maxmfstr ), OptionDouble( denmfstr ) ) ) ; tomwalters@0: tomwalters@0: mfsource = GenericEntry( mfsource, DoFilterShortDataArray ) ; tomwalters@0: /* mfsource = GenericEntry( mfsource, DoNewFilterDataArray ) ; */ tomwalters@0: mfsource = NewProcessingSource( tomwalters@0: newCorti( tomwalters@0: Frameheight(), Samplerate(), frequencies, Erb, tomwalters@0: atof( risestr ), atof( latstr ) * OptionDouble( denmfstr ), tomwalters@0: atof( rapidstr ), atof( faststr ), atof( propstr ), tomwalters@0: log10( Scalar( vdrainstr ) ) * 2000., /* convert to millibells */ tomwalters@0: (int) ( OptionDouble( denmfstr ) * atof( latstr ) / Samplerate() + 1. ) * atoi( timesstr ), tomwalters@0: 0 tomwalters@0: ), (void ( * )()) Corti, closeCorti, tomwalters@0: mfsource, tomwalters@0: "model.c thresholding" tomwalters@0: ) ; tomwalters@0: tomwalters@0: return ( mfsource ) ; tomwalters@0: } tomwalters@0: tomwalters@0: #endif tomwalters@0: /***** long term adaptation - not implemented - used to sneak in modulation frequency thing *****/ tomwalters@0: tomwalters@0: static char adapdflt[] = "0", *adapstr = adapdflt ; tomwalters@0: tomwalters@0: static Source AdaptEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: #ifndef DSP32 tomwalters@0: if( OptionDouble( denmfstr ) > 0 ) tomwalters@0: source = Mfsai( source ) ; tomwalters@0: #endif tomwalters@0: return( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*********** [fba] [fea] stage: "adapted transduced filter output" *********/ tomwalters@0: tomwalters@0: static Option fbaopts[] = { tomwalters@0: tomwalters@0: { "mmincf_mfb", minmfdflt, &minmfstr, "Minimum modulation frequency (Hz)", SilentOption}, tomwalters@0: { "mmaxcf_mfb", maxmfdflt, &maxmfstr, "Maximum modulation frequency (Hz)", SilentOption}, tomwalters@0: { "mdencf_mfb", denmfdflt, &denmfstr, "Modulation filter density ", SilentOption}, tomwalters@0: { "stepcf_mfb", stepmfdflt, &stepmfstr, "Step between images\n", SilentOption}, tomwalters@0: tomwalters@0: { "tadaptation", adapdflt, &adapstr, "Time constant of long term adaptation\n", SilentOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /***** hard limiting *****/ tomwalters@0: tomwalters@0: static char harddflt[] = "off", *hardstr = harddflt ; tomwalters@0: tomwalters@0: static Source HardEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: return( Saturate( source, hardstr ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /*********** [fbh] [feh] stage: "hard limited filter output" **************/ tomwalters@0: tomwalters@0: static Option fbhopts[] = { tomwalters@0: tomwalters@0: { "hard_limit", harddflt, &hardstr, "Hardlimit firing rate before integration\n",OutputOption}, tomwalters@0: { "hard_limit", harddflt, &hardstr, "Hardlimit firing rate before integration\n",SilentOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: /***** [sgm,cgm,fbd,fbi] [fed,fei] stage: "integrated filter output" *******/ tomwalters@0: tomwalters@0: /***** temporal integration *****/ tomwalters@0: tomwalters@0: static char stagedflt[] = "off", *stagestr = stagedflt ; tomwalters@0: static char updflt[] = "8ms", *upstr = updflt ; tomwalters@0: static char downdflt[] = "1", *downstr = downdflt ; tomwalters@0: static char lossdflt[] = "1", *lossstr = lossdflt ; tomwalters@0: static char vlossdflt[] = "0", *vlossstr = vlossdflt ; tomwalters@0: static char igaindflt[] = "1", *igainstr = igaindflt ; tomwalters@0: tomwalters@0: static Option fbiopts[] = { tomwalters@0: tomwalters@0: { "stages_idt", stagedflt, &stagestr, "Stages of integration", InOutOption}, tomwalters@0: { "igain_idt", igaindflt, &igainstr, "Gain of integration stage\n", OutputOption}, tomwalters@0: { "igain_idt", igaindflt, &igainstr, "Gain of integration stage\n", SilentOption}, tomwalters@0: tomwalters@0: { "vloss_idt", vlossdflt, &vlossstr, "Rest level for loss", OutputOption}, tomwalters@0: { "vloss_idt", vlossdflt, &vlossstr, "Rest level for loss", SilentOption}, tomwalters@0: { "loss_idt", lossdflt, &lossstr, "Loss time constant", OutputOption}, tomwalters@0: { "loss_idt", lossdflt, &lossstr, "Loss time constant", SilentOption}, tomwalters@0: { "tdown_idt", downdflt, &downstr, "Downward time constant in ms", OutputOption}, tomwalters@0: { "tdown_idt", downdflt, &downstr, "Downward time constant in ms", SilentOption}, tomwalters@0: { "tup_idt", updflt, &upstr, "Low-pass filter time constant", InOutOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static Source IntegralEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: return ( LowpassDataTypeSource( source, OptionInt( stagestr ), Frameheight(), Samples( upstr, Samplerate() ), Samples( downstr, Samplerate() ), Scalar( igainstr ) ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* downsampling */ tomwalters@0: tomwalters@0: static char downsdflt[] = "off", *downsstr = downsdflt ; tomwalters@0: tomwalters@0: static Option dwnopts[] = { tomwalters@0: tomwalters@0: { "downsample", downsdflt, &downsstr, "Downsampling over time", InOutOption}, tomwalters@0: { "frstep_epn", downsdflt, &downsstr, "Downsampling over time\n", InOutOption}, tomwalters@0: tomwalters@0: (char *) 0 } ; tomwalters@0: tomwalters@0: static Source DownSampleEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: int spacing = Samples( downsstr, Samplerate() ) ; tomwalters@0: int channels = Frameheight() * Framewidth() ; tomwalters@0: tomwalters@0: if( spacing != 0 ) { tomwalters@0: tomwalters@0: #if defined( PC ) || defined( DSP32 ) tomwalters@0: source = NewSegmentingSource( source, Frameheight() * Framewidth() * sizeof ( DataType ) * 4 ) ; tomwalters@0: #endif tomwalters@0: tomwalters@0: if( spacing > 0 ) tomwalters@0: source = DownSampleSource( source, spacing, channels ) ; tomwalters@0: else { tomwalters@0: spacing = -spacing ; tomwalters@0: source = BlockSampleSource( source, spacing, channels ) ; tomwalters@0: } tomwalters@0: tomwalters@0: setFramestep( spacing ) ; tomwalters@0: tomwalters@0: setFrames( Frames() / spacing ) ; tomwalters@0: } tomwalters@0: tomwalters@0: return( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* stabilised image defaults */ tomwalters@0: tomwalters@0: static char llimdflt[] = "1.5c" , *llimstr = llimdflt ; tomwalters@0: static char ulimdflt[] = "24ms" , *ulimstr = ulimdflt ; tomwalters@0: tomwalters@0: static char saidflt[] = "1" , *saistr = saidflt ; tomwalters@0: #ifdef PC tomwalters@0: static char pwidthdflt[] = "20ms" , *pwidthstr = pwidthdflt ; tomwalters@0: #else tomwalters@0: static char pwidthdflt[] = "35ms" , *pwidthstr = pwidthdflt ; /* roy 23-12-92 */ tomwalters@0: #endif tomwalters@0: /* static char nwidthdflt[] = "-5ms" , *nwidthstr = nwidthdflt ; roy 23-12-92 */ tomwalters@0: tomwalters@0: static char ltlimdflt[] = "150Hz" , *ltlimstr = ltlimdflt ; tomwalters@0: static char utlimdflt[] = "20Hz" , *utlimstr = utlimdflt ; tomwalters@0: static char decaydflt[] = "30ms" , *decaystr = decaydflt ; tomwalters@0: static char cgmdflt[] = "2.5" , *cgmstr = cgmdflt ; /* 30ms > 1.25 roy 23-12-92 */ tomwalters@0: static char ttdflt[] = "5" , *ttstr = ttdflt ; /* 8ms > 10 roy 23-12-92 */ tomwalters@0: tomwalters@0: static char sustdflt[] = "0" , *susthreshstr = sustdflt ; tomwalters@0: tomwalters@0: static char swdflt[] = "off" , *swstr = swdflt ; tomwalters@0: tomwalters@0: #ifdef PC tomwalters@0: static char stepdflt[] = "15.25ms" , *stepstr = stepdflt ; tomwalters@0: #else tomwalters@0: static char stepdflt[] = "16ms" , *stepstr = stepdflt ; tomwalters@0: #endif tomwalters@0: tomwalters@0: /* spiral parameters */ tomwalters@0: tomwalters@0: static char zerodflt[] = "off" , *zerostr = zerodflt ; tomwalters@0: static char formdflt[] = "arch" , *formstr = formdflt ; tomwalters@0: static char origdflt[] = "3.072" , *origstr = origdflt ; tomwalters@0: tomwalters@0: static char ArchStr[] = "arch" ; tomwalters@0: static char LogStr[] = "log" ; tomwalters@0: tomwalters@0: static char expodflt[] = "off" , *expostr = expodflt ; tomwalters@0: tomwalters@0: /*********** [spl,sai] [sie] stage: "stabilized auditory image" ************/ tomwalters@0: tomwalters@0: static Option saiopts[] = { tomwalters@0: tomwalters@0: { "frstep_aid", stepdflt, &stepstr, "Step between frames of the auditory image (ms)",InOutOption}, tomwalters@0: { "pwidth_aid", pwidthdflt, &pwidthstr, "Positive width of auditory image (ms)", InOutOption}, tomwalters@0: { "nwidth_aid", nwidthdflt, &nwidthstr, "Negative width of auditory image (ms)", InOutOption}, tomwalters@0: tomwalters@0: { "form_spd", formdflt, &formstr, "Form of spiral: Archemedian or log", InputOption}, tomwalters@0: { "zeroline_spd", zerodflt, &zerostr, "Draw zero axis of spiral", InOutOption}, tomwalters@0: { "orig_spd", origdflt, &origstr, "Spiral rotation and circuit removal\n", InOutOption}, tomwalters@0: tomwalters@0: { "napdecay_ai", cgmdflt, &cgmstr, "Neural activity decay rate in %/ms", InOutOption}, tomwalters@0: { "stdecay_ai", ttdflt, &ttstr, "Strobe-threshold decay rate in %/ms", InOutOption}, tomwalters@0: {"stcrit_ai", susldflt, &suslevelstr,"Strobe criterion (1 to 5) ", InOutOption}, tomwalters@0: {"stlag_ai" , stlagdflt, &stlagstr, "Auditory image strobe lag time (in ms)", InOutOption}, tomwalters@0: { "stthresh_ai", sustdflt, &susthreshstr, "Strobe threshold set to all points above this", SilentOption}, tomwalters@0: { "decay_ai", decaydflt, &decaystr, "Auditory image decay time constant", InOutOption}, tomwalters@0: { "stinfo_ai", swdflt, &swstr, "Strobe information (off, on, filename)\n", InOutOption}, tomwalters@0: tomwalters@0: { "utrate_ai", utlimdflt, &utlimstr, "Disconnected in R5.6", SilentOption}, tomwalters@0: { "ltrate_ai", ltlimdflt, <limstr, "Disconnected in R5.6", SilentOption}, tomwalters@0: { "ulim_sas", ulimdflt, &ulimstr, "Upper integration limit for auditory image", SilentOption}, tomwalters@0: { "llim_sas", llimdflt, &llimstr, "Lower integration limit for auditory image\n", SilentOption}, tomwalters@0: tomwalters@0: { "exponential_decay" , expodflt, &expostr , "Exponential trigger Decay", SilentOption}, tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: /* generate Stabilised image in image.c */ tomwalters@0: tomwalters@0: static Source SaiEntry( source ) /* CG */ tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: int framestep = Samples( stepstr, Samplerate() ) / Framestep() ; tomwalters@0: int pwidth = Samples( pwidthstr, Samplerate() ) / Framestep() ; tomwalters@0: int nwidth = Samples( nwidthstr, Samplerate() ) / Framestep() ; tomwalters@0: int stlag = Samples( stlagstr, Samplerate() ) / Framestep() ; tomwalters@0: tomwalters@0: tomwalters@0: /* Convert arguments for spiral drawing. See spiral.ch */ tomwalters@0: tomwalters@0: #ifndef DSP32 tomwalters@0: if (strncmp(formstr, ArchStr, strlen( formstr) ) == 0) form_spl = 'A'; tomwalters@0: else if (strncmp(formstr, LogStr, strlen( formstr) ) == 0) form_spl = 'L'; tomwalters@0: else stitch_error("gensai: unknown form_spl\n"); tomwalters@0: tomwalters@0: axis_spl = OptionInt( zerostr ) ; tomwalters@0: zero_spl = OptionDouble( origstr ) ; tomwalters@0: #endif tomwalters@0: tomwalters@0: /* Hack so that spirals never include transient info. */ tomwalters@0: if (strncmp(whichstr,"spl", strlen("spl")) == 0) tomwalters@0: { nwidth=0; tomwalters@0: if ( (int)atoi(suslevelstr)>=4) tomwalters@0: suslevelstr="3"; tomwalters@0: /* if ( (int)atoi(suslevelstr)>=4) tomwalters@0: pwidth+=stlag; tomwalters@0: else tomwalters@0: stlag=0; */ tomwalters@0: } tomwalters@0: /* Hack so that sas and sep have pwidth=max(ulim) and nwidth=min(llim) */ tomwalters@0: tomwalters@0: if ( strcmp(whichstr, "sas") == 0 || strcmp(whichstr, "sep") == 0 ) { tomwalters@0: pwidth = Cycles( ulimstr, frequencies[0], Samplerate() ) ; tomwalters@0: nwidth = Cycles( llimstr, frequencies[0], Samplerate() ) ; tomwalters@0: if (nwidth > 0) nwidth=0; tomwalters@0: } tomwalters@0: tomwalters@0: /* Check ranges of pwidth and nwidth, and quit if invalid */ tomwalters@0: if (pwidth < 0) tomwalters@0: stitch_error("Warning: gensai pwidth_aid should be positive\n"); tomwalters@0: if (nwidth > 0) tomwalters@0: stitch_error("Warning: gensai nwidth_aid should be zero or negative\n"); tomwalters@0: tomwalters@0: /* nwidth is given as a -ve value, but is used internally as +ve */ tomwalters@0: nwidth = -(nwidth); tomwalters@0: tomwalters@0: source = Sai( source, Frameheight(), framestep, pwidth, nwidth, tomwalters@0: (int)Samples(decaystr, Samplerate())/Framestep(), tomwalters@0: (int)Samplerate(), frequencies, tomwalters@0: (double)atof(ttstr), tomwalters@0: Samples(cgmstr,Samplerate())/Framestep(), tomwalters@0: (int)Freq(utlimstr), (int)Freq(ltlimstr), (int)atoi(suslevelstr), tomwalters@0: susthreshstr, swstr, expostr, stlag); tomwalters@0: tomwalters@0: setFramewidth( pwidth+nwidth ) ; tomwalters@0: setFramestep( framestep ) ; tomwalters@0: setFrames( Frames()/framestep ) ; tomwalters@0: tomwalters@0: return( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: DelayAxis( min, max, label ) tomwalters@0: double *min, *max ; tomwalters@0: char **label ; tomwalters@0: { tomwalters@0: *min = -Samples( pwidthstr, Samplerate() ) / Samplerate() * 1000. ; tomwalters@0: *max = -Samples( nwidthstr, Samplerate() ) / Samplerate() * 1000. ; tomwalters@0: tomwalters@0: *label = "Integration Interval [ms]" ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: #if 0 /* where did this come from? */ tomwalters@0: /* table of default model options */ tomwalters@0: tomwalters@0: static char llimdflt[] = "3.5", *llimstr = llimdflt ; tomwalters@0: static char ulimdflt[] = "imagedurn", *ulimstr = ulimdflt ; tomwalters@0: static char saidflt[] = "0.25", *saistr = saidflt ; tomwalters@0: /* static char susldflt[] = "1", *suslevelstr = susldflt ; AJD 13-3-95 tomwalters@0: static char sustdflt[] = "0", *susthreshstr = sustdflt; */ tomwalters@0: #endif tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /*********** [sas] [sse] stage: "stabilized auditory spectrogram" **********/ tomwalters@0: tomwalters@0: /* summarise spectrogram by adding across rows */ tomwalters@0: tomwalters@0: static Option sasopts[] = { tomwalters@0: tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static Source SummaryEntry( source ) /* CG */ tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: source = Summary( source, Frameheight(), Scalar( saistr ), frequencies, Samplerate(), llimstr, ulimstr ) ; tomwalters@0: tomwalters@0: setFramewidth( 1 ) ; tomwalters@0: tomwalters@0: return( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: #if defined(DSP32) || defined( THINK_C ) tomwalters@0: static void swab( in, out, bytes ) tomwalters@0: char *in, *out ; tomwalters@0: int bytes ; tomwalters@0: { tomwalters@0: register int i ; tomwalters@0: tomwalters@0: for( i=0 ; isource, 1, DataType ) ; tomwalters@0: tomwalters@0: for( chan=0 ; chanchans ; chan++ ) tomwalters@0: *optr++ = input ; tomwalters@0: } tomwalters@0: tomwalters@0: if( !last ) tomwalters@0: return ( (Pointer) buffer ) ; tomwalters@0: else tomwalters@0: return ( DeleteFillableSource( state ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source TestEntry( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: DeclareNew( struct _test_state *, state ) ; tomwalters@0: tomwalters@0: state->source = source ; tomwalters@0: state->chans = Frameheight() ; tomwalters@0: tomwalters@0: return( SetFillableSource( state, test_callback, "test model.c" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /********************* Option defaults (application specific) *************** tomwalters@0: * Each application may have its own set of option defaults. tomwalters@0: * These override the generic defaults defined for each option, when the tomwalters@0: * options table is constructed, (see constructOptions()). tomwalters@0: * Note that options must have their full names. Abbreviations won't do here. tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: /* Wave and excitation pattern modules */ tomwalters@0: tomwalters@0: #ifndef DSP32 tomwalters@0: static char zerobotstr[] = "bottom=0" ; tomwalters@0: static char excitestr[] = "view=excitation" ; tomwalters@0: static char nohiding[] = "hiddenline=off" ; tomwalters@0: static char downsample[] = "downsample=10ms" ; tomwalters@0: static char turn_on_idt[] = "stages_idt=2" ; tomwalters@0: static char mincfdflt[] = "mincf_afb=50" ; tomwalters@0: static char maxcfdflt[] = "maxcf_afb=5000" ; tomwalters@0: static char chandflt[] = "channels_afb=128" ; tomwalters@0: static char lengthdflt[] = "length=32ms" ; tomwalters@0: static char greyscalestr[] = "view=greyscale" ; tomwalters@0: #endif tomwalters@0: tomwalters@0: char *wavdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: "view=wave", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *stpdflts[] = { /* CG */ tomwalters@0: #ifndef DSP32 tomwalters@0: "view=wave", tomwalters@0: "filter=off", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *asadflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: excitestr, tomwalters@0: "top=2500", zerobotstr, tomwalters@0: nohiding, tomwalters@0: chandflt, /* CG */ tomwalters@0: "transduction=off", /* CG */ tomwalters@0: turn_on_idt, /* CG */ tomwalters@0: downsample, /* CG */ tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *epndflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: excitestr, tomwalters@0: "top=1000", zerobotstr, /* CG */ tomwalters@0: nohiding, tomwalters@0: chandflt, /* CG */ tomwalters@0: turn_on_idt, tomwalters@0: downsample, tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *sepdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: excitestr, tomwalters@0: "top=200", zerobotstr, tomwalters@0: nohiding, tomwalters@0: chandflt, /* CG */ tomwalters@0: "ulim_sas=16ms", "llim_sas=-4ms", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: /* Auditory (ie landscape) modules */ tomwalters@0: tomwalters@0: char *bmmdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: lengthdflt, tomwalters@0: "top=100", "bottom=-100", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *napdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: lengthdflt, tomwalters@0: "top=2000", zerobotstr, /* CG */ tomwalters@0: chandflt, /* CG */ tomwalters@0: "stages_idt=2", tomwalters@0: "tup_idt=0.133ms", tomwalters@0: "downsample=1p", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: tomwalters@0: char *saidflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: "top=500", zerobotstr, /* CG */ tomwalters@0: "stages_idt=2", tomwalters@0: "tup_idt=0.133ms", tomwalters@0: "downsample=1p", tomwalters@0: "frstep_epn=1p", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *spldflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: "view=spiral", tomwalters@0: #ifdef PC tomwalters@0: "width_win=300", "height_win=300", tomwalters@0: #else tomwalters@0: "width_win=500", "height_win=500", tomwalters@0: #endif tomwalters@0: "box_ps=off", /* MAA 6/9/1995 */ tomwalters@0: "figurelinewidth_ps=0.25", /* MAA 6/9/1995 */ tomwalters@0: "top=26", "bottom=25", tomwalters@0: "dencf=1", "pen=2", tomwalters@0: "nwidth_aid=0ms", "pwidth_aid=35ms", tomwalters@0: "stlag=5ms", "stcrit=5", /* AJD */ tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: /* Speech (ie greyscale) modules */ tomwalters@0: tomwalters@0: char *sgmdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: greyscalestr, tomwalters@0: "top=2500", zerobotstr, tomwalters@0: chandflt, /* CG */ tomwalters@0: "transduction=off", /* CG */ tomwalters@0: turn_on_idt, tomwalters@0: downsample, tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *cgmdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: greyscalestr, tomwalters@0: "top=1000", zerobotstr, /* CG */ tomwalters@0: chandflt, /* CG */ tomwalters@0: turn_on_idt, tomwalters@0: downsample, tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: char *sasdflts[] = { tomwalters@0: #ifndef DSP32 tomwalters@0: greyscalestr, tomwalters@0: "top=300", zerobotstr, /* CG */ tomwalters@0: chandflt, /* CG */ tomwalters@0: "stages_idt=off", tomwalters@0: "frstep_epn=off", tomwalters@0: "downsample=off", tomwalters@0: "ulim_sas=16ms", "llim_sas=-4ms", tomwalters@0: #endif tomwalters@0: (char *)0 } ; tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /******************************* stage table ******************************** tomwalters@0: * tomwalters@0: * The "stages" are application names. tomwalters@0: * A stage identifier name is the last three chars of the program name. tomwalters@0: * (Eg "sai" is the stage identifier for the stabilized auditory image tomwalters@0: * application, which is a program called "gensai". This is an alias for tomwalters@0: * the "gen" program, provided by one of the set of symbolic links). tomwalters@0: * The stages are grouped into "models" (each an array of structs below): tomwalters@0: * envelope: calculation of the envelope of the underlying function. tomwalters@0: * fine: calculation of the whole ("fine structure") of the function. tomwalters@0: * complex tomwalters@0: * nonmult tomwalters@0: * noncalc tomwalters@0: * tomwalters@0: * FindStage( which ) - find a place in the stage table for the program goal. tomwalters@0: * Take a stage identifier, (contained in the "which" string), and return a ptr tomwalters@0: * to the corresponding stage structure, (one line of one of the arrays below). tomwalters@0: * tomwalters@0: * The returned goal stage is the final processing stage of the sequence of tomwalters@0: * stages which make up the program. tomwalters@0: * The sequential order of processing is dictated by the stage table. tomwalters@0: * The sequence of stages is from the first stage (texually at the bottom of tomwalters@0: * each "model" group in the stage table), through each stage back up the table tomwalters@0: * to the goal stage. tomwalters@0: * tomwalters@0: * The stage structure (defined below) is as follows: tomwalters@0: * struct _stage { tomwalters@0: * char *ident ; Stage identifier name tomwalters@0: * Source (*entry)() ; Pointer to function for entry to stage tomwalters@0: * Option *options ; Model options for stage (see table.c) tomwalters@0: * char **defaults ; Option defaults for stage (see gen.c) tomwalters@0: * char *help ; Description of stage tomwalters@0: * }; tomwalters@0: * tomwalters@0: * For example, the sai stage (found when gensai is asked for) is: tomwalters@0: * "sai", SaiEntry, saiopts, saidflts, "stabilized auditory image", tomwalters@0: * tomwalters@0: * The stage struct fields are: tomwalters@0: * tomwalters@0: * *ident tomwalters@0: * Stage identifier name used by FindStage() to match a stage struct to the tomwalters@0: * application. The stage is found by matching the ident string against those tomwalters@0: * stored in the model arrays of stages. The default stage is "wav". tomwalters@0: * tomwalters@0: * (*entry)() tomwalters@0: * The name of the entry-point function for the stage. Most entry-point tomwalters@0: * functions are defned in model.c. The entry-point function name is only tomwalters@0: * accessed by a call to FindStage() from ModeledSource() in gen.c. tomwalters@0: * tomwalters@0: * *options tomwalters@0: * The options field of a stage is used by the constructOptions() routine tomwalters@0: * to include the model options for that stage in the complete options table tomwalters@0: * which it constructs. This is composed of the display options, (which are tomwalters@0: * common to all applications, and are listed in array displayopts[] in gen.c), tomwalters@0: * the model options for the stage, (which are listed in table.c), AND all the tomwalters@0: * model options given for each of the stages back to the start stage, (at the tomwalters@0: * bottom of the stage table, within a model group of stages). tomwalters@0: * tomwalters@0: * **defaults tomwalters@0: * The defaults field is used by the constructOptions() routine to override the tomwalters@0: * defaults defined for the options which have been included in the complete tomwalters@0: * options table. The reason for this is so that each application can have its tomwalters@0: * own set of option defaults, if necessary. (If defaults are not given tomwalters@0: * or the set is not complete, then the original defaults still apply). tomwalters@0: * The defaults fields contain option defaults which override the generic tomwalters@0: * defaults defined for each option. tomwalters@0: * After the complete options table has been constructed, (constructOptions()), tomwalters@0: * all options in the table will be: tomwalters@0: * a) initialized to their default values (in getnopts()). tomwalters@0: * b) re-initialized by any corresponding options in "rc" files. tomwalters@0: * c) displayed as a help menu (if asked for). tomwalters@0: * tomwalters@0: * *help tomwalters@0: * This message is printed at the top of the help menu. The help field is only tomwalters@0: * accessed by modelHelp(which), called from gen.c, which takes a stage tomwalters@0: * identifier and returns the "help" string of the stage struct which has a tomwalters@0: * matching ident field, to assign it to "helpstring". tomwalters@0: * tomwalters@0: * tomwalters@0: * Its important to note that the options field refers to model options, and tomwalters@0: * these are cumulative over the sequential stages of processing. tomwalters@0: * The defaults field refers to the defaults to be used for the goal stage tomwalters@0: * only, (ie the application), and these are not cumulative. tomwalters@0: * The complete options table (constructed at run time) consists of the display tomwalters@0: * options, and the accumulated model options (one group per processing stage). tomwalters@0: * tomwalters@0: * The NullEntry routine is a dummy which does no processing, and is used to tomwalters@0: * introduce aliases into the stage sequence. tomwalters@0: * tomwalters@0: * Routines which call FindStage(), and access the stage table: tomwalters@0: * tomwalters@0: * main() tomwalters@0: * | tomwalters@0: * +----------------------+-----------------+ tomwalters@0: * | | | tomwalters@0: * | | | tomwalters@0: * constructOptions() ModeledSource() modelHelp() tomwalters@0: * | | | tomwalters@0: * | | | tomwalters@0: * +----------------------+-----------------+ tomwalters@0: * | tomwalters@0: * FindStage() tomwalters@0: * tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: tomwalters@0: #define NO_OPTS (Option *) 0 tomwalters@0: #define NO_DFLTS (char **) 0 tomwalters@0: tomwalters@0: struct _stage *FindStage( which ) tomwalters@0: char *which ; tomwalters@0: { tomwalters@0: static struct _stage envelope[] = { tomwalters@0: "sse", SummaryEntry, sasopts, sasdflts, "stabilized auditory spectrogram", tomwalters@0: "sie", SaiEntry, saiopts, saidflts, "stabilized auditory image", tomwalters@0: "sem", NullEntry, NO_OPTS, NO_DFLTS, "spectrogram", tomwalters@0: "fed", DownSampleEntry, dwnopts, NO_DFLTS, "downsampled filter envelope", tomwalters@0: "fei", IntegralEntry, fbiopts, NO_DFLTS, "integrated filter envelope", tomwalters@0: "feh", HardEntry, fbhopts, NO_DFLTS, "hard limited filter envelope", tomwalters@0: "fea", AdaptEntry, fbaopts, NO_DFLTS, "adapted filter envelope", tomwalters@0: "fet", ThresholdEntry, fbtopts, NO_DFLTS, "thresholded filter envelope", tomwalters@0: "fel", LowpassEntry, fblopts, NO_DFLTS, "low-pass filtered filter envelope", tomwalters@0: "fes", SaturateEntry, fbsopts, NO_DFLTS, "saturated filter envelope", tomwalters@0: "feu", UncompressEntry, fbuopts, NO_DFLTS, "uncompressed filter envelope", tomwalters@0: "fec", EnvelopeEntry, fbcopts, NO_DFLTS, "compressed filter envelope", tomwalters@0: "fem", NullEntry, fbmopts, NO_DFLTS, "dummy entry to get options through", tomwalters@0: "wav", NullEntry, wavopts, wavdflts, "picture of wave", tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static struct _stage fine[] = { tomwalters@0: "sep", NullEntry, NO_OPTS, sepdflts, "stabilized excitation pattern", tomwalters@0: "sas", SummaryEntry, sasopts, sasdflts, "stabilized auditory spectrogram", tomwalters@0: "spl", NullEntry, NO_OPTS, spldflts, "spiral stabilized auditory image", tomwalters@0: "sai", SaiEntry, saiopts, saidflts, "stabilized auditory image", tomwalters@0: "sgm", NullEntry, NO_OPTS, sgmdflts, "spectrogram", tomwalters@0: "cgm", NullEntry, NO_OPTS, cgmdflts, "cochleogram", tomwalters@0: "nap", NullEntry, NO_OPTS, napdflts, "neural activity pattern", tomwalters@0: "asa", NullEntry, NO_OPTS, asadflts, "auditory spectral analysis", tomwalters@0: "epn", NullEntry, NO_OPTS, epndflts, "excitation pattern", tomwalters@0: "fbd", DownSampleEntry, dwnopts, NO_DFLTS, "downsampled filter output", tomwalters@0: "fbi", IntegralEntry, fbiopts, NO_DFLTS, "integrated filter output", tomwalters@0: "fbh", HardEntry, fbhopts, NO_DFLTS, "hard limited filter output", tomwalters@0: "fba", AdaptEntry, fbaopts, NO_DFLTS, "adapted transduced filter output", tomwalters@0: "fbt", ThresholdEntry, fbtopts, NO_DFLTS, "thresholded filter output", tomwalters@0: "fbl", LowpassEntry, fblopts, NO_DFLTS, "low-pass filtered filter output", tomwalters@0: "fbs", SaturateEntry, fbsopts, NO_DFLTS, "saturated filter output", tomwalters@0: "fbu", UncompressEntry, fbuopts, NO_DFLTS, "uncompressed filter output", tomwalters@0: "fbc", LogEntry, fbcopts, NO_DFLTS, "compressed filter output", tomwalters@0: "fbr", RectifyEntry, fbropts, NO_DFLTS, "rectified filter output", tomwalters@0: "fbm", NullEntry, NO_OPTS, NO_DFLTS, "auditory filter output", /* CG */ tomwalters@0: "stp", FineEntry, fbmopts, stpdflts, "stapes vibration output", /* CG */ tomwalters@0: "wav", NullEntry, wavopts, wavdflts, "picture of wave", tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static struct _stage complex[] = { tomwalters@0: "fcp", PolarEntry, NO_OPTS, NO_DFLTS, "polar co-ordinate complex output", tomwalters@0: "fcr", ComplexEntry, fbmopts, NO_DFLTS, "rectangular co-ordinate complex output", tomwalters@0: "wav", NullEntry, wavopts, wavdflts, "picture of wave", tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static struct _stage nonmult[] = { tomwalters@0: "bmm", NullEntry, NO_OPTS, bmmdflts, "basilar membrane motion", /* CG */ tomwalters@0: "stp", FineEntry, fbmopts, stpdflts, "stapes vibration output", /* CG */ tomwalters@0: "wav", NullEntry, wavopts, wavdflts, "draw wave", tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static struct _stage noncalc[] = { tomwalters@0: "tst", TestEntry, NO_OPTS, NO_DFLTS, "Test system", tomwalters@0: "wav", NullEntry, wavopts, wavdflts, "draw wave", tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: static struct _stage *models[] = { envelope, fine, complex, nonmult, noncalc, ( struct _stage * ) 0 } ; tomwalters@0: tomwalters@0: struct _stage *stage ; tomwalters@0: int model ; tomwalters@0: tomwalters@0: /* for each type of model */ tomwalters@0: for( model=0 ; models[ model ] != ( struct _stage * ) 0 ; model++ ) tomwalters@0: /* for each stage in the model */ tomwalters@0: for( stage=models[ model ] ; stage->ident != ( char * ) 0 ; stage++ ) tomwalters@0: if( strncmp( which, stage->ident, strlen( stage->ident ) ) == 0 ) { tomwalters@0: tomwalters@0: /* kludge to fix bug (see fixchans routine below) */ tomwalters@0: if ( strcmp( which, "nap" ) == 0 ) tomwalters@0: fixchans( stage->defaults ) ; tomwalters@0: tomwalters@0: return ( stage ) ; tomwalters@0: } tomwalters@0: tomwalters@0: return ( FindStage( "wav" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /* Return the "help" string for the given stage identifier */ tomwalters@0: /* This routine is called once from gen.c:main() */ tomwalters@0: char *modelHelp( which ) tomwalters@0: char *which ; tomwalters@0: { tomwalters@0: return( FindStage( which )->help ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* tomwalters@0: This routine is a hack to fix a bug we caused earlier! tomwalters@0: We changed the order of entry points in Findstage, so that nap was able tomwalters@0: to use the lp filter. But this caused nap to inherit the defaults of all tomwalters@0: the other entry points which use that filter. In particular, the number of tomwalters@0: channels for nap was changed as a result of this. This hack is designed to tomwalters@0: restore the number chans, in the case of gennap only, to their default tomwalters@0: value. tomwalters@0: */ tomwalters@0: tomwalters@0: fixchans( str ) tomwalters@0: char **str ; tomwalters@0: { tomwalters@0: while ( *str != (char *)0 ) { tomwalters@0: if ( strncmp( *str, "channels_afb", 12 ) == 0 ) { tomwalters@0: strcpy( (*str)+13, chansdflt ) ; tomwalters@0: /* fprintf(stderr, "fixchans: %s\n", *str ) ; */ tomwalters@0: break ; tomwalters@0: } tomwalters@0: *str++ ; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /*********************** Strings for use in DSP version ********************/ tomwalters@0: tomwalters@0: #if defined(DSPHOST) || defined(DSP32) tomwalters@0: #if 00 tomwalters@0: char **shared[] = { &llimstr, &ulimstr, &saistr, &pwidthstr, tomwalters@0: &nwidthstr, <limstr, &utlimstr, &ttstr, tomwalters@0: &cgmstr, &decaystr, &stepstr, &downsstr, tomwalters@0: &stagestr, &upstr, &downstr, &lossstr, tomwalters@0: &vlossstr, &igainstr, &hardstr, &adapstr, tomwalters@0: ×str, &vdrainstr, &propstr, &faststr, tomwalters@0: &latstr, &rapidstr, &risestr, &stxstr, tomwalters@0: &lstagestr, &lupstr, &ldownstr, &llossstr, tomwalters@0: &lvlossstr, &ligainstr, &meddisstr, &satstr, tomwalters@0: &logstr, &rectstr, &qualstr, &limitstr, tomwalters@0: &interpstr, &minstr, &maxstr, &denstr, tomwalters@0: &chansstr, &orderstr, &phasestr, &gainstr, tomwalters@0: &audiostr, &floatstr, &samplestr, &bitstr, tomwalters@0: &envstr, &whichstr, &framesstr, &framebytesstr, tomwalters@0: &framewidthstr, &frameheightstr, &framestepstr, tomwalters@0: ( char ** ) 0 } ; tomwalters@0: #endif tomwalters@0: char **returned[] = { &framesstr, &framebytesstr, &framewidthstr, tomwalters@0: &frameheightstr, &framestepstr, tomwalters@0: ( char ** ) 0 } ; tomwalters@0: tomwalters@0: #endif tomwalters@0: tomwalters@0: tomwalters@0: /******* support for DSP32 C ******************/ tomwalters@0: tomwalters@0: #ifdef DSP32 tomwalters@0: void receiveParameters( parameters, psize ) tomwalters@0: char *parameters ; tomwalters@0: short psize ; tomwalters@0: { tomwalters@0: struct _stage *stage = FindStage( "sas" ), *sptr ; tomwalters@0: char *bptr ; tomwalters@0: int c ; tomwalters@0: tomwalters@0: for( sptr = stage ; sptr->ident != (char *) 0 ; sptr++ ) tomwalters@0: ; tomwalters@0: tomwalters@0: sptr-- ; tomwalters@0: tomwalters@0: for( bptr = parameters ; bptr < parameters + psize ; sptr-- ) tomwalters@0: if( sptr->options != (Option *) 0 ) tomwalters@0: for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) { tomwalters@0: *(sptr->options[c].value) = bptr ; tomwalters@0: bptr += strlen( bptr ) + 1 ; tomwalters@0: } tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: #endif tomwalters@0: tomwalters@0: #ifdef DSPHOST tomwalters@0: #include "utils.h" tomwalters@0: #define DSP_BIN_VAR "DSPBIN" tomwalters@0: #define DEFAULT_DSP_BIN "c:\\bin\\dspmain" tomwalters@0: extern char *getenv() ; tomwalters@0: tomwalters@0: void sendParameters( which ) tomwalters@0: char *which ; tomwalters@0: { tomwalters@0: register struct _stage *stage = FindStage( which ), *sptr ; tomwalters@0: unsigned c, bytes = 0 ; tomwalters@0: char *buffer, *bptr ; tomwalters@0: long paddr, baddr ; tomwalters@0: tomwalters@0: for( sptr = stage ; sptr->ident != (char *) 0 ; sptr++ ) tomwalters@0: if( sptr->options != (Option *) 0 ) tomwalters@0: for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) tomwalters@0: bytes += strlen( *(sptr->options[c].value) ) + 1 ; tomwalters@0: tomwalters@0: sptr-- ; tomwalters@0: tomwalters@0: buffer = Allocate( bytes, "argument array model.c" ) ; tomwalters@0: tomwalters@0: for( bptr = buffer ; sptr >= stage ; sptr-- ) tomwalters@0: if( sptr->options != (Option *) 0 ) tomwalters@0: for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) { tomwalters@0: (void) strcpy( bptr, *(sptr->options[c].value) ) ; tomwalters@0: bptr += strlen( bptr ) + 1 ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: paddr = find_label_name( "psize" ) ; tomwalters@0: tomwalters@0: dsp_dl_int( paddr, (int) ( bptr - buffer ) ) ; tomwalters@0: tomwalters@0: baddr = find_label_name( "params" ) ; tomwalters@0: tomwalters@0: while( dsp_up_long( baddr ) == 0 ) tomwalters@0: ; tomwalters@0: tomwalters@0: dsp_dl_bytes( deref( baddr ), (long) ( bptr - buffer ), buffer ) ; tomwalters@0: tomwalters@0: dsp_dl_int( paddr, 0 ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: struct _dsp_state { unsigned long needed_addr, output_addr, errno_addr ; } ; tomwalters@0: tomwalters@0: static void dsp_callback( state, bytes, buffer ) tomwalters@0: struct _dsp_state *state ; tomwalters@0: ByteCount bytes ; tomwalters@0: Pointer buffer ; tomwalters@0: { tomwalters@0: char errbuff[200] ; tomwalters@0: tomwalters@0: /* tell dsp how much you want */ tomwalters@0: tomwalters@0: dsp_dl_int( state->needed_addr, bytes ) ; tomwalters@0: tomwalters@0: /* wait for it to provide it */ tomwalters@0: tomwalters@0: while( dsp_up_int( state->needed_addr ) != 0 ) tomwalters@0: if( dsp_up_int( state->errno_addr ) != 0 ) { tomwalters@0: /* tomwalters@0: if( dispw != ( WindowObject ) 0 ) Close( dispw ) ; tomwalters@0: */ tomwalters@0: dsp_up_bytes( find_label_name( "errstr" ), (long) sizeof ( errbuff ), errbuff ) ; tomwalters@0: printf( "freemem %ld stackmax %lx\n", tomwalters@0: dsp_up_long( find_label_name( "freemem" ) ), tomwalters@0: dsp_up_long( find_label_name( "stackmax" ) ) ) ; tomwalters@0: stitch_error( errbuff, dsp_up_int( find_label_name( "errno" ) ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /* upload it into PC buffer */ tomwalters@0: tomwalters@0: dsp_up_bytes( deref( state->output_addr ), (long) bytes, buffer ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: Source DspSource( source ) tomwalters@0: Source source ; tomwalters@0: { tomwalters@0: DeclareNew( struct _dsp_state *, state ) ; tomwalters@0: unsigned long addr ; tomwalters@0: char errbuff[200] ; tomwalters@0: char ***param ; tomwalters@0: char *binary_path = getenv( DSP_BIN_VAR ) ; tomwalters@0: tomwalters@0: if( binary_path == ( char * ) 0 ) tomwalters@0: binary_path = DEFAULT_DSP_BIN ; tomwalters@0: tomwalters@0: /* load dsp */ tomwalters@0: tomwalters@0: (void) fprintf( stderr, "Downloading %s to DSP32 at i/o addres 0x%x\n", binary_path, default_addr() ) ; tomwalters@0: tomwalters@0: if( dsp_dl_exec( binary_path ) == 0 ) tomwalters@0: stitch_error( "\nDSP load failed\n" ) ; tomwalters@0: tomwalters@0: /* start dsp */ tomwalters@0: tomwalters@0: dsp_run() ; tomwalters@0: tomwalters@0: /* send parameters down to model */ tomwalters@0: tomwalters@0: sendParameters( whichstr ) ; tomwalters@0: tomwalters@0: /* send down input if required */ tomwalters@0: tomwalters@0: if( whichstr[0] != 'i' ) { tomwalters@0: tomwalters@0: addr = find_label_name( "input" ) ; tomwalters@0: tomwalters@0: while( dsp_up_long( addr ) == 0 ) tomwalters@0: ; tomwalters@0: tomwalters@0: (void) fprintf( stderr, "Downloading input file of %ld points to dsp addres 0x%lx\n", Frames(), deref( addr ) ) ; tomwalters@0: tomwalters@0: dsp_dl_array( deref( addr ), Frames(), PullInts( source, Frames() ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /* wait for model setup */ tomwalters@0: tomwalters@0: state->needed_addr = find_label_name( "needed" ) ; tomwalters@0: state->output_addr = find_label_name( "output" ) ; tomwalters@0: state->errno_addr = find_label_name( "errno" ) ; tomwalters@0: tomwalters@0: addr = find_label_name( "source" ) ; tomwalters@0: tomwalters@0: while( dsp_up_long( addr ) == 0l && dsp_up_int( state->errno_addr ) == 0 ) tomwalters@0: (void) fprintf( stderr, "Waiting for dsp (status:%d)\r", dsp_up_long( addr ) ) ; tomwalters@0: tomwalters@0: if( dsp_up_int( state->errno_addr ) != 0 ) { tomwalters@0: dsp_up_bytes( find_label_name( "errstr" ), (long) sizeof ( errbuff ), errbuff ) ; tomwalters@0: (void) fprintf( stderr, "dsp error: %s\n", errbuff ) ; tomwalters@0: stitch_error( "so there" ) ; tomwalters@0: } tomwalters@0: tomwalters@0: (void) fprintf( stderr, "DSP setup (source=0x%lx)\n", dsp_up_long( addr ) ) ; tomwalters@0: tomwalters@0: addr = find_label_name( "returned" ) ; tomwalters@0: tomwalters@0: for( param=returned ; *param != ( char ** ) 0 ; param++ ) { tomwalters@0: tomwalters@0: dsp_up_bytes( deref( deref( addr ) ), RETURN_SIZE, **param ) ; tomwalters@0: addr += 4 ; tomwalters@0: } tomwalters@0: #if 0 tomwalters@0: fprintf( stderr, "Frames %ld - %d %d %d\n\nType Return\n", Frames(), Frameheight(), Framewidth(), Framebytes() ) ; tomwalters@0: getchar() ; tomwalters@0: #endif tomwalters@0: return ( stdAutoSource( ( Pointer ) state, dsp_callback ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: #endif tomwalters@0: tomwalters@0: /*************************************************************************** tomwalters@0: * ModeledSource() tomwalters@0: * Called from main() in gen.c to initialize a chain of objects which will tomwalters@0: * ultimately execute the program, (see also SinkSource() in gen.c:main). tomwalters@0: * tomwalters@0: * The routine ModeledSource() first uses Findstage() to find the appropriate tomwalters@0: * place in the stage table, called for by the program, (and indicated by tomwalters@0: * "whichstr", the last three chars of the program's name). tomwalters@0: * Then it finds the end of the table, and works back up to the stage called tomwalters@0: * for by the program. tomwalters@0: * At each stage, call the corresponding entry-point function, (provided it's tomwalters@0: * not a null pointer), to create and initialize a source object. tomwalters@0: * (Each stage in the table is a process on the way to the program as a whole. tomwalters@0: * The order of the stage table sets the order of processing). tomwalters@0: * tomwalters@0: * The "check" argument is used when the "useprevious" option is on, tomwalters@0: * (see main() and checkForFile() in gen.c), otherwise it will be a null ptr. tomwalters@0: ***************************************************************************/ tomwalters@0: tomwalters@0: Source ModeledSource( source, check ) tomwalters@0: Source source ; tomwalters@0: Source (*check)() ; tomwalters@0: { tomwalters@0: /* Find the place in the stage table called for by the program */ tomwalters@0: register struct _stage *sptr, *stage = FindStage( whichstr ) ; tomwalters@0: Source stmp ; tomwalters@0: tomwalters@0: #if !defined( DSP32 ) && !defined( THINK_C ) tomwalters@0: if( OptionInt( swapstr ) != 0 ) tomwalters@0: source = SwabEntry( source ) ; tomwalters@0: #endif tomwalters@0: tomwalters@0: #ifdef DSPHOST tomwalters@0: if( getenv( "DSP32" ) != ( char * ) 0 ) tomwalters@0: return ( DspSource( source ) ) ; tomwalters@0: else tomwalters@0: (void) fprintf( stderr, "Not using DSP card\n" ) ; tomwalters@0: #endif tomwalters@0: tomwalters@0: if( stage->entry == ( Source ( * )() ) 0 ) tomwalters@0: return ( source ) ; tomwalters@0: #if 00 tomwalters@0: /* Set frameheight (channels) and centre-frequencies array */ tomwalters@0: updateFrequencies() ; tomwalters@0: #endif tomwalters@0: tomwalters@0: #ifdef FLOAT tomwalters@0: source = ShortFloatSource( source ) ; tomwalters@0: #endif tomwalters@0: tomwalters@0: /* Find the end of the stage table */ tomwalters@0: for( sptr = stage ; sptr->ident != ( char * ) 0 ; sptr++ ) tomwalters@0: ; tomwalters@0: tomwalters@0: /* Work back up the stage table to the stage called for by the program */ tomwalters@0: /* At each stage, call the entry-point function (if it's not null) */ tomwalters@0: while( sptr-- > stage ) { tomwalters@0: tomwalters@0: if( sptr->entry != (Source ( * )()) 0 ) tomwalters@0: source = sptr->entry( source ) ; tomwalters@0: tomwalters@0: if( check != ( Source ( * )() ) 0 ) { tomwalters@0: stmp = check( sptr->ident ) ; tomwalters@0: if( _SPTR( stmp ) != (struct _source *) 0 ) { tomwalters@0: tomwalters@0: #ifdef FLOAT tomwalters@0: source = ShortFloatSource( stmp ) ; tomwalters@0: #else tomwalters@0: source = stmp ; tomwalters@0: #endif tomwalters@0: /* Set frameheight (channels) and centre-frequencies array */ tomwalters@0: updateFrequencies() ; tomwalters@0: } tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: #ifdef FLOAT tomwalters@0: source = FloatShortSource( source ) ; tomwalters@0: #endif tomwalters@0: tomwalters@0: setFrames( Frames() ) ; tomwalters@0: tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: