annotate model/bank.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 bank.c
tomwalters@0 20 ======
tomwalters@0 21
tomwalters@0 22 long awaited proper generic multiplexed filter bank with phase compensation!
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 : 10th March, 1989.
tomwalters@0 30
tomwalters@0 31 Edited :
tomwalters@0 32 Christian Giguere, March 1994
tomwalters@0 33 - Provided facilities to print filterbank information to stderr
tomwalters@0 34 - To locate changes, search for "CG"
tomwalters@0 35
tomwalters@0 36 */
tomwalters@0 37
tomwalters@0 38 #include <math.h>
tomwalters@0 39 #include <stdio.h> /* CG */
tomwalters@0 40
tomwalters@0 41 #include "stitch.h"
tomwalters@0 42 #include "source.h"
tomwalters@0 43 #include "recurse.h"
tomwalters@0 44 #include "formulae.h"
tomwalters@0 45
tomwalters@0 46 #include "bank.h"
tomwalters@0 47
tomwalters@0 48 #ifndef lint
tomwalters@0 49 static char *sccs_id = "@(#)bank.c 1.16 John Holdsworth (MRC-APU) 6/6/91" ;
tomwalters@0 50 #endif
tomwalters@0 51
tomwalters@0 52
tomwalters@0 53 /* interpolation */
tomwalters@0 54
tomwalters@0 55 struct _interp_state { struct _fillable_source parent ; Source source ; unsigned ichans ; int (*interp)() ; } ;
tomwalters@0 56
tomwalters@0 57 static Pointer interp_callback( state, bytes, buffer )
tomwalters@0 58 struct _interp_state *state ;
tomwalters@0 59 ByteCount *bytes ;
tomwalters@0 60 short *buffer ;
tomwalters@0 61 {
tomwalters@0 62 register int last = *bytes == 0 ;
tomwalters@0 63 register int ipointer, points = ToPoints( short, *bytes ) ;
tomwalters@0 64 register int ipoints = points / (state->ichans*2-1) * state->ichans ;
tomwalters@0 65 short *input = PullShorts( state->source, ipoints ) ;
tomwalters@0 66
tomwalters@0 67 if( !last ) {
tomwalters@0 68 for( ipointer=0 ; ipointer < ipoints ; ipointer += state->ichans )
tomwalters@0 69 state->interp( input+ipointer, buffer+ipointer/state->ichans*(state->ichans*2-1), state->ichans, state->ichans*2-1 ) ;
tomwalters@0 70
tomwalters@0 71 return ( (Pointer) buffer ) ;
tomwalters@0 72 }
tomwalters@0 73 else
tomwalters@0 74 return ( DeleteFillableSource( state ) ) ;
tomwalters@0 75 }
tomwalters@0 76
tomwalters@0 77 Source InterpSource( source, ichans )
tomwalters@0 78 Source source ;
tomwalters@0 79 int ichans ;
tomwalters@0 80 {
tomwalters@0 81 DeclareNew( struct _interp_state *, state ) ;
tomwalters@0 82 extern int interp() ;
tomwalters@0 83
tomwalters@0 84 state->source = source ;
tomwalters@0 85 state->ichans = ichans ;
tomwalters@0 86 state->interp = interp ;
tomwalters@0 87
tomwalters@0 88 return ( SetFillableSource( state, interp_callback, "bank.c interpolating" ) ) ;
tomwalters@0 89 }
tomwalters@0 90
tomwalters@0 91 Source LinterpSource( source, ichans )
tomwalters@0 92 Source source ;
tomwalters@0 93 int ichans ;
tomwalters@0 94 {
tomwalters@0 95 DeclareNew( struct _interp_state *, state ) ;
tomwalters@0 96 extern int linterp() ;
tomwalters@0 97
tomwalters@0 98 state->source = source ;
tomwalters@0 99 state->ichans = ichans ;
tomwalters@0 100 state->interp = linterp ;
tomwalters@0 101
tomwalters@0 102 return ( SetFillableSource( state, interp_callback, "bank.c linterpolating" ) ) ;
tomwalters@0 103 }
tomwalters@0 104
tomwalters@0 105 static int segsize = 50 ;
tomwalters@0 106
tomwalters@0 107 #ifdef DSP32
tomwalters@0 108 #define BUFFSIZE 256
tomwalters@0 109 #else
tomwalters@0 110 #define BUFFSIZE 2048
tomwalters@0 111 #endif
tomwalters@0 112
tomwalters@0 113 /* multiplexed filter bank */
tomwalters@0 114
tomwalters@0 115 struct _bank_state {
tomwalters@0 116 struct _fillable_source parent ;
tomwalters@0 117 Source source ; char *input ; unsigned chans ;
tomwalters@0 118 int active, pointer, iptr, *delays, (*proc)(), input_size, output_size ;
tomwalters@0 119 RecursiveFilterState **states ;
tomwalters@0 120 } ;
tomwalters@0 121
tomwalters@0 122 static Pointer bank_callback( state, bytes, buffer )
tomwalters@0 123 struct _bank_state *state ;
tomwalters@0 124 ByteCount *bytes ;
tomwalters@0 125 char *buffer ;
tomwalters@0 126 {
tomwalters@0 127 extern char *bstart, *bend ;
tomwalters@0 128 register int last = *bytes == 0 ;
tomwalters@0 129 static int segment = BUFFSIZE ;
tomwalters@0 130 int points, bytecount ;
tomwalters@0 131
tomwalters@0 132 if( state->input == ( char * ) 0 ) {
tomwalters@0 133
tomwalters@0 134 if( state->delays[0] < 0 )
tomwalters@0 135 state->pointer = state->delays[0] ;
tomwalters@0 136 else
tomwalters@0 137 state->pointer = 0 ;
tomwalters@0 138
tomwalters@0 139 if( segment < state->delays[state->chans-1] - state->delays[0] )
tomwalters@0 140 segment = state->delays[state->chans-1] - state->delays[0] << 1 ;
tomwalters@0 141
tomwalters@0 142 state->input = Pull( state->source, segment * state->input_size ) ;
tomwalters@0 143 state->iptr = state->pointer ;
tomwalters@0 144 state->active = 0 ;
tomwalters@0 145
tomwalters@0 146 bstart = state->input - segment * state->input_size ;
tomwalters@0 147 bend = state->input + segment * state->input_size ;
tomwalters@0 148 }
tomwalters@0 149
tomwalters@0 150 if( !last ) {
tomwalters@0 151 for( bytecount=0 ; bytecount<*bytes ; ) {
tomwalters@0 152
tomwalters@0 153 if( state->iptr + segsize - state->delays[0] >= segment ) {
tomwalters@0 154 state->input = Pull( state->source, segment * state->input_size ) ;
tomwalters@0 155 state->iptr -= segment ;
tomwalters@0 156
tomwalters@0 157 bstart = state->input - segment * state->input_size ;
tomwalters@0 158 bend = state->input + segment * state->input_size ;
tomwalters@0 159
tomwalters@0 160 }
tomwalters@0 161
tomwalters@0 162 while( state->active < state->chans && state->delays[ state->active ] <= state->pointer )
tomwalters@0 163 state->active++ ;
tomwalters@0 164
tomwalters@0 165 if( state->pointer < 0 || state->active < state->chans || state->output_size == 0 ) {
tomwalters@0 166
tomwalters@0 167 points = 1 ;
tomwalters@0 168
tomwalters@0 169 state->output_size = state->proc( state->states, state->delays, state->input + state->iptr * state->input_size, buffer+bytecount, points, state->active ) ;
tomwalters@0 170
tomwalters@0 171 stitch_bzero( buffer+bytecount+state->active*state->output_size, (int) ( ( state->chans - state->active ) * state->output_size ) ) ;
tomwalters@0 172 }
tomwalters@0 173 else {
tomwalters@0 174 points = ( *bytes - bytecount ) / state->chans / state->output_size ;
tomwalters@0 175
tomwalters@0 176 if( points > segsize )
tomwalters@0 177 points = segsize ;
tomwalters@0 178
tomwalters@0 179 state->output_size = state->proc( state->states, state->delays, state->input + state->iptr * state->input_size, buffer+bytecount, points, state->active ) ;
tomwalters@0 180 }
tomwalters@0 181
tomwalters@0 182 state->iptr += points ;
tomwalters@0 183
tomwalters@0 184 if( ++state->pointer > 0 )
tomwalters@0 185 bytecount += points*state->chans*state->output_size ;
tomwalters@0 186 }
tomwalters@0 187
tomwalters@0 188 return ( buffer ) ;
tomwalters@0 189 }
tomwalters@0 190 else {
tomwalters@0 191 Pull( state->source, 0 ) ;
tomwalters@0 192
tomwalters@0 193 for( last=0 ; last<state->chans ; last++ )
tomwalters@0 194 Delete( state->states[last] ) ;
tomwalters@0 195
tomwalters@0 196 Delete( state->states ) ;
tomwalters@0 197 Delete( state->delays ) ;
tomwalters@0 198
tomwalters@0 199 return ( DeleteFillableSource( state ) ) ;
tomwalters@0 200 }
tomwalters@0 201
tomwalters@0 202 }
tomwalters@0 203
tomwalters@0 204
tomwalters@0 205 Source GenericFilterBank( source, interps, chans, samplerate, center_frequencies, bandwidth_function, scale_function, output_scale, audio_power, order, phase_compensation, input_bits, frames, proc, input_size, info )
tomwalters@0 206 Source source ;
tomwalters@0 207 int interps, *chans ;
tomwalters@0 208 double samplerate, *center_frequencies, (*bandwidth_function)(), (*scale_function)() ; /* CG: 23-03-94 */
tomwalters@0 209 double output_scale, audio_power ; /* CG: 23-03-94 */
tomwalters@0 210 int order, phase_compensation, input_bits ;
tomwalters@0 211 long frames ;
tomwalters@0 212 int (*proc)(), input_size, info ; /* CG: 23-03-94 */
tomwalters@0 213 {
tomwalters@0 214 DeclareNew( struct _bank_state *, state ) ;
tomwalters@0 215 double sample_delay, max_delay, freq ;
tomwalters@0 216 extern Source Interp() ;
tomwalters@0 217 Source out ;
tomwalters@0 218 int chan ;
tomwalters@0 219
tomwalters@0 220 state->chans = *chans >> interps ;
tomwalters@0 221
tomwalters@0 222 state->states = NewArray( RecursiveFilterState *, state->chans, "bank.c for states" ) ;
tomwalters@0 223 state->delays = NewArray( int, state->chans, "bank.c for delays" ) ;
tomwalters@0 224
tomwalters@0 225 state->input_size = input_size ;
tomwalters@0 226
tomwalters@0 227 if( info ) /* CG: 23-03-94 */
tomwalters@0 228 fprintf( stderr, "\nGTF filterbank information:\n" ) ;
tomwalters@0 229
tomwalters@0 230 for( chan=0 ; chan < state->chans ; chan++ ) {
tomwalters@0 231 sample_delay = 0 ;
tomwalters@0 232
tomwalters@0 233 freq = center_frequencies[ chan<<interps ] ;
tomwalters@0 234
tomwalters@0 235 if( info ) /* CG: 23-03-94 */
tomwalters@0 236 fprintf( stderr, "%3d -- cf:%7.1f Hz =%6.2f ERBs -- bwidth=%5.1f Hz\n",
tomwalters@0 237 chan + 1 , freq, scale_function( freq ), bandwidth_function( freq ) ) ;
tomwalters@0 238
tomwalters@0 239 state->states[ chan ] = NewRecursiveFilter( samplerate, freq, bandwidth_function( freq ),
tomwalters@0 240 output_scale * pow( Audiogram( freq ), audio_power ),
tomwalters@0 241 order, phase_compensation, input_bits, &sample_delay ) ;
tomwalters@0 242
tomwalters@0 243 if( chan == 0 )
tomwalters@0 244 max_delay = sample_delay ;
tomwalters@0 245
tomwalters@0 246 if( phase_compensation == FINE_ALIGNMENT || phase_compensation == ENVELOPE_ALIGNMENT )
tomwalters@0 247 state->delays[ chan ] = sample_delay - max_delay ;
tomwalters@0 248 else
tomwalters@0 249 state->delays[ chan ] = sample_delay ;
tomwalters@0 250 }
tomwalters@0 251
tomwalters@0 252 state->output_size = 0 ;
tomwalters@0 253
tomwalters@0 254 state->source = NewRetainingSource( source, BUFFSIZE * state->input_size ) ;
tomwalters@0 255
tomwalters@0 256 state->input = ( char * ) 0 ;
tomwalters@0 257 state->proc = proc ;
tomwalters@0 258
tomwalters@0 259 out = SetFillableSource( state, bank_callback, "bank.c filter" ) ;
tomwalters@0 260
tomwalters@0 261 for( chan = state->chans ; interps-- > 0 ; chan = chan*2-1 )
tomwalters@0 262 out = InterpSource( out, chan ) ;
tomwalters@0 263
tomwalters@0 264 *chans = chan ;
tomwalters@0 265
tomwalters@0 266 return ( out ) ;
tomwalters@0 267 }
tomwalters@0 268