comparison model/corti.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:5242703e91d3
1 /*
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
3 ===========================================================================
4
5 Permission to use, copy, modify, and distribute this software without fee
6 is hereby granted for research purposes, provided that this copyright
7 notice appears in all copies and in all supporting documentation, and that
8 the software is not redistributed for any fee (except for a nominal shipping
9 charge). Anyone wanting to incorporate all or part of this software in a
10 commercial product must obtain a license from the Medical Research Council.
11
12 The MRC makes no representations about the suitability of this
13 software for any purpose. It is provided "as is" without express or implied
14 warranty.
15
16 */
17
18 /*
19 corti.c
20 =======
21
22 attempt at model of organ of corti
23
24
25 Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit.
26
27
28 Author : John Holdsworth
29 Written : 30th November, 1988.
30
31 Edited :
32
33 Christian Giguere, March 1994.
34 - Changed option "scale_at" into "gain_at".
35 - That option is now passed to newCorti() as a double instead of an integer
36 - In Corti(), this meant multiplying *optr by state->scale
37 - To locate changes, search for "CG"
38
39 */
40 #include <stdio.h>
41 #include <math.h>
42
43 #include "stitch.h"
44 #include "source.h"
45 #include "corti.h"
46 #include "calc.h"
47
48 #if 0
49 #define DEBUG
50 #endif
51
52 #ifndef lint
53 static char *sccs_id = "@(#)corti.c 1.15 J. Holdsworth (MRC-APU) 5/31/91" ;
54 #endif
55
56 /* calmB is the mB of the magnitude where the slope of temporal recovery is calculated */
57 /* 5497 corresponds to a magnitude of 500 units */
58
59 static double calmB = 5497. ;
60
61 struct _cell_state {
62 StoreType microphonic, rapid_limit, absolute_limit ;
63 ScalarType rapid_rise, fast_rise, rapid_decay, fast_decay ;
64 double compensate ; /* Changed to double from StoreType (mha:22/1/93) */
65 } ;
66
67 struct _corti_state {
68 struct _cell_state *cell_states ;
69 StoreType scale ;
70 ScalarType t_lat ;
71 unsigned cells, times ;
72 } ;
73
74
75 /* global variable for spectral tilt control to compensate for differences */
76 /* between channels in terms of mean firing rate */
77
78 double compensate = 1. ;
79
80
81 char *newCorti( cells, samplerate, center_frequencies, bandwidth_function, t_rise, t_lat, t_rapid, t_fast, prop, absthresh, times, scale )
82 int cells ;
83 double samplerate, *center_frequencies, (*bandwidth_function)(), t_rise, t_lat, t_rapid, t_fast, prop, absthresh ;
84 int times ;
85 double scale ; /* CG: 22/03/94 */
86 {
87 DeclareNew( struct _corti_state *, state ) ;
88 struct _cell_state *cell_ptr ;
89 double ratio, k_rise ;
90 double expected_rate, expected_reference ;
91
92 /* parameters that are constant across cells */
93
94 state->t_lat = SCALAR( t_lat / ( samplerate * times ) ) ;
95
96 state->cells = cells ;
97 state->times = times ;
98 state->scale = scale ;
99
100 state->cell_states = NewArray( struct _cell_state, state->cells, "corti.c for cell states" ) ;
101
102 for( cell_ptr = state->cell_states ; cell_ptr < state->cell_states + cells ; cell_ptr++ ) {
103
104 /* corti states */
105
106 cell_ptr->microphonic = SCALAR( absthresh ) ;
107 cell_ptr->rapid_limit = SCALAR( absthresh ) ;
108 cell_ptr->absolute_limit = SCALAR( absthresh ) ;
109
110 /* recovery time constants */
111
112 cell_ptr->rapid_decay = SCALAR( bandwidth_function( center_frequencies[cell_ptr-state->cell_states] ) *
113 t_rapid * calmB / ( calmB - absthresh ) / samplerate /* / ( 1. - prop ) */ ) ;
114
115 cell_ptr->fast_decay = SCALAR( 1. / t_fast / samplerate ) ;
116
117 /* adaptation time constants */
118
119 ratio = prop / ( 1. - prop ) / cell_ptr->rapid_decay * cell_ptr->fast_decay ;
120
121 if( t_rise > 0 )
122 k_rise = t_rise / ( samplerate * times ) ;
123 else
124 k_rise = 1. ;
125
126 cell_ptr->rapid_rise = SCALAR( k_rise * 1. / ( 1. + ratio ) ) ;
127 cell_ptr->fast_rise = SCALAR( k_rise * ratio / ( 1. + ratio ) ) ;
128
129 /* introduce variable amount of compensation w.r.t expected firing rate variation */
130
131 expected_rate = UNSCALE( cell_ptr->rapid_decay ) * ( calmB - absthresh ) ;
132
133 if( cell_ptr == state->cell_states )
134 expected_reference = expected_rate ;
135
136 /* New formula for computing cell_ptr->compensate (mha: 20/1/93) */
137 /* Parameters chosen to flatten pulse-train spectrum. */
138 /* _cell_state member "compensate" changed to double. */
139 /* The exponent used is 1.128*compensate so that the given */
140 /* parameter (compensate_at) can be set as "on" (ie 1.0) for */
141 /* optimal compensation (instead of a magic number) */
142 /* The value for "compensate_at=off", (calmB - absthresh) was */
143 /* chosen as similar to the original, and because the results */
144 /* were appropriate for an un-compensated spectrum. */
145
146 if (compensate)
147 cell_ptr->compensate = pow(center_frequencies[cell_ptr - state->cell_states], 1.128*compensate) + 800. ;
148 else
149 cell_ptr->compensate = calmB - absthresh ;
150
151 /* Originally, compensate used the SCALAR macro, and so it failed */
152 /* for a floating-point version (defined in calc.h). */
153 /* To fix this, the new compensate formula is scaled up using the */
154 /* original integer version of the UNSCALE macro (see calc.h). */
155
156 #ifdef FLOAT
157 cell_ptr->compensate /= (float) ( 1l << 16l ) ;
158 #endif
159
160 #ifdef DEBUG
161 (void) fprintf( stderr, "rapid_decay:%f fast_decay:%f ratio:%f k_rise:%f rapid_rise:%f fast_rise:%f compensation:%f\n",
162 UNSCALE(cell_ptr->rapid_decay), UNSCALE(cell_ptr->fast_decay),
163 ratio, k_rise, UNSCALE(cell_ptr->rapid_rise), UNSCALE(cell_ptr->fast_rise),
164 1./UNSCALE(cell_ptr->compensate) ) ;
165 #endif
166 }
167 #ifdef DEBUG
168 (void) fprintf( stderr, "times:%d t_lat:%f\n", times, UNSCALE( state->t_lat ) ) ;
169 #endif
170
171 return( (char *) state ) ;
172 }
173
174 int Corti( state_ptr, bytes, out, end, in )
175 char *state_ptr ;
176 ByteCount *bytes ;
177 DataType *out, *end, *in ;
178 {
179 register struct _corti_state *state = (struct _corti_state *) state_ptr ;
180 register struct _cell_state *cell_ptr, *cell_end = state->cell_states + state->cells ;
181 register DataType *iptr, *optr, *eptr = end ;
182 register StoreType delta, old_last_mic ;
183 register int time ;
184
185 while( out < eptr ) {
186
187 for( time=0 ; time < state->times ; time++ ) {
188
189 cell_ptr = state->cell_states ;
190
191 iptr = in ;
192 optr = out ;
193
194 /* raise threhsolds */
195
196 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ ) {
197
198 if( time == 0 )
199 *optr = 0 ;
200
201 delta = *iptr++ - DESCALE( cell_ptr->microphonic ) ;
202
203 if( delta > 0 ) {
204
205 cell_ptr->microphonic += delta * cell_ptr->rapid_rise ;
206 cell_ptr->rapid_limit += delta * cell_ptr->fast_rise ;
207
208 *optr += delta ;
209 }
210
211 optr++ ;
212 }
213
214 /* leak thresholds symetrically across channels */
215
216 old_last_mic = state->cell_states->microphonic ;
217
218 for( cell_ptr = state->cell_states+1 ; cell_ptr < cell_end ; cell_ptr++ ) {
219
220 delta = DESCALE( old_last_mic - cell_ptr->microphonic ) * state->t_lat ;
221 old_last_mic = cell_ptr->microphonic ;
222
223 if( cell_ptr-1 != state->cell_states )
224 (cell_ptr-1)->microphonic -= delta ;
225
226 if( cell_ptr+1 != cell_end )
227 (cell_ptr )->microphonic += delta ;
228 }
229 }
230
231 /* decay potentails */
232
233 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
234 cell_ptr->microphonic -= DESCALE( cell_ptr->microphonic - cell_ptr->rapid_limit ) * cell_ptr->rapid_decay ;
235
236 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
237 cell_ptr->rapid_limit -= DESCALE( cell_ptr->rapid_limit - cell_ptr->absolute_limit ) * cell_ptr->fast_decay ;
238
239 /* generate output */
240
241 iptr = in ;
242 optr = out ;
243
244 if( state->scale >= 0 ) /* CG: 22/3/94 */
245 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ ) {
246 delta = SCALE( *iptr++ ) - cell_ptr->microphonic ;
247 if( delta > 0 )
248 *optr++ = state->scale * delta / cell_ptr->compensate ; /* CG: 22/3/94 */
249 else
250 *optr++ = 0 ;
251 }
252 else if( state->scale < 0 )
253 switch( (int) state->scale ) {
254
255 /* output internal states */
256
257 case -1 :
258 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
259 *optr++ = DESCALE( cell_ptr->microphonic ) ;
260
261 break ;
262
263 case -2 :
264 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
265 *optr++ = DESCALE( cell_ptr->rapid_limit ) ;
266
267 break ;
268
269 default :
270 for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
271 *optr++ = ( *iptr++ - DESCALE( cell_ptr->microphonic ) ) * -state->scale ;
272
273 break ;
274
275 }
276 /* else leave value as is */
277
278
279 /* next frame */
280
281 in += state->cells ;
282 out += state->cells ;
283 }
284
285 /* return amount processed */
286
287 return ( *bytes ) ;
288 }
289
290 /* for compatability */
291
292 int OldCorti( state_ptr, cells, in, out )
293 char *state_ptr ;
294 unsigned cells ;
295 DataType *in, *out ;
296 {
297 ByteCount bytes = ToBytes( DataType, cells ) ;
298
299 return ( ToPoints( DataType, Corti( state_ptr, &bytes, out, out+cells, in ) ) ) ;
300 }
301
302 void closeCorti( state )
303 struct _corti_state *state ;
304 {
305 Delete( state->cell_states ) ;
306 Delete( state ) ;
307
308 return ;
309 }
310
311
312 /* experimental corti simulation */
313
314
315 struct _corti2_state { int *working, *falls, slope, scale ; short *forward, *backward ; } ;
316
317 char *newCorti2( cells, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, t_slope, scale, forward, backward )
318 int cells ;
319 double samplerate, *center_frequencies, (*bandwidth_function)(), bandwidth_scalar, t_slope, scale ;
320 short *forward, *backward ;
321 {
322 DeclareNew( struct _corti2_state *, state ) ;
323 int i ;
324
325 state->working = NewArray( int, cells, "corti.c for works" ) ;
326 state->falls = NewZeroedArray( int, cells, "corti.c for falls" ) ;
327
328 for( i=0 ; i < cells ; i++ )
329 state->falls[i] = bandwidth_function( center_frequencies[i] ) * bandwidth_scalar /
330 samplerate * t_slope ;
331
332 state->forward = forward ;
333 state->backward = backward ;
334
335 state->scale = scale ;
336
337 return( ( char * ) state ) ;
338 }
339
340 int Corti2( state_ptr, cells, in, out )
341 char *state_ptr ;
342 unsigned cells ;
343 short *in, *out ;
344 {
345 struct _corti2_state *state ;
346 register int i, when ;
347
348 state = ( struct _corti2_state * ) state_ptr ;
349
350 for( i=0 ; i<cells ; i++ ) {
351 state->working[i] -= state->falls[i] ;
352 out[i] = in[i] - state->working[i] ;
353 if( out[i] > 0 )
354 state->working[i] += out[i] ;
355 }
356
357 when = 0 ;
358
359 for( i=1 ; i<cells ; i++ )
360 if( state->working[i] < state->working[ when ] + state->forward[ i - when ] ) {
361 state->working[i] = state->working[ when ] + state->forward[ i - when ] ;
362 out[i] = 0 ;
363 }
364 else
365 when = i ;
366
367 when = cells-1 ;
368
369 for( i=cells-2 ; i>=0 ; i-- )
370 if( state->working[i] < state->working[ when ] + state->backward[ when - i ] ) {
371 state->working[i] = state->working[ when ] + state->backward[ when - i ] ;
372 out[i] = 0 ;
373 }
374 else
375 when = i ;
376
377 for( i=0 ; i<cells ; i++ )
378 if( state->scale != 0 )
379 out[i] = out[i] * state->scale / state->falls[i] ;
380 else
381 out[i] = state->working[i] ;
382
383 return ;
384 }
385
386 void closeCorti2( state )
387 struct _corti2_state *state ;
388 {
389 stitch_free( ( char * ) state->working ) ;
390 stitch_free( ( char * ) state->falls ) ;
391
392 Delete( state ) ;
393
394 return ;
395 }
396
397 #if 0
398
399 /* obsolete code stored here for now.. stitch entry points */
400
401
402 struct _stx_state { Source source ; unsigned cells ; char *corti ; int (*model)() ; } ;
403
404 static void stx_callback( state, bytes, buffer )
405 struct _stx_state *state ;
406 ByteCount bytes ;
407 DataType *buffer ;
408 {
409 int points = ToPoints( DataType, bytes ) ;
410 DataType *input = PullItems( state->source, points, DataType ) ;
411 int pointer ;
412
413 for( pointer=0 ; pointer < points ; pointer += state->cells )
414 (void) state->model( state->corti, state->cells, input+pointer, buffer+pointer ) ;
415
416 return ;
417 }
418
419 Source Stx( source, chans, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, t_rise, t_lat, t_rapid, absthresh, times, scale )
420 Source source ;
421 int chans ;
422 double samplerate, *center_frequencies, (*bandwidth_function)(), bandwidth_scalar, t_rise, t_lat, t_rapid, absthresh ;
423 int times, scale ;
424 {
425 DeclareNew( struct _stx_state *, state ) ;
426
427 state->source = source ;
428 state->cells = chans ;
429
430 state->corti = newCorti( chans, samplerate, center_frequencies, bandwidth_function, t_rise, t_lat, t_rapid, absthresh, times, scale ) ;
431 state->model = OldCorti ;
432
433 return ( stdAutoSource( ( Pointer ) state, stx_callback ) ) ;
434 }
435
436 Source Stx2( source, chans, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, rapid_rises, scale )
437 Source source ;
438 int chans ;
439 double samplerate, *center_frequencies, (*bandwidth_function)(), bandwidth_scalar, rapid_rises, scale ;
440 {
441 DeclareNew( struct _stx_state *, state ) ;
442 short *forward = ( short * ) 0, *backward = ( short * ) 0 ;
443
444 state->source = source ;
445 state->cells = chans ;
446
447 state->corti = newCorti2( chans, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, rapid_rises, scale, forward, backward ) ;
448 state->model = Corti2 ;
449
450 return ( stdAutoSource( ( Pointer ) state, stx_callback ) ) ;
451 }
452
453 #endif