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