annotate wdf/bank_tl.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. 1994
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 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
tomwalters@0 17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
tomwalters@0 18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
tomwalters@0 19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
tomwalters@0 20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
tomwalters@0 21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
tomwalters@0 22 */
tomwalters@0 23
tomwalters@0 24 /*
tomwalters@0 25 Acknowledgment:
tomwalters@0 26 ==============
tomwalters@0 27
tomwalters@0 28 The source code provided in this file was originally developed by
tomwalters@0 29 Christian Giguere as part of a Ph.D degree at the Department of
tomwalters@0 30 Engineering of the University of Cambridge from April 1990 to
tomwalters@0 31 November 1993. The code was subsequently adapted under a grant
tomwalters@0 32 from the Hearing Research Trust for full compatibility with
tomwalters@0 33 AIM Release 6.15.
tomwalters@0 34
tomwalters@0 35 Christian Giguere 25/03/94
tomwalters@0 36
tomwalters@0 37 */
tomwalters@0 38
tomwalters@0 39 /*
tomwalters@0 40 ===========================================================
tomwalters@0 41 bank_tl.c
tomwalters@0 42 ===========================================================
tomwalters@0 43
tomwalters@0 44 Design of cochlear transmission line filterbank (TLF) with
tomwalters@0 45 coupled outer ear and middle ear (EAR) filter.
tomwalters@0 46
tomwalters@0 47 Author : Christian Giguere
tomwalters@0 48 First written : 01st April, 1991
tomwalters@0 49 Last edited : 07th March, 1994
tomwalters@0 50
tomwalters@0 51 Reference:
tomwalters@0 52 (1) C.Giguere and P.C.Woodland (1994). JASA 95(1): 331-342.
tomwalters@0 53 ===========================================================
tomwalters@0 54 */
tomwalters@0 55
tomwalters@0 56 /***** includes *****/
tomwalters@0 57
tomwalters@0 58 #include <math.h>
tomwalters@0 59 #include <stdio.h>
tomwalters@0 60 #include "stitch.h"
tomwalters@0 61 #include "source.h"
tomwalters@0 62 #include "calc.h"
tomwalters@0 63 #include "calc_tl.h"
tomwalters@0 64 #include "wdf_tl.h"
tomwalters@0 65 #include "formulae.h"
tomwalters@0 66 #include "formulae_tl.h"
tomwalters@0 67 #include "scales.h"
tomwalters@0 68 #include "scales_tl.h"
tomwalters@0 69 #include "bank.h"
tomwalters@0 70 #include "bank_tl.h"
tomwalters@0 71 #include "ear.h"
tomwalters@0 72 #include "wdf_ear.h"
tomwalters@0 73
tomwalters@0 74 /***** defines *****/
tomwalters@0 75
tomwalters@0 76 #if 0
tomwalters@0 77 #define _DEBUG_
tomwalters@0 78 #endif
tomwalters@0 79
tomwalters@0 80 #define MIN_CF ( 16.0 ) /* Minimum BM segment CF allowed (Hz) */
tomwalters@0 81 #define MAX_CF ( 15000.0 ) /* Maximum BM segment CF allowed (Hz) */
tomwalters@0 82 #define REF_CF ( 1000.0 ) /* Reference CF (Hz) for scaling BM output and Q factor */
tomwalters@0 83 #define L ( 3.5 ) /* Length of BM (cm) */
tomwalters@0 84 #define MinLength ( 1.0E-6 ) /* Mininum length of each BM segment (cm) */
tomwalters@0 85 #define B0 ( 0.015 ) /* BM width at basal end (cm) */
tomwalters@0 86 #define B_exp ( 0.30 ) /* Exponential constant for BM width (1/cm) */
tomwalters@0 87 #define A0 ( 0.03 ) /* Cross-sectional area of each scala at basal end (cm2) */
tomwalters@0 88 #define A_exp ( -0.60 ) /* Exponential constant for scalea cross-sectional area (1/cm) */
tomwalters@0 89 #define RHO_fluid ( 1.0 ) /* Density of cochlear fluids [g/cm3] */
tomwalters@0 90 #define MASS_PER_AREA ( 0.015 ) /* Transerval mass per area of basilar membrane (g/cm2) */
tomwalters@0 91 #define Q_CHANNEL ( 0 ) /* Introduce channel-dependent Q factor */
tomwalters@0 92 #define RATIO ( 30.0 ) /* Transformer ratio between oval window and eardrum */
tomwalters@0 93 #define WARPING ( 0 ) /* Compensate frequency warping of bilinear transform */
tomwalters@0 94
tomwalters@0 95
tomwalters@0 96 /***** externals */
tomwalters@0 97
tomwalters@0 98 extern Source InterpSource() ;
tomwalters@0 99
tomwalters@0 100 /***** functions *****/
tomwalters@0 101
tomwalters@0 102 /**************************************************************************
tomwalters@0 103 * name: function:
tomwalters@0 104 *
tomwalters@0 105 * tlf_bank_callback() Callable procedure returning pointer to filtered
tomwalters@0 106 * data (BM velocity or displacement).
tomwalters@0 107 *
tomwalters@0 108 * TLF_GenBank() Set-up and initialization function for the design
tomwalters@0 109 * of the cochlear filterbank. Returns pointer to
tomwalters@0 110 * a new source.
tomwalters@0 111 ***************************************************************************/
tomwalters@0 112
tomwalters@0 113 typedef struct _bank_segment BankSegment ;
tomwalters@0 114
tomwalters@0 115 struct _bank_segment {
tomwalters@0 116 double center_frequency ;
tomwalters@0 117 double seglength, position ;
tomwalters@0 118 int active ;
tomwalters@0 119 } ;
tomwalters@0 120
tomwalters@0 121 struct _tlf_bank_state {
tomwalters@0 122 struct _fillable_source parent ;
tomwalters@0 123 Source source ;
tomwalters@0 124 Pointer input ;
tomwalters@0 125 int inout_size ;
tomwalters@0 126 void (*proc)(), (*closeEar)(), (*closeTLF)() ;
tomwalters@0 127 int total_chans, display_chans ;
tomwalters@0 128 TLF_BankInfo *bank ;
tomwalters@0 129 WDFilterState **states ;
tomwalters@0 130 int Ntube ;
tomwalters@0 131 WaveWDFstate *wave_states ;
tomwalters@0 132 EartubeWDFstate **eartube_states ;
tomwalters@0 133 EarmiddleWDFstate *earmiddle_states ;
tomwalters@0 134 } ;
tomwalters@0 135
tomwalters@0 136
tomwalters@0 137 /************************* tlf_bank_callback() ****************************/
tomwalters@0 138
tomwalters@0 139 static Pointer tlf_bank_callback( state, bytes, buffer )
tomwalters@0 140 struct _tlf_bank_state *state ;
tomwalters@0 141 ByteCount *bytes ;
tomwalters@0 142 Pointer buffer ;
tomwalters@0 143 {
tomwalters@0 144 register TLF_BankInfo *bankInfo = state->bank ;
tomwalters@0 145 register int last = *bytes == 0 ;
tomwalters@0 146 register int points ;
tomwalters@0 147 register ByteCount bytecount ;
tomwalters@0 148
tomwalters@0 149 /***** process *****/
tomwalters@0 150 if( !last ) {
tomwalters@0 151
tomwalters@0 152 points = *bytes * bankInfo->decimate_factor /
tomwalters@0 153 ( state->display_chans * state->inout_size ) ;
tomwalters@0 154
tomwalters@0 155 state->input = Pull( state->source, points * state->inout_size ) ;
tomwalters@0 156
tomwalters@0 157 state->proc( bankInfo, state->states, state->input, buffer, points,
tomwalters@0 158 state->total_chans, state->wave_states, state->eartube_states,
tomwalters@0 159 state->earmiddle_states, state->Ntube ) ;
tomwalters@0 160
tomwalters@0 161 return ( buffer ) ;
tomwalters@0 162 }
tomwalters@0 163
tomwalters@0 164 /***** close *****/
tomwalters@0 165 else {
tomwalters@0 166
tomwalters@0 167 Pull( state->source, 0 ) ;
tomwalters@0 168 state->closeEar( state->wave_states, state->eartube_states, state->earmiddle_states, state->Ntube ) ;
tomwalters@0 169 state->closeTLF( state->states, state->total_chans, state->bank ) ;
tomwalters@0 170
tomwalters@0 171 return ( DeleteFillableSource( state ) ) ;
tomwalters@0 172 }
tomwalters@0 173 }
tomwalters@0 174
tomwalters@0 175
tomwalters@0 176 /************************** TLF_GenBank() *****************************/
tomwalters@0 177
tomwalters@0 178 Source TLF_GenBank( source, interps, info, chans, decimate_factor, samplerate, center_frequencies,
tomwalters@0 179 output_gain, outdens, qbase, OHC_gain, OHC_sat, motionstr, concha, canal )
tomwalters@0 180 Source source ;
tomwalters@0 181 int interps, info, *chans, *decimate_factor ;
tomwalters@0 182 double samplerate, *center_frequencies, output_gain, outdens ;
tomwalters@0 183 double qbase, OHC_gain, OHC_sat ;
tomwalters@0 184 char *motionstr ;
tomwalters@0 185 TubeInfo *concha, *canal ;
tomwalters@0 186 {
tomwalters@0 187 DeclareNew( struct _tlf_bank_state *, state ) ;
tomwalters@0 188 BankSegment **bankSeg, *segmentPointer, **GenerateBankSegments() ;
tomwalters@0 189 double density, freq, scale_disp, scale_vel ;
tomwalters@0 190 double qfactor, bn, xn, delta_xn, an, Lt, zov ;
tomwalters@0 191 double length, diam, attn ;
tomwalters@0 192 Source outputSource ;
tomwalters@0 193 int chan, total_chans, segment, counter = 0 ;
tomwalters@0 194
tomwalters@0 195 /***** initialise input-related parameters *****/
tomwalters@0 196 state->inout_size = sizeof ( DataType ) ;
tomwalters@0 197 state->input = ( char * ) 0 ;
tomwalters@0 198 state->source = source ;
tomwalters@0 199
tomwalters@0 200 /***** set WDF-TLF filterbank parameters *****/
tomwalters@0 201 density = DensityOnScale( ErbScale( center_frequencies[ 0 ]), ErbScale( center_frequencies[ *chans - 1]),
tomwalters@0 202 *chans ) ;
tomwalters@0 203 if( density == 0. ) {
tomwalters@0 204 if( outdens <= 0. )
tomwalters@0 205 density = 1. ; /* arbitrary */
tomwalters@0 206 else
tomwalters@0 207 density = outdens ;
tomwalters@0 208 }
tomwalters@0 209
tomwalters@0 210 if( interps > 0 )
tomwalters@0 211 interps = MIN( interps, ( int ) floor( log( ( double ) *chans ) / log( 2. ) ) ) ;
tomwalters@0 212
tomwalters@0 213 bankSeg = GenerateBankSegments( interps, samplerate, center_frequencies, &density, &outdens,
tomwalters@0 214 chans, &total_chans ) ;
tomwalters@0 215 state->display_chans = *chans ;
tomwalters@0 216 state->total_chans = total_chans ;
tomwalters@0 217 state->states = NewArray( WDFilterState *, state->total_chans, "bank_tl.c for states" ) ;
tomwalters@0 218
tomwalters@0 219 if( info )
tomwalters@0 220 fprintf( stderr, "\nTLF filterbank information:\n" ) ;
tomwalters@0 221
tomwalters@0 222 xn = bankSeg[0]->position ;
tomwalters@0 223 delta_xn = bankSeg[0]->seglength ;
tomwalters@0 224 Lt = -2. * RHO_fluid / ( A0 * A_exp ) * ( exp( -A_exp * L ) - exp( -A_exp * ( xn + delta_xn ) ) ) ;
tomwalters@0 225
tomwalters@0 226 for( chan = 0 ; chan < state->total_chans ; chan++ ) {
tomwalters@0 227 segmentPointer = bankSeg[ chan ] ;
tomwalters@0 228 freq = segmentPointer->center_frequency ;
tomwalters@0 229 xn = segmentPointer->position ;
tomwalters@0 230 delta_xn = MAX( segmentPointer->seglength, MinLength ) ;
tomwalters@0 231
tomwalters@0 232 /*** channel-dependent scalea cross-sectional area ***/
tomwalters@0 233 an = A0 * exp( A_exp * xn ) ;
tomwalters@0 234
tomwalters@0 235 /*** channel-dependent BM width ***/
tomwalters@0 236 bn = B0 * exp( B_exp * xn ) ;
tomwalters@0 237
tomwalters@0 238 /*** channel-dependent Q-factor ***/
tomwalters@0 239 if ( Q_CHANNEL != 0 )
tomwalters@0 240 qfactor = qbase * ( freq / REF_CF ) * ( Erb( REF_CF ) / Erb(freq) ) ;
tomwalters@0 241 else
tomwalters@0 242 qfactor = qbase ;
tomwalters@0 243
tomwalters@0 244 /*** print filterbank configuration ***/
tomwalters@0 245 if( info ) {
tomwalters@0 246 counter += 1 * segmentPointer->active ;
tomwalters@0 247 fprintf( stderr, "%3d -- active=%3d -- cf:%7.1f Hz =%6.2f ERBs -- x=%.3fcm delta=%.3fcm b=%.3fcm A=%.3fcm2\n",
tomwalters@0 248 state->total_chans - chan, counter * segmentPointer->active, freq, ErbScale( freq ), xn, delta_xn, bn, an ) ;
tomwalters@0 249 }
tomwalters@0 250
tomwalters@0 251 /*** scale output ***/
tomwalters@0 252 scale_vel = output_gain * FILTERBANK_SCALE ;
tomwalters@0 253 scale_disp = TwoPi * REF_CF * scale_vel ;
tomwalters@0 254
tomwalters@0 255 /*** get filter states ***/
tomwalters@0 256 state->states[ chan ] = WDFilter( samplerate, freq, scale_vel, scale_disp, RHO_fluid, an, bn,
tomwalters@0 257 qfactor, MASS_PER_AREA, delta_xn, Lt, WARPING,
tomwalters@0 258 segmentPointer->active, &zov, OHC_gain, OHC_sat ) ;
tomwalters@0 259
tomwalters@0 260 Delete( segmentPointer ) ;
tomwalters@0 261 }
tomwalters@0 262
tomwalters@0 263 Delete( bankSeg ) ;
tomwalters@0 264
tomwalters@0 265
tomwalters@0 266 /*** set parameters common to all channels ***/
tomwalters@0 267
tomwalters@0 268 state->bank = New( TLF_BankInfo * ) ;
tomwalters@0 269 state->bank->output_chans = state->display_chans ;
tomwalters@0 270
tomwalters@0 271 /* set decimation parameters */
tomwalters@0 272 state->bank->decimateCount = 0 ;
tomwalters@0 273 *decimate_factor = MAX( 1, *decimate_factor ) ;
tomwalters@0 274 state->bank->decimate_factor = *decimate_factor ;
tomwalters@0 275
tomwalters@0 276
tomwalters@0 277 /***** set output and nonlinearity variables, and filter procedure *****/
tomwalters@0 278
tomwalters@0 279 if( strncmp( motionstr, "velocity", 3 ) == 0 ) {
tomwalters@0 280 state->proc = DoWDFdataArray ;
tomwalters@0 281 state->bank->output_var = VELOCITY ;
tomwalters@0 282 state->bank->nl_var = DISPLACEMENT ;
tomwalters@0 283 }
tomwalters@0 284 else {
tomwalters@0 285 state->proc = DoWDFdataArray ;
tomwalters@0 286 state->bank->output_var = DISPLACEMENT ;
tomwalters@0 287 state->bank->nl_var = DISPLACEMENT ;
tomwalters@0 288 }
tomwalters@0 289
tomwalters@0 290
tomwalters@0 291 /***** Set WDF-EAR filter design parameters *****/
tomwalters@0 292 state->wave_states = FreefieldWDF( samplerate, RHO_air, C, As, concha->diameter/2. ) ;
tomwalters@0 293
tomwalters@0 294 state->Ntube = concha->Nsegments + canal->Nsegments ;
tomwalters@0 295 state->eartube_states = NewArray( EartubeWDFstate *, state->Ntube, "ear.c for eartube states" ) ;
tomwalters@0 296
tomwalters@0 297 length = concha->length / concha->Nsegments ;
tomwalters@0 298 diam = concha->diameter ;
tomwalters@0 299 attn = concha->att_factor ;
tomwalters@0 300 for( segment = 0 ; segment < concha->Nsegments ; segment++ )
tomwalters@0 301 state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ;
tomwalters@0 302
tomwalters@0 303 length = canal->length / canal->Nsegments ;
tomwalters@0 304 diam = canal->diameter ;
tomwalters@0 305 attn = canal->att_factor ;
tomwalters@0 306 for( ; segment < state->Ntube ; segment++ )
tomwalters@0 307 state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ;
tomwalters@0 308
tomwalters@0 309 state->earmiddle_states = EarmiddleWDF( samplerate, zov, 1.0, RATIO ) ;
tomwalters@0 310
tomwalters@0 311
tomwalters@0 312 /***** specify procedures upon closing *****/
tomwalters@0 313 state->closeEar = CloseEarWDF ;
tomwalters@0 314 state->closeTLF = CloseWDF ;
tomwalters@0 315
tomwalters@0 316 /***** initialise output-related parameters and return *****/
tomwalters@0 317 outputSource = SetFillableSource( state, tlf_bank_callback, "bank_tl.c filter" ) ;
tomwalters@0 318
tomwalters@0 319 for( *chans = state->display_chans ; interps-- > 0 ; *chans = *chans * 2 - 1, density = density * 2. )
tomwalters@0 320 outputSource = InterpSource( outputSource, *chans ) ;
tomwalters@0 321
tomwalters@0 322 return ( outputSource ) ;
tomwalters@0 323 }
tomwalters@0 324
tomwalters@0 325
tomwalters@0 326 /************************** lower level functions *************************/
tomwalters@0 327
tomwalters@0 328 BankSegment **GenerateBankSegments( interps, samplerate, display_frequencies, display_dens,
tomwalters@0 329 out_dens, display_chans, total_chans )
tomwalters@0 330 int interps ;
tomwalters@0 331 double samplerate ;
tomwalters@0 332 double *display_frequencies ;
tomwalters@0 333 double *display_dens, *out_dens ;
tomwalters@0 334 int *display_chans, *total_chans ;
tomwalters@0 335 {
tomwalters@0 336 BankSegment **bankSeg, *segmentPointer ;
tomwalters@0 337 double min_cf, max_cf ;
tomwalters@0 338 double apical_cf, basal_cf ;
tomwalters@0 339 double *apical_frequencies, *basal_frequencies ;
tomwalters@0 340 double apical_dens, basal_dens, central_dens ;
tomwalters@0 341 int apical_chans, basal_chans, central_chans ;
tomwalters@0 342 int ichan, chan ;
tomwalters@0 343 int remainder ;
tomwalters@0 344 double cm_per_CB = GetERBscaling ( ) / 10. ;
tomwalters@0 345
tomwalters@0 346
tomwalters@0 347 /***** set number and density of central channels *****/
tomwalters@0 348 if( interps >= 0 ) {
tomwalters@0 349
tomwalters@0 350 central_chans = *display_chans = *display_chans >> interps ;
tomwalters@0 351 central_dens = *display_dens = ldexp( *display_dens, -interps ) ;
tomwalters@0 352 min_cf = FofErbScale( ErbScale( display_frequencies[0] ) - 1. / central_dens ) ;
tomwalters@0 353 max_cf = display_frequencies[ ( central_chans - 1 ) << interps ] ;
tomwalters@0 354 }
tomwalters@0 355
tomwalters@0 356 else {
tomwalters@0 357 central_chans = *display_chans << -interps ;
tomwalters@0 358 central_dens = ldexp( *display_dens, -interps ) ;
tomwalters@0 359 min_cf = FofErbScale( ErbScale( display_frequencies[0] )
tomwalters@0 360 - ( 1 << -interps ) / central_dens ) ;
tomwalters@0 361 max_cf = display_frequencies[*display_chans - 1] ;
tomwalters@0 362 }
tomwalters@0 363
tomwalters@0 364
tomwalters@0 365 /***** set number and density of apical and basal channels outside display range *****/
tomwalters@0 366
tomwalters@0 367 if( *out_dens <= 0. ) {
tomwalters@0 368
tomwalters@0 369 apical_cf = min_cf ;
tomwalters@0 370 apical_dens = 0. ;
tomwalters@0 371 basal_cf = max_cf ;
tomwalters@0 372 basal_dens = 0. ;
tomwalters@0 373 }
tomwalters@0 374 else {
tomwalters@0 375 apical_cf = adjustCF( MIN_CF, samplerate ) ;
tomwalters@0 376 apical_dens = *out_dens ;
tomwalters@0 377 basal_cf = adjustCF( MAX_CF, samplerate ) ;
tomwalters@0 378 basal_dens = *out_dens ;
tomwalters@0 379 }
tomwalters@0 380
tomwalters@0 381 apical_chans = 0 ;
tomwalters@0 382 basal_chans = 0 ;
tomwalters@0 383
tomwalters@0 384
tomwalters@0 385 /***** generate apical and basal center frequencies outside display range *****/
tomwalters@0 386
tomwalters@0 387 apical_frequencies = GenerateFrequencies( apical_cf, min_cf, min_cf, &apical_dens, &apical_chans ) ;
tomwalters@0 388 basal_frequencies = GenerateFrequencies( max_cf, basal_cf, max_cf, &basal_dens, &basal_chans ) ;
tomwalters@0 389
tomwalters@0 390 /***** fill in array of BanKSegment structures with BM segment info *****/
tomwalters@0 391 *total_chans = apical_chans + central_chans + basal_chans - 2 ;
tomwalters@0 392 bankSeg = NewArray( BankSegment *, *total_chans + 1, "tl_bank.c for segments" ) ;
tomwalters@0 393
tomwalters@0 394 ichan = 0 ;
tomwalters@0 395 for( chan = 1 ; chan < apical_chans ; chan++ ) {
tomwalters@0 396
tomwalters@0 397 bankSeg[ ichan++ ] = segmentPointer = New( BankSegment * ) ;
tomwalters@0 398 segmentPointer->center_frequency = apical_frequencies[ chan ] ;
tomwalters@0 399 segmentPointer->seglength = cm_per_CB / apical_dens ;
tomwalters@0 400 segmentPointer->position = L - cm_per_CB * ErbScale( segmentPointer->center_frequency ) ;
tomwalters@0 401 segmentPointer->active = 0 ;
tomwalters@0 402 }
tomwalters@0 403
tomwalters@0 404 for( chan = 0 ; chan < central_chans ; chan++ ) {
tomwalters@0 405
tomwalters@0 406 bankSeg[ ichan++ ] = segmentPointer = New( BankSegment * ) ;
tomwalters@0 407
tomwalters@0 408 if( interps >= 0 ) {
tomwalters@0 409 segmentPointer->center_frequency = display_frequencies[ chan << interps ] ;
tomwalters@0 410 segmentPointer->active = 1 ;
tomwalters@0 411 }
tomwalters@0 412 else {
tomwalters@0 413 remainder = chan % ( 1 << -interps ) ;
tomwalters@0 414 segmentPointer->center_frequency = FofErbScale( ErbScale( display_frequencies[ chan >> -interps ] )
tomwalters@0 415 + ( remainder - ( 1 << -interps ) + 1 ) / central_dens ) ;
tomwalters@0 416 segmentPointer->active = ( remainder == ( ( 1 << -interps ) - 1 ) ) ;
tomwalters@0 417 }
tomwalters@0 418
tomwalters@0 419 segmentPointer->seglength = cm_per_CB / central_dens ;
tomwalters@0 420 segmentPointer->position = L - cm_per_CB * ErbScale( segmentPointer->center_frequency ) ;
tomwalters@0 421 }
tomwalters@0 422
tomwalters@0 423
tomwalters@0 424 for( chan = 1 ; chan < basal_chans ; chan++ ) {
tomwalters@0 425
tomwalters@0 426 bankSeg[ ichan++ ] = segmentPointer = New( BankSegment * ) ;
tomwalters@0 427 segmentPointer->center_frequency = basal_frequencies[ chan ] ;
tomwalters@0 428 segmentPointer->seglength = cm_per_CB / basal_dens ;
tomwalters@0 429 segmentPointer->position = L - cm_per_CB * ErbScale( segmentPointer->center_frequency ) ;
tomwalters@0 430 segmentPointer->active = 0 ;
tomwalters@0 431 }
tomwalters@0 432
tomwalters@0 433 segmentPointer = bankSeg[ 0 ] ;
tomwalters@0 434 if( ( segmentPointer->position + segmentPointer->seglength ) > L )
tomwalters@0 435 segmentPointer->seglength = L - MIN( L, segmentPointer->position ) ;
tomwalters@0 436
tomwalters@0 437 /***** return and deallocate dynamic memory *****/
tomwalters@0 438 Delete( apical_frequencies ) ;
tomwalters@0 439 Delete( basal_frequencies ) ;
tomwalters@0 440
tomwalters@0 441 return( bankSeg ) ;
tomwalters@0 442 }
tomwalters@0 443
tomwalters@0 444
tomwalters@0 445 double *GenerateFrequencies( min_cf, max_cf, base_cf, density, channels )
tomwalters@0 446 double min_cf, max_cf, base_cf ;
tomwalters@0 447 double *density ;
tomwalters@0 448 int *channels ;
tomwalters@0 449 {
tomwalters@0 450 double freq, *frequencies ;
tomwalters@0 451
tomwalters@0 452 /*** map characteristic frequencies onto specified scale ***/
tomwalters@0 453 min_cf = ErbScale( min_cf ) ;
tomwalters@0 454 max_cf = ErbScale( max_cf ) ;
tomwalters@0 455 max_cf = MAX( min_cf, max_cf ) ; /* max_cf cannot be smaller than min_cf */
tomwalters@0 456 base_cf = ErbScale( base_cf ) ;
tomwalters@0 457
tomwalters@0 458
tomwalters@0 459 /*** call appropriate generating functions ***/
tomwalters@0 460 if( *channels <= 0 ) {
tomwalters@0 461
tomwalters@0 462 if( *density <= 0. ) {
tomwalters@0 463 *channels = 1 ; /* there must be at least one channel */
tomwalters@0 464 freq = FofErbScale( min_cf ) ; /* arbitrary */
tomwalters@0 465 frequencies = &freq ;
tomwalters@0 466 *density = 1. ; /* arbitrary */
tomwalters@0 467
tomwalters@0 468 }
tomwalters@0 469 else {
tomwalters@0 470 frequencies = GenerateScale( min_cf, max_cf, *density, base_cf, FofErbScale ) ;
tomwalters@0 471 *channels = NumberOnScale( min_cf, max_cf, *density, base_cf ) ;
tomwalters@0 472 }
tomwalters@0 473 }
tomwalters@0 474
tomwalters@0 475 else {
tomwalters@0 476 frequencies = NumberedScale( min_cf, max_cf, *channels, FofErbScale ) ;
tomwalters@0 477 *density = DensityOnScale( min_cf, max_cf, *channels ) ;
tomwalters@0 478 if( *density == 0. )
tomwalters@0 479 *density = 1. ; /* arbitrary */
tomwalters@0 480 }
tomwalters@0 481
tomwalters@0 482 /*** return pointer to array of center frequencies ***/
tomwalters@0 483 return ( frequencies ) ;
tomwalters@0 484 }
tomwalters@0 485
tomwalters@0 486
tomwalters@0 487 double adjustCF( cf, samplerate )
tomwalters@0 488 double cf, samplerate ;
tomwalters@0 489 {
tomwalters@0 490 cf = MAX( cf, MIN_CF ) ;
tomwalters@0 491 cf = MAX( cf, FofErbScale( 0. ) ) ;
tomwalters@0 492
tomwalters@0 493 cf = MIN( cf, samplerate / 2. ) ;
tomwalters@0 494 cf = MIN( cf, MAX_CF ) ;
tomwalters@0 495 cf = MIN( cf, FofErbScale( 10. * L / GetERBscaling() ) );
tomwalters@0 496
tomwalters@0 497 return ( cf ) ;
tomwalters@0 498 }
tomwalters@0 499