Mercurial > hg > aim92
comparison filter/generic.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 */ | |
17 | |
18 /* | |
19 ======================================================== | |
20 generic.c generic C code for recursive filter section. | |
21 ======================================================== | |
22 | |
23 | |
24 J. Holdsworth - 23rd February 1988. | |
25 | |
26 | |
27 Copywright (c) Applied Psychology Unit, Medical Research Council. 1988. | |
28 ======================================================================= | |
29 | |
30 | |
31 Release 2: 5th July 1988. | |
32 Rewrite : 21st Jan 1989. | |
33 | |
34 */ | |
35 | |
36 #ifndef _MATH_H_ | |
37 #include <math.h> | |
38 #define _MATH_H_ | |
39 #endif | |
40 | |
41 #ifndef _STITCH_H_ | |
42 #include "stitch.h" | |
43 #endif | |
44 #ifndef _RECURSE_H_ | |
45 #include "recurse.h" | |
46 #endif | |
47 #ifndef _PHASE_H_ | |
48 #include "phase.h" | |
49 #endif | |
50 #ifndef _GAMMA_TONE_H_ | |
51 #include "gamma_tone.h" | |
52 #endif | |
53 | |
54 #ifndef FLOAT | |
55 | |
56 #define STATE_TYPE long | |
57 | |
58 #define I_SHIFT( _number ) ( ( _number ) << i_shift ) | |
59 | |
60 #ifdef vax | |
61 #define K_SHIFT( _number ) ( ( _number ) << k_shift ) | |
62 #define S_SHIFT( _number ) ( ( _number ) << s_shift ) | |
63 #else | |
64 #define K_SHIFT( _number ) ( ( _number ) >> k_shift ) | |
65 #define S_SHIFT( _number ) ( ( _number ) >> s_shift ) | |
66 #endif | |
67 | |
68 #else | |
69 | |
70 #define STATE_TYPE FLOAT | |
71 | |
72 #define I_SHIFT( _number ) ( _number ) | |
73 #define K_SHIFT( _number ) ( _number ) | |
74 #define S_SHIFT( _number ) ( _number ) | |
75 | |
76 #endif | |
77 | |
78 #ifndef INPUT_TYPE | |
79 #define INPUT_TYPE short | |
80 #endif | |
81 | |
82 #ifndef OUTPUT_TYPE | |
83 #define OUTPUT_TYPE INPUT_TYPE | |
84 #endif | |
85 | |
86 #ifndef MODULE_NAME | |
87 #define MODULE_NAME DoFilterShortDataArray | |
88 #define FILTER_NAME FilterShortDataArray | |
89 #endif | |
90 | |
91 #ifdef DSP32 | |
92 | |
93 #define SIN( _PHI ) ( *( (float *) ( (char *) sin_table + istore ) ) ) | |
94 #define COS( _PHI ) ( *( (float *) ( (char *) cos_table + istore ) ) ) | |
95 | |
96 #else | |
97 | |
98 #define SIN( _PHI ) ( sin_table[ HI( _PHI ) ] ) | |
99 #define COS( _PHI ) ( cos_table[ HI( _PHI ) ] ) | |
100 | |
101 #endif | |
102 | |
103 /* Code that performs the actual filtering */ | |
104 | |
105 PointCount MODULE_NAME( filter_states, delays, input, output, points, channels ) | |
106 RecursiveFilterState **filter_states ; | |
107 int *delays ; | |
108 INPUT_TYPE *input ; | |
109 OUTPUT_TYPE *output ; | |
110 int points, channels ; | |
111 { | |
112 extern char *bstart, *bend ; | |
113 #ifdef DSP32 | |
114 /* do not change the order of these definitions - the "asm()" calls depend on it */ | |
115 register STATE_TYPE k, *states_ptr, *states_out, *states_end, *ptr ; | |
116 #else | |
117 register STATE_TYPE *states_ptr, *states_end, store, rstore, istore, k ; | |
118 #endif | |
119 register RecursiveFilterState *filter_state ; | |
120 #ifndef FLOAT | |
121 register int k_shift, s_shift, i_shift ; | |
122 #endif | |
123 #ifdef DSP32 | |
124 register int istore ; | |
125 #endif | |
126 register Table sin_table, cos_table ; | |
127 register STATE_TYPE output_store, input_store ; | |
128 #ifdef COMPLEX | |
129 register STATE_TYPE ioutput_store ; | |
130 #endif | |
131 register OUTPUT_TYPE *output_ptr, *end ; | |
132 register INPUT_TYPE *input_ptr ; | |
133 int loop_count, channel ; | |
134 #ifdef DSP32 | |
135 #ifndef ASM | |
136 STATE_TYPE a0, a1 ; | |
137 #endif | |
138 #endif | |
139 /* set up register pointers for speed of inner loop */ | |
140 | |
141 sin_table = filterSineTable ; | |
142 cos_table = filterCosineTable ; | |
143 | |
144 end = output + points * channels ; | |
145 | |
146 /* for all channels */ | |
147 | |
148 for( channel=0 ; channel < channels ; channel++ ) { | |
149 | |
150 filter_state = filter_states[ channel ] ; | |
151 | |
152 #ifndef FLOAT | |
153 i_shift = 16 - filter_state->input_bits ; | |
154 k_shift = 16 - 2 ; | |
155 | |
156 s_shift = filterSineTableShift ; | |
157 #endif | |
158 | |
159 /* if first time then perform implementation specific initialisation */ | |
160 | |
161 if( filter_state->states == (Pointer) 0 ) { | |
162 | |
163 filter_state->states = stitch_ralloc( (unsigned) ( filter_state->order + 1 ) * 2 * sizeof ( STATE_TYPE ), "generic.c for filter states" ) ; | |
164 | |
165 /* filter state stored in form of complex phasor for each cascade of filter */ | |
166 /* real and imaginary state values interleaved in state array */ | |
167 | |
168 filter_state->states_end = (Pointer) ( (STATE_TYPE *) filter_state->states + ( filter_state->order + 1 ) * 2 ) ; | |
169 | |
170 stitch_bzero( filter_state->states, (int) ( filter_state->states_end - filter_state->states ) ) ; | |
171 | |
172 #ifdef FLOAT | |
173 filter_state->output_scale /= ( 1l << filterSineTableShift ) ; | |
174 #ifdef ENVELOPE | |
175 filter_state->post_log = -log10( filter_state->output_scale ) * 2000. ; | |
176 #else | |
177 filter_state->output_scale /= ( 1l << filterSineTableShift ) ; | |
178 #endif | |
179 #else | |
180 filter_state->ik = filter_state->k * ( 1l << k_shift ) + 0.5 ; | |
181 filter_state->post_divisor = ( 1l << ( filterSineTableShift + i_shift ) ) / filter_state->output_scale + 0.5 ; | |
182 #ifdef ENVELOPE | |
183 filter_state->post_log = imB( (long) filter_state->post_divisor ) - imB( 1l << filterSineTableShift ) ; | |
184 #endif | |
185 #endif | |
186 #ifdef ENVELOPE | |
187 filter_state->post_log -= ( filter_state->over_sample - 1 ) * imB( 2l ) / 2 ; | |
188 #endif | |
189 } | |
190 | |
191 #ifdef FLOAT | |
192 k = filter_state->k ; | |
193 #else | |
194 k = filter_state->ik ; | |
195 #ifdef vax | |
196 k_shift = -k_shift ; | |
197 s_shift = -s_shift ; | |
198 #endif | |
199 #endif | |
200 | |
201 | |
202 /* Eurgh - the price of compatability */ | |
203 | |
204 if( input == (INPUT_TYPE *) 0 ) { | |
205 input_ptr = (INPUT_TYPE *) output ; | |
206 | |
207 stitch_bzero( input_ptr, ( end - output ) / channels * sizeof ( *input_ptr ) ) ; | |
208 } | |
209 else | |
210 input_ptr = input - delays[ channel ] ; | |
211 | |
212 /* not required to test bank.c any more | |
213 if( (char *) input_ptr < bstart || (char *) ( input_ptr + points ) > bend ) | |
214 printf( "Filter bank error!! %x %x %x\n", bstart, input_ptr, bend ) ; | |
215 */ | |
216 states_end = (STATE_TYPE *) filter_state->states_end ; | |
217 | |
218 #ifdef DSP32 | |
219 /* this section is optimised for DSP32 processor with more registers than instructions */ | |
220 | |
221 for( output_ptr = output + channel ; output_ptr < end ; output_ptr += channels ) { | |
222 | |
223 input_store = I_SHIFT( *input_ptr++ ) ; | |
224 output_store = 0 ; | |
225 #ifdef COMPLEX | |
226 ioutput_store = 0 ; | |
227 #endif | |
228 | |
229 loop_count = filter_state->over_sample ; | |
230 | |
231 do | |
232 { | |
233 /* multipy by complex phasor */ | |
234 | |
235 ptr = &input_store ; | |
236 | |
237 istore = HI( filter_state->phi ) << 1 << 1 ; | |
238 | |
239 #ifdef ASM | |
240 asm( "r1e = r6 + r8" ) ; | |
241 asm( "a0 = *r10 * *r1" ) ; | |
242 asm( "r2e = r7 + r8" ) ; | |
243 asm( "a1 = *r10 * *r2" ) ; | |
244 #else | |
245 a0 = *ptr * COS( filter_state->phi ) ; | |
246 a1 = *ptr * SIN( filter_state->phi ) ; | |
247 #endif | |
248 | |
249 /* low pass filter by simple alfa decay difference equation */ | |
250 | |
251 states_ptr = (STATE_TYPE *) filter_state->states ; | |
252 states_out = states_ptr ; | |
253 | |
254 #ifdef ASM | |
255 asm( "LOOP:" ) ; | |
256 asm( "a0 = a0 - *r13++" ) ; | |
257 asm( "a1 = a1 - *r13++" ) ; | |
258 asm( "nop" ) ; | |
259 asm( "*r12++ = a0 = *r12 + a3 * a0" ) ; | |
260 asm( "r13e - r11" ) ; | |
261 asm( "if(cc) goto EXIT" ); | |
262 asm( "*r12++ = a1 = *r12 + a3 * a1" ) ; | |
263 | |
264 asm( " a2 = a0 - *r13++ " ) ; | |
265 asm( " a1 = a1 - *r13++ " ) ; | |
266 asm( " a0 = *r12 " ) ; | |
267 asm( "*r12++ = a2 = *r12 + a3 * a2" ) ; | |
268 asm( " a2 = a1 " ) ; | |
269 asm( " a1 = *r12 " ) ; | |
270 asm( "r13e - r11" ) ; | |
271 asm( "if(cs) goto LOOP" ); | |
272 asm( "*r12++ = a2 = *r12 + a3 * a2" ) ; | |
273 asm( "EXIT:" ) ; | |
274 #else | |
275 do | |
276 { | |
277 a0 = a0 - *states_ptr++ ; | |
278 a1 = a1 - *states_ptr++ ; | |
279 a0 = *states_out++ += k * a0 ; | |
280 a1 = *states_out++ += k * a1 ; | |
281 } | |
282 while( states_ptr < states_end ) ; | |
283 /* multiply back up to carrier frequency */ | |
284 #endif | |
285 istore = HI( filter_state->output_phi ) << 1 << 1 ; | |
286 | |
287 #ifndef ENVELOPE | |
288 #ifdef ASM | |
289 asm( "r1e = r6 + r8" ) ; | |
290 asm( "a2 = a2 + a0 * *r1" ) ; | |
291 asm( "r2e = r7 + r8" ) ; | |
292 asm( "a2 = a2 + a1 * *r2" ) ; | |
293 #else | |
294 output_store += a0 * COS( filter_state->output_phi ) ; | |
295 output_store += a1 * SIN( filter_state->output_phi ) ; | |
296 #endif | |
297 #ifdef COMPLEX | |
298 ptr = &ioutput_store ; | |
299 #ifdef ASM | |
300 asm( " a0 = *r10 + a0 * *r2" ) ; | |
301 asm( "*r10 = a0 = a0 - a1 * *r1" ) ; | |
302 #else | |
303 ioutput_store += a0 * SIN( filter_state->output_phi ) ; | |
304 ioutput_store -= a1 * COS( filter_state->output_phi ) ; | |
305 #endif | |
306 #endif | |
307 #else ENVELOPE | |
308 #ifdef ASM | |
309 asm( "a2 = a2 + a1 * a1" ) ; | |
310 asm( "a2 = a2 + a0 * a0" ) ; | |
311 #else | |
312 output_store += a0 * a0 ; | |
313 output_store += a1 * a1 ; | |
314 #endif | |
315 #endif ENVELOPE | |
316 | |
317 ALL( filter_state->phi ) += filter_state->delta_phi ; | |
318 } | |
319 while( --loop_count > 0 ) ; | |
320 /* do it again if over sampling */ | |
321 | |
322 #else | |
323 /* this section optimised for generall purpose processor e.g. vax or 68000 */ | |
324 | |
325 for( output_ptr = output + channel ; output_ptr < end ; output_ptr += channels ) { | |
326 | |
327 input_store = I_SHIFT( *input_ptr++ ) ; | |
328 | |
329 output_store = 0 ; | |
330 #ifdef COMPLEX | |
331 ioutput_store = 0 ; | |
332 #endif | |
333 loop_count = filter_state->over_sample ; | |
334 | |
335 do | |
336 { | |
337 /* multipy by complex phasor */ | |
338 | |
339 states_ptr = (STATE_TYPE *) filter_state->states + 2 ; | |
340 | |
341 rstore = input_store * COS( filter_state->phi ) ; | |
342 istore = input_store * SIN( filter_state->phi ) ; | |
343 | |
344 do | |
345 { | |
346 rstore = *states_ptr + k * K_SHIFT( rstore - *states_ptr ) ; | |
347 *states_ptr++ = rstore ; | |
348 | |
349 istore = *states_ptr + k * K_SHIFT( istore - *states_ptr ) ; | |
350 *states_ptr++ = istore ; | |
351 | |
352 if( states_ptr < states_end ) { | |
353 store = k * K_SHIFT( rstore - *states_ptr ) ; | |
354 rstore = *states_ptr ; | |
355 *states_ptr++ = rstore + store ; | |
356 | |
357 store = k * K_SHIFT( istore - *states_ptr ) ; | |
358 istore = *states_ptr ; | |
359 *states_ptr++ = istore + store ; | |
360 } | |
361 } | |
362 while( states_ptr < states_end ) ; | |
363 /* | |
364 *states_ptr++ = input_store * COS( filter_state->phi ) ; | |
365 *states_ptr++ = input_store * SIN( filter_state->phi ) ; | |
366 | |
367 do | |
368 { | |
369 store = k * K_SHIFT( states_ptr[ -2 ] - *states_ptr ) ; | |
370 *states_ptr++ += store ; | |
371 store = k * K_SHIFT( states_ptr[ -2 ] - *states_ptr ) ; | |
372 *states_ptr++ += store ; | |
373 } | |
374 while( states_ptr < states_end ) ; | |
375 */ | |
376 /* multiply back up to carrier frequency */ | |
377 | |
378 #ifdef ENVELOPE | |
379 istore = S_SHIFT( istore ) ; | |
380 output_store += istore * istore ; | |
381 rstore = S_SHIFT( rstore ) ; | |
382 output_store += rstore * rstore ; | |
383 #else | |
384 output_store += S_SHIFT( istore ) * SIN( filter_state->output_phi ) ; | |
385 output_store += S_SHIFT( rstore ) * COS( filter_state->output_phi ) ; | |
386 #ifdef COMPLEX | |
387 ioutput_store -= S_SHIFT( istore ) * COS( filter_state->output_phi ) ; | |
388 ioutput_store += S_SHIFT( rstore ) * SIN( filter_state->output_phi ) ; | |
389 #endif | |
390 #endif | |
391 ALL( filter_state->phi ) += filter_state->delta_phi ; | |
392 ALL( filter_state->phi ) &= filterSineTableMask ; | |
393 } | |
394 while( --loop_count > 0 ) ; | |
395 /* do it again if over sampling */ | |
396 #endif | |
397 | |
398 /* common tail end */ | |
399 | |
400 #ifdef ENVELOPE | |
401 #ifdef FLOAT | |
402 if( output_store < 1. ) | |
403 *output_ptr = LOG_ZERO ; | |
404 else | |
405 *output_ptr = log10( output_store ) * 1000. - filter_state->post_log ; | |
406 | |
407 if( *output_ptr < 0. ) | |
408 *output_ptr = 0. ; | |
409 #else | |
410 *output_ptr = ( imB( (long) output_store ) >> 1 ) - filter_state->post_log ; | |
411 | |
412 if( *output_ptr < 0 ) | |
413 *output_ptr = 0 ; | |
414 #endif | |
415 #else | |
416 /* for non-envelope output */ | |
417 | |
418 ALL( filter_state->output_phi ) += filter_state->output_delta_phi ; | |
419 #ifndef DSP32 | |
420 ALL( filter_state->output_phi ) &= filterSineTableMask ; | |
421 #endif | |
422 | |
423 /* scale output_ptr back down for output_ptr array compensating for over sampling if ness. */ | |
424 | |
425 #ifdef COMPLEX | |
426 #ifdef FLOAT | |
427 output_ptr->real = output_store * filter_state->output_scale ; | |
428 output_ptr->imag = ioutput_store * filter_state->output_scale ; | |
429 #else | |
430 output_ptr->real = output_store / filter_state->post_divisor ; | |
431 output_ptr->imag = ioutput_store / filter_state->post_divisor ; | |
432 #endif | |
433 #else | |
434 #ifdef FLOAT | |
435 *output_ptr = output_store * filter_state->output_scale ; | |
436 #else | |
437 *output_ptr = output_store / filter_state->post_divisor ; | |
438 #endif | |
439 #endif | |
440 #endif | |
441 } | |
442 } | |
443 | |
444 return( sizeof ( OUTPUT_TYPE ) ) ; | |
445 } | |
446 | |
447 /* for compatability */ | |
448 | |
449 PointCount FILTER_NAME( compensator_state, input_array, output_array, npoints ) | |
450 FilterChannelInfo *compensator_state ; | |
451 INPUT_TYPE *input_array ; | |
452 OUTPUT_TYPE *output_array ; | |
453 PointCount npoints ; | |
454 { | |
455 ( (PhaseCompensatorState *) compensator_state )->filter_module = MODULE_NAME ; | |
456 | |
457 return( PhaseCompensateFilter( (PhaseCompensatorState *) compensator_state, ( Pointer ) input_array, ( Pointer ) output_array, npoints ) ) ; | |
458 } | |
459 | |
460 | |
461 /* tidy up defines for redefinition */ | |
462 | |
463 #undef STATE_TYPE | |
464 #undef INPUT_TYPE | |
465 #undef OUTPUT_TYPE | |
466 #undef FILTER_NAME | |
467 #undef MODULE_NAME | |
468 #undef I_SHIFT | |
469 #undef K_SHIFT | |
470 #undef S_SHIFT | |
471 | |
472 #undef SIN | |
473 #undef COS | |
474 | |
475 #ifdef FLOAT | |
476 #undef FLOAT | |
477 #endif | |
478 | |
479 #ifdef COMPLEX | |
480 #undef COMPLEX | |
481 #endif |