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
|