annotate filter/recurse.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 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 ================================================
tomwalters@0 26 recurse.c - start-up code for recursive filter
tomwalters@0 27 ================================================
tomwalters@0 28
tomwalters@0 29
tomwalters@0 30 Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit.
tomwalters@0 31
tomwalters@0 32
tomwalters@0 33 Author : John Holdsworth
tomwalters@0 34 Written : 22th March, 1989.
tomwalters@0 35
tomwalters@0 36 Edited :
tomwalters@0 37
tomwalters@0 38 */
tomwalters@0 39
tomwalters@0 40
tomwalters@0 41 #include <math.h>
tomwalters@0 42
tomwalters@0 43 #ifndef _STITCH_H_
tomwalters@0 44 #include "stitch.h"
tomwalters@0 45 #endif
tomwalters@0 46
tomwalters@0 47 #ifndef _RECURSE_H_
tomwalters@0 48 #include "recurse.h"
tomwalters@0 49 #endif
tomwalters@0 50
tomwalters@0 51 #define Pi ( 3.1415926535 )
tomwalters@0 52 #define TwoPi ( 2*Pi )
tomwalters@0 53
tomwalters@0 54 #ifndef lint
tomwalters@0 55 static char *sccs_id = "@(#)recurse.c 1.8 John Holdsworth (MRC-APU) 11/8/90" ;
tomwalters@0 56 #endif
tomwalters@0 57
tomwalters@0 58 static void generateSineTable() ;
tomwalters@0 59 static double factorial() ;
tomwalters@0 60
tomwalters@0 61 #ifdef DSP32
tomwalters@0 62 int filterSineTableBits = 8 ;
tomwalters@0 63 int filterSineTableShift = 0 ;
tomwalters@0 64 #else
tomwalters@0 65 int filterSineTableBits = 12 ;
tomwalters@0 66 int filterSineTableShift = 14 ;
tomwalters@0 67 #endif
tomwalters@0 68 unsigned long filterSineTableSize, filterSineTableMask ;
tomwalters@0 69 Table filterSineTable, filterCosineTable ;
tomwalters@0 70
tomwalters@0 71 char *bstart, *bend ;
tomwalters@0 72
tomwalters@0 73
tomwalters@0 74 RecursiveFilterState *NewRecursiveFilter( samplerate, center_frequency, bandwidth, output_scale, order, phase_compensation, input_bits, sample_delay )
tomwalters@0 75 double samplerate, center_frequency, bandwidth, output_scale ;
tomwalters@0 76 int order, phase_compensation, input_bits ;
tomwalters@0 77 double *sample_delay ;
tomwalters@0 78 {
tomwalters@0 79 DeclareNew( RecursiveFilterState *, filter_state ) ;
tomwalters@0 80 double omega ;
tomwalters@0 81
tomwalters@0 82 if( filterSineTableSize != 1 << filterSineTableBits )
tomwalters@0 83 generateSineTable() ;
tomwalters@0 84
tomwalters@0 85 filter_state->order = order ;
tomwalters@0 86 filter_state->input_bits = input_bits ;
tomwalters@0 87
tomwalters@0 88 /* compensation for nominal 6dB loss in filter */
tomwalters@0 89
tomwalters@0 90 filter_state->output_scale = output_scale * 2. ;
tomwalters@0 91
tomwalters@0 92 omega = TwoPi * bandwidth / bandwidth_normalisation( filter_state->order ) ;
tomwalters@0 93
tomwalters@0 94 /* delta phi of carrier between sample ticks */
tomwalters@0 95
tomwalters@0 96 filter_state->output_delta_phi = center_frequency / samplerate * ( filterSineTableSize << 16 ) + 0.5 ;
tomwalters@0 97 filter_state->delta_phi = filter_state->output_delta_phi ;
tomwalters@0 98
tomwalters@0 99 /* initialise phases to give rounding */
tomwalters@0 100
tomwalters@0 101 ALL( filter_state->phi ) = ALL( filter_state->output_phi ) = 1l << 15 ;
tomwalters@0 102
tomwalters@0 103 /* calculate time delay required for phase compensation selected */
tomwalters@0 104 /* time advance is currently implemented as delay of */
tomwalters@0 105 /* maximum advance minus desired advance */
tomwalters@0 106
tomwalters@0 107 if( center_frequency < samplerate / 4 )
tomwalters@0 108 filter_state->over_sample = 1 ;
tomwalters@0 109 else {
tomwalters@0 110 /* if center frequency is over half the nyquist rate filtering process */
tomwalters@0 111 /* is performed at twice the sampling rate to avoid aliases */
tomwalters@0 112
tomwalters@0 113 filter_state->over_sample = 2 ;
tomwalters@0 114
tomwalters@0 115 ALL( filter_state->phi ) -= filter_state->delta_phi / 4 ;
tomwalters@0 116 #ifndef DSP32
tomwalters@0 117 ALL( filter_state->phi ) &= filterSineTableMask ;
tomwalters@0 118 #endif
tomwalters@0 119 filter_state->delta_phi /= 2 ;
tomwalters@0 120
tomwalters@0 121 /* must amplitude compensate for attenuation of high frequencies introduced by over sampling */
tomwalters@0 122
tomwalters@0 123 filter_state->output_scale /= ( filter_state->over_sample * cos( TwoPi * center_frequency / samplerate / 4 ) ) ;
tomwalters@0 124 }
tomwalters@0 125
tomwalters@0 126 filter_state->k = ( double ) 1. - exp( -omega / samplerate / filter_state->over_sample ) ;
tomwalters@0 127
tomwalters@0 128 /* fiddle delay time to take into acount half sample */
tomwalters@0 129 /* interval advance introduced by difference equation */
tomwalters@0 130
tomwalters@0 131 #if 0 /* not needed any more as alternate forward and backward differences */
tomwalters@0 132
tomwalters@0 133 *sample_delay += filter_state->order / filter_state->over_sample / 2 ;
tomwalters@0 134
tomwalters@0 135 /* compensate carrier phase for delay introduced above */
tomwalters@0 136
tomwalters@0 137 ALL( filter_state->output_phi ) += filter_state->order / filter_state->over_sample / 2 *
tomwalters@0 138 filter_state->delta_phi * filter_state->over_sample ;
tomwalters@0 139 #ifndef DSP32
tomwalters@0 140 ALL( filter_state->output_phi ) &= filterSineTableMask ;
tomwalters@0 141 #endif
tomwalters@0 142 #endif
tomwalters@0 143
tomwalters@0 144 /* munge to sin phase gammatone for mfsais */
tomwalters@0 145
tomwalters@0 146 ALL( filter_state->output_phi ) += 3 * filterSineTableMask / 4 ;
tomwalters@0 147
tomwalters@0 148 /* perform required phase compensation */
tomwalters@0 149
tomwalters@0 150 if( phase_compensation > 0 )
tomwalters@0 151 *sample_delay -= phase_compensation / center_frequency * samplerate ;
tomwalters@0 152 else if( phase_compensation < 0 )
tomwalters@0 153 *sample_delay -= ( filter_state->order - 1. ) / omega * samplerate ;
tomwalters@0 154
tomwalters@0 155 /* if phase compensation of type -2 or -4 is asked for the carrier phase */
tomwalters@0 156 /* is shifted to be aligned with the envelope maxima */
tomwalters@0 157
tomwalters@0 158 if( phase_compensation == FINE_ALIGNMENT || phase_compensation <= ACUASAL + FINE_ALIGNMENT ) {
tomwalters@0 159 ALL( filter_state->phi ) += ( filter_state->order - 1. ) / omega * center_frequency * ( filterSineTableSize << 16 ) + 0.5 ;
tomwalters@0 160 #ifndef DSP32
tomwalters@0 161 ALL( filter_state->phi ) &= filterSineTableMask ;
tomwalters@0 162 #endif
tomwalters@0 163 }
tomwalters@0 164
tomwalters@0 165 /* new recurse filter coefts */
tomwalters@0 166
tomwalters@0 167 filter_state->gain = pow( 2 * omega / samplerate, (double) order ) * output_scale ;
tomwalters@0 168 filter_state->k1 = exp( -omega / samplerate ) * cos( TwoPi * center_frequency / samplerate ) ;
tomwalters@0 169 filter_state->k2 = exp( -2 * omega / samplerate ) ;
tomwalters@0 170
tomwalters@0 171 /* flag channel not fully initialised */
tomwalters@0 172 /* leave filter specific initialisation to specific filter code */
tomwalters@0 173
tomwalters@0 174 filter_state->states = ( char * ) 0 ;
tomwalters@0 175
tomwalters@0 176 /* generate sin lookup table if necessary */
tomwalters@0 177
tomwalters@0 178 return ( filter_state ) ;
tomwalters@0 179 }
tomwalters@0 180
tomwalters@0 181 double bandwidth_normalisation( order )
tomwalters@0 182 int order ;
tomwalters@0 183 {
tomwalters@0 184 return( Pi * factorial( 2*order - 2 ) / factorial( order - 1 ) / factorial( order - 1 ) / ( 1 << ( 2 * order - 2 ) ) ) ;
tomwalters@0 185 }
tomwalters@0 186
tomwalters@0 187 static double factorial( n )
tomwalters@0 188 int n ;
tomwalters@0 189 {
tomwalters@0 190 double fact ;
tomwalters@0 191 int i ;
tomwalters@0 192
tomwalters@0 193 fact = 1. ;
tomwalters@0 194
tomwalters@0 195 for( i = n ; i > 1 ; i-- )
tomwalters@0 196 fact *= i ;
tomwalters@0 197
tomwalters@0 198 return( fact ) ;
tomwalters@0 199 }
tomwalters@0 200
tomwalters@0 201
tomwalters@0 202 static void generateSineTable()
tomwalters@0 203 {
tomwalters@0 204 static double filterTwoPi ;
tomwalters@0 205 register int i ;
tomwalters@0 206
tomwalters@0 207 if( filterSineTableSize != 1 << filterSineTableBits )
tomwalters@0 208 {
tomwalters@0 209 if( filterSineTable != ( Table ) 0 )
tomwalters@0 210 stitch_free( ( Pointer ) filterSineTable ) ;
tomwalters@0 211
tomwalters@0 212 if( filterTwoPi == 0. )
tomwalters@0 213 filterTwoPi = atan( 1. ) * 8. ;
tomwalters@0 214
tomwalters@0 215 filterSineTableSize = 1l << filterSineTableBits ;
tomwalters@0 216 filterSineTableMask = ( filterSineTableSize << 16 ) - 1 ;
tomwalters@0 217
tomwalters@0 218 /* sin table 5/4 times larger than required for cosine values */
tomwalters@0 219
tomwalters@0 220 filterSineTable = ( Table ) stitch_malloc( ( unsigned ) ( filterSineTableSize * 5 / 4 + 1 ) * sizeof( *filterSineTable ), "recurse.c for log table" ) ;
tomwalters@0 221
tomwalters@0 222 for( i=0 ; i <= filterSineTableSize/4 ; i++ ) {
tomwalters@0 223 filterSineTable[ i ] = sin( filterTwoPi * i / filterSineTableSize ) * ( 1<<filterSineTableShift ) ;
tomwalters@0 224 filterSineTable[ filterSineTableSize/2 - i ] = filterSineTable[ i ] ;
tomwalters@0 225 filterSineTable[ filterSineTableSize/2 + i ] = -filterSineTable[ i ] ;
tomwalters@0 226 filterSineTable[ filterSineTableSize - i ] = -filterSineTable[ i ] ;
tomwalters@0 227 filterSineTable[ filterSineTableSize + i ] = filterSineTable[ i ] ;
tomwalters@0 228 }
tomwalters@0 229
tomwalters@0 230 filterCosineTable = filterSineTable + filterSineTableSize / 4 ;
tomwalters@0 231 }
tomwalters@0 232
tomwalters@0 233 return ;
tomwalters@0 234 }
tomwalters@0 235