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 ) ;
+}
+