comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:5242703e91d3
1 /*
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
3 ===========================================================================
4
5 Permission to use, copy, modify, and distribute this software without fee
6 is hereby granted for research purposes, provided that this copyright
7 notice appears in all copies and in all supporting documentation, and that
8 the software is not redistributed for any fee (except for a nominal shipping
9 charge). Anyone wanting to incorporate all or part of this software in a
10 commercial product must obtain a license from the Medical Research Council.
11
12 The MRC makes no representations about the suitability of this
13 software for any purpose. It is provided "as is" without express or implied
14 warranty.
15
16 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24 /*
25 ================================================
26 recurse.c - start-up code for recursive filter
27 ================================================
28
29
30 Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit.
31
32
33 Author : John Holdsworth
34 Written : 22th March, 1989.
35
36 Edited :
37
38 */
39
40
41 #include <math.h>
42
43 #ifndef _STITCH_H_
44 #include "stitch.h"
45 #endif
46
47 #ifndef _RECURSE_H_
48 #include "recurse.h"
49 #endif
50
51 #define Pi ( 3.1415926535 )
52 #define TwoPi ( 2*Pi )
53
54 #ifndef lint
55 static char *sccs_id = "@(#)recurse.c 1.8 John Holdsworth (MRC-APU) 11/8/90" ;
56 #endif
57
58 static void generateSineTable() ;
59 static double factorial() ;
60
61 #ifdef DSP32
62 int filterSineTableBits = 8 ;
63 int filterSineTableShift = 0 ;
64 #else
65 int filterSineTableBits = 12 ;
66 int filterSineTableShift = 14 ;
67 #endif
68 unsigned long filterSineTableSize, filterSineTableMask ;
69 Table filterSineTable, filterCosineTable ;
70
71 char *bstart, *bend ;
72
73
74 RecursiveFilterState *NewRecursiveFilter( samplerate, center_frequency, bandwidth, output_scale, order, phase_compensation, input_bits, sample_delay )
75 double samplerate, center_frequency, bandwidth, output_scale ;
76 int order, phase_compensation, input_bits ;
77 double *sample_delay ;
78 {
79 DeclareNew( RecursiveFilterState *, filter_state ) ;
80 double omega ;
81
82 if( filterSineTableSize != 1 << filterSineTableBits )
83 generateSineTable() ;
84
85 filter_state->order = order ;
86 filter_state->input_bits = input_bits ;
87
88 /* compensation for nominal 6dB loss in filter */
89
90 filter_state->output_scale = output_scale * 2. ;
91
92 omega = TwoPi * bandwidth / bandwidth_normalisation( filter_state->order ) ;
93
94 /* delta phi of carrier between sample ticks */
95
96 filter_state->output_delta_phi = center_frequency / samplerate * ( filterSineTableSize << 16 ) + 0.5 ;
97 filter_state->delta_phi = filter_state->output_delta_phi ;
98
99 /* initialise phases to give rounding */
100
101 ALL( filter_state->phi ) = ALL( filter_state->output_phi ) = 1l << 15 ;
102
103 /* calculate time delay required for phase compensation selected */
104 /* time advance is currently implemented as delay of */
105 /* maximum advance minus desired advance */
106
107 if( center_frequency < samplerate / 4 )
108 filter_state->over_sample = 1 ;
109 else {
110 /* if center frequency is over half the nyquist rate filtering process */
111 /* is performed at twice the sampling rate to avoid aliases */
112
113 filter_state->over_sample = 2 ;
114
115 ALL( filter_state->phi ) -= filter_state->delta_phi / 4 ;
116 #ifndef DSP32
117 ALL( filter_state->phi ) &= filterSineTableMask ;
118 #endif
119 filter_state->delta_phi /= 2 ;
120
121 /* must amplitude compensate for attenuation of high frequencies introduced by over sampling */
122
123 filter_state->output_scale /= ( filter_state->over_sample * cos( TwoPi * center_frequency / samplerate / 4 ) ) ;
124 }
125
126 filter_state->k = ( double ) 1. - exp( -omega / samplerate / filter_state->over_sample ) ;
127
128 /* fiddle delay time to take into acount half sample */
129 /* interval advance introduced by difference equation */
130
131 #if 0 /* not needed any more as alternate forward and backward differences */
132
133 *sample_delay += filter_state->order / filter_state->over_sample / 2 ;
134
135 /* compensate carrier phase for delay introduced above */
136
137 ALL( filter_state->output_phi ) += filter_state->order / filter_state->over_sample / 2 *
138 filter_state->delta_phi * filter_state->over_sample ;
139 #ifndef DSP32
140 ALL( filter_state->output_phi ) &= filterSineTableMask ;
141 #endif
142 #endif
143
144 /* munge to sin phase gammatone for mfsais */
145
146 ALL( filter_state->output_phi ) += 3 * filterSineTableMask / 4 ;
147
148 /* perform required phase compensation */
149
150 if( phase_compensation > 0 )
151 *sample_delay -= phase_compensation / center_frequency * samplerate ;
152 else if( phase_compensation < 0 )
153 *sample_delay -= ( filter_state->order - 1. ) / omega * samplerate ;
154
155 /* if phase compensation of type -2 or -4 is asked for the carrier phase */
156 /* is shifted to be aligned with the envelope maxima */
157
158 if( phase_compensation == FINE_ALIGNMENT || phase_compensation <= ACUASAL + FINE_ALIGNMENT ) {
159 ALL( filter_state->phi ) += ( filter_state->order - 1. ) / omega * center_frequency * ( filterSineTableSize << 16 ) + 0.5 ;
160 #ifndef DSP32
161 ALL( filter_state->phi ) &= filterSineTableMask ;
162 #endif
163 }
164
165 /* new recurse filter coefts */
166
167 filter_state->gain = pow( 2 * omega / samplerate, (double) order ) * output_scale ;
168 filter_state->k1 = exp( -omega / samplerate ) * cos( TwoPi * center_frequency / samplerate ) ;
169 filter_state->k2 = exp( -2 * omega / samplerate ) ;
170
171 /* flag channel not fully initialised */
172 /* leave filter specific initialisation to specific filter code */
173
174 filter_state->states = ( char * ) 0 ;
175
176 /* generate sin lookup table if necessary */
177
178 return ( filter_state ) ;
179 }
180
181 double bandwidth_normalisation( order )
182 int order ;
183 {
184 return( Pi * factorial( 2*order - 2 ) / factorial( order - 1 ) / factorial( order - 1 ) / ( 1 << ( 2 * order - 2 ) ) ) ;
185 }
186
187 static double factorial( n )
188 int n ;
189 {
190 double fact ;
191 int i ;
192
193 fact = 1. ;
194
195 for( i = n ; i > 1 ; i-- )
196 fact *= i ;
197
198 return( fact ) ;
199 }
200
201
202 static void generateSineTable()
203 {
204 static double filterTwoPi ;
205 register int i ;
206
207 if( filterSineTableSize != 1 << filterSineTableBits )
208 {
209 if( filterSineTable != ( Table ) 0 )
210 stitch_free( ( Pointer ) filterSineTable ) ;
211
212 if( filterTwoPi == 0. )
213 filterTwoPi = atan( 1. ) * 8. ;
214
215 filterSineTableSize = 1l << filterSineTableBits ;
216 filterSineTableMask = ( filterSineTableSize << 16 ) - 1 ;
217
218 /* sin table 5/4 times larger than required for cosine values */
219
220 filterSineTable = ( Table ) stitch_malloc( ( unsigned ) ( filterSineTableSize * 5 / 4 + 1 ) * sizeof( *filterSineTable ), "recurse.c for log table" ) ;
221
222 for( i=0 ; i <= filterSineTableSize/4 ; i++ ) {
223 filterSineTable[ i ] = sin( filterTwoPi * i / filterSineTableSize ) * ( 1<<filterSineTableShift ) ;
224 filterSineTable[ filterSineTableSize/2 - i ] = filterSineTable[ i ] ;
225 filterSineTable[ filterSineTableSize/2 + i ] = -filterSineTable[ i ] ;
226 filterSineTable[ filterSineTableSize - i ] = -filterSineTable[ i ] ;
227 filterSineTable[ filterSineTableSize + i ] = filterSineTable[ i ] ;
228 }
229
230 filterCosineTable = filterSineTable + filterSineTableSize / 4 ;
231 }
232
233 return ;
234 }
235