Mercurial > hg > aim92
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/model/bank.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,268 @@ +/* + Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 + =========================================================================== + + Permission to use, copy, modify, and distribute this software without fee + is hereby granted for research purposes, provided that this copyright + notice appears in all copies and in all supporting documentation, and that + the software is not redistributed for any fee (except for a nominal shipping + charge). Anyone wanting to incorporate all or part of this software in a + commercial product must obtain a license from the Medical Research Council. + + The MRC makes no representations about the suitability of this + software for any purpose. It is provided "as is" without express or implied + warranty. + +*/ + +/* + bank.c + ====== + + long awaited proper generic multiplexed filter bank with phase compensation! + + + Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit. + + + Author : John Holdsworth + Written : 10th March, 1989. + + Edited : + Christian Giguere, March 1994 + - Provided facilities to print filterbank information to stderr + - To locate changes, search for "CG" + +*/ + +#include <math.h> +#include <stdio.h> /* CG */ + +#include "stitch.h" +#include "source.h" +#include "recurse.h" +#include "formulae.h" + +#include "bank.h" + +#ifndef lint +static char *sccs_id = "@(#)bank.c 1.16 John Holdsworth (MRC-APU) 6/6/91" ; +#endif + + +/* interpolation */ + +struct _interp_state { struct _fillable_source parent ; Source source ; unsigned ichans ; int (*interp)() ; } ; + +static Pointer interp_callback( state, bytes, buffer ) +struct _interp_state *state ; +ByteCount *bytes ; +short *buffer ; +{ + register int last = *bytes == 0 ; + register int ipointer, points = ToPoints( short, *bytes ) ; + register int ipoints = points / (state->ichans*2-1) * state->ichans ; + short *input = PullShorts( state->source, ipoints ) ; + + if( !last ) { + for( ipointer=0 ; ipointer < ipoints ; ipointer += state->ichans ) + state->interp( input+ipointer, buffer+ipointer/state->ichans*(state->ichans*2-1), state->ichans, state->ichans*2-1 ) ; + + return ( (Pointer) buffer ) ; + } + else + return ( DeleteFillableSource( state ) ) ; +} + +Source InterpSource( source, ichans ) +Source source ; +int ichans ; +{ + DeclareNew( struct _interp_state *, state ) ; + extern int interp() ; + + state->source = source ; + state->ichans = ichans ; + state->interp = interp ; + + return ( SetFillableSource( state, interp_callback, "bank.c interpolating" ) ) ; +} + +Source LinterpSource( source, ichans ) +Source source ; +int ichans ; +{ + DeclareNew( struct _interp_state *, state ) ; + extern int linterp() ; + + state->source = source ; + state->ichans = ichans ; + state->interp = linterp ; + + return ( SetFillableSource( state, interp_callback, "bank.c linterpolating" ) ) ; +} + +static int segsize = 50 ; + +#ifdef DSP32 +#define BUFFSIZE 256 +#else +#define BUFFSIZE 2048 +#endif + +/* multiplexed filter bank */ + +struct _bank_state { + struct _fillable_source parent ; + Source source ; char *input ; unsigned chans ; + int active, pointer, iptr, *delays, (*proc)(), input_size, output_size ; + RecursiveFilterState **states ; + } ; + +static Pointer bank_callback( state, bytes, buffer ) +struct _bank_state *state ; +ByteCount *bytes ; +char *buffer ; +{ +extern char *bstart, *bend ; + register int last = *bytes == 0 ; + static int segment = BUFFSIZE ; + int points, bytecount ; + + if( state->input == ( char * ) 0 ) { + + if( state->delays[0] < 0 ) + state->pointer = state->delays[0] ; + else + state->pointer = 0 ; + + if( segment < state->delays[state->chans-1] - state->delays[0] ) + segment = state->delays[state->chans-1] - state->delays[0] << 1 ; + + state->input = Pull( state->source, segment * state->input_size ) ; + state->iptr = state->pointer ; + state->active = 0 ; + + bstart = state->input - segment * state->input_size ; + bend = state->input + segment * state->input_size ; + } + + if( !last ) { + for( bytecount=0 ; bytecount<*bytes ; ) { + + if( state->iptr + segsize - state->delays[0] >= segment ) { + state->input = Pull( state->source, segment * state->input_size ) ; + state->iptr -= segment ; + + bstart = state->input - segment * state->input_size ; + bend = state->input + segment * state->input_size ; + + } + + while( state->active < state->chans && state->delays[ state->active ] <= state->pointer ) + state->active++ ; + + if( state->pointer < 0 || state->active < state->chans || state->output_size == 0 ) { + + points = 1 ; + + state->output_size = state->proc( state->states, state->delays, state->input + state->iptr * state->input_size, buffer+bytecount, points, state->active ) ; + + stitch_bzero( buffer+bytecount+state->active*state->output_size, (int) ( ( state->chans - state->active ) * state->output_size ) ) ; + } + else { + points = ( *bytes - bytecount ) / state->chans / state->output_size ; + + if( points > segsize ) + points = segsize ; + + state->output_size = state->proc( state->states, state->delays, state->input + state->iptr * state->input_size, buffer+bytecount, points, state->active ) ; + } + + state->iptr += points ; + + if( ++state->pointer > 0 ) + bytecount += points*state->chans*state->output_size ; + } + + return ( buffer ) ; + } + else { + Pull( state->source, 0 ) ; + + for( last=0 ; last<state->chans ; last++ ) + Delete( state->states[last] ) ; + + Delete( state->states ) ; + Delete( state->delays ) ; + + return ( DeleteFillableSource( state ) ) ; + } + +} + + +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 ) +Source source ; +int interps, *chans ; +double samplerate, *center_frequencies, (*bandwidth_function)(), (*scale_function)() ; /* CG: 23-03-94 */ +double output_scale, audio_power ; /* CG: 23-03-94 */ +int order, phase_compensation, input_bits ; +long frames ; +int (*proc)(), input_size, info ; /* CG: 23-03-94 */ +{ + DeclareNew( struct _bank_state *, state ) ; + double sample_delay, max_delay, freq ; + extern Source Interp() ; + Source out ; + int chan ; + + state->chans = *chans >> interps ; + + state->states = NewArray( RecursiveFilterState *, state->chans, "bank.c for states" ) ; + state->delays = NewArray( int, state->chans, "bank.c for delays" ) ; + + state->input_size = input_size ; + + if( info ) /* CG: 23-03-94 */ + fprintf( stderr, "\nGTF filterbank information:\n" ) ; + + for( chan=0 ; chan < state->chans ; chan++ ) { + sample_delay = 0 ; + + freq = center_frequencies[ chan<<interps ] ; + + if( info ) /* CG: 23-03-94 */ + fprintf( stderr, "%3d -- cf:%7.1f Hz =%6.2f ERBs -- bwidth=%5.1f Hz\n", + chan + 1 , freq, scale_function( freq ), bandwidth_function( freq ) ) ; + + state->states[ chan ] = NewRecursiveFilter( samplerate, freq, bandwidth_function( freq ), + output_scale * pow( Audiogram( freq ), audio_power ), + order, phase_compensation, input_bits, &sample_delay ) ; + + if( chan == 0 ) + max_delay = sample_delay ; + + if( phase_compensation == FINE_ALIGNMENT || phase_compensation == ENVELOPE_ALIGNMENT ) + state->delays[ chan ] = sample_delay - max_delay ; + else + state->delays[ chan ] = sample_delay ; + } + + state->output_size = 0 ; + + state->source = NewRetainingSource( source, BUFFSIZE * state->input_size ) ; + + state->input = ( char * ) 0 ; + state->proc = proc ; + + out = SetFillableSource( state, bank_callback, "bank.c filter" ) ; + + for( chan = state->chans ; interps-- > 0 ; chan = chan*2-1 ) + out = InterpSource( out, chan ) ; + + *chans = chan ; + + return ( out ) ; +} +