tomwalters@0
|
1 #include <stdio.h>
|
tomwalters@0
|
2 #include <math.h>
|
tomwalters@0
|
3 #include "sigproc.h"
|
tomwalters@0
|
4
|
tomwalters@0
|
5
|
tomwalters@0
|
6 /*
|
tomwalters@0
|
7 C is n complex numbers: (real,imag), (ie 2n floats).
|
tomwalters@0
|
8 Overwrite the first n floats with the modulus of the n complex numbers.
|
tomwalters@0
|
9 */
|
tomwalters@0
|
10
|
tomwalters@0
|
11 Mod( C, n )
|
tomwalters@0
|
12 complex *C ;
|
tomwalters@0
|
13 int n ;
|
tomwalters@0
|
14 {
|
tomwalters@0
|
15 register complex *eptr = C+n ;
|
tomwalters@0
|
16 register float *V = (float *)C ;
|
tomwalters@0
|
17
|
tomwalters@0
|
18 for ( ; C < eptr ; C++ )
|
tomwalters@0
|
19 *V++ = mod(C) ;
|
tomwalters@0
|
20 }
|
tomwalters@0
|
21
|
tomwalters@0
|
22 /*
|
tomwalters@0
|
23 Return the modulus of the given complex number
|
tomwalters@0
|
24 */
|
tomwalters@0
|
25
|
tomwalters@0
|
26 float mod( C )
|
tomwalters@0
|
27 complex *C ;
|
tomwalters@0
|
28 {
|
tomwalters@0
|
29 return ( sqrt( sq(Re(C)) + sq(Im(C)) ) ) ;
|
tomwalters@0
|
30 }
|
tomwalters@0
|
31
|
tomwalters@0
|
32
|
tomwalters@0
|
33
|
tomwalters@0
|
34 /*
|
tomwalters@0
|
35 C is n complex numbers: (real,imag), (ie 2n floats).
|
tomwalters@0
|
36 Overwrite the first n floats with the argument of the n complex numbers.
|
tomwalters@0
|
37 */
|
tomwalters@0
|
38
|
tomwalters@0
|
39 Arg( C, n )
|
tomwalters@0
|
40 complex *C ;
|
tomwalters@0
|
41 int n ;
|
tomwalters@0
|
42 {
|
tomwalters@0
|
43 register complex *eptr = C+n ;
|
tomwalters@0
|
44 register float *V = (float *)C ;
|
tomwalters@0
|
45
|
tomwalters@0
|
46 for ( ; C < eptr ; C++ )
|
tomwalters@0
|
47 *V++ = arg(C) ;
|
tomwalters@0
|
48 }
|
tomwalters@0
|
49
|
tomwalters@0
|
50 /*
|
tomwalters@0
|
51 Return the argument of the given complex number
|
tomwalters@0
|
52 */
|
tomwalters@0
|
53
|
tomwalters@0
|
54 float arg( C )
|
tomwalters@0
|
55 complex *C;
|
tomwalters@0
|
56 {
|
tomwalters@0
|
57 if (Im(C) >= 0) {
|
tomwalters@0
|
58 if (Re(C) >= 0) return ( atan(Im(C)/Re(C)) ); /* 1st quad */
|
tomwalters@0
|
59 else return ( PI + atan(Im(C)/Re(C)) ); /* 2nd quad */
|
tomwalters@0
|
60 }
|
tomwalters@0
|
61 else {
|
tomwalters@0
|
62 if (Re(C) < 0) return ( PI + atan(Im(C)/Re(C)) ); /* 1st quad */
|
tomwalters@0
|
63 else return ( TWOPI + atan(Im(C)/Re(C)) ); /* 2nd quad */
|
tomwalters@0
|
64 }
|
tomwalters@0
|
65 }
|
tomwalters@0
|
66
|
tomwalters@0
|
67
|
tomwalters@0
|
68 /*
|
tomwalters@0
|
69 C1 and C2 are both n complex numbers: (real,imag), (ie each 2n floats).
|
tomwalters@0
|
70 Overwrite the C1 with product of C1 and the complex conjugate of C2.
|
tomwalters@0
|
71 (When C1==C2, result is squared mod in the real parts, and 0 imag parts).
|
tomwalters@0
|
72 */
|
tomwalters@0
|
73
|
tomwalters@0
|
74 conj( C1, C2, n )
|
tomwalters@0
|
75 complex *C1, *C2 ;
|
tomwalters@0
|
76 int n ;
|
tomwalters@0
|
77 {
|
tomwalters@0
|
78 register complex *eptr = C1+n ;
|
tomwalters@0
|
79 float ReC1, ReC2 ;
|
tomwalters@0
|
80
|
tomwalters@0
|
81 for ( ; C1 < eptr ; C1++, C2++ ) {
|
tomwalters@0
|
82 Re(C1) = ( ReC1=Re(C1) ) * ( ReC2=Re(C2) ) + Im(C1) * Im(C2) ;
|
tomwalters@0
|
83 Im(C1) = ReC2 * Im(C1) - ReC1 * Im(C2) ;
|
tomwalters@0
|
84 }
|
tomwalters@0
|
85 }
|
tomwalters@0
|
86
|
tomwalters@0
|
87
|
tomwalters@0
|
88 /*
|
tomwalters@0
|
89 Autocorrelation function via fft.
|
tomwalters@0
|
90 A complex fft (of real data) is multiplied by its conjugate, and also scaled
|
tomwalters@0
|
91 prior to the inverse fft.
|
tomwalters@0
|
92 */
|
tomwalters@0
|
93
|
tomwalters@0
|
94
|
tomwalters@0
|
95
|
tomwalters@0
|
96 acf( V, m )
|
tomwalters@0
|
97 float *V ;
|
tomwalters@0
|
98 int m ;
|
tomwalters@0
|
99 {
|
tomwalters@0
|
100 register complex *C, *eptr ;
|
tomwalters@0
|
101 register int n = m>>1 ;
|
tomwalters@0
|
102 float tmp ;
|
tomwalters@0
|
103
|
tomwalters@0
|
104 fft( V, m, 1 ) ;
|
tomwalters@0
|
105 tmp = V[1] ; V[1] = 0 ;
|
tomwalters@0
|
106
|
tomwalters@0
|
107 for ( C=(complex *)V, eptr=C+n ; C<eptr ; C++ ) {
|
tomwalters@0
|
108 Re(C) = ( sq(Re(C)) + sq(Im(C)) ) / n ;
|
tomwalters@0
|
109 Im(C) = 0 ;
|
tomwalters@0
|
110 }
|
tomwalters@0
|
111 V[1] = sq( tmp ) / n ;
|
tomwalters@0
|
112
|
tomwalters@0
|
113 fft( V, m, -1 ) ;
|
tomwalters@0
|
114 }
|
tomwalters@0
|
115
|
tomwalters@0
|
116
|
tomwalters@0
|
117 /*
|
tomwalters@0
|
118 Test x: return 1 if x is a power of 2, otherwise return 0.
|
tomwalters@0
|
119 */
|
tomwalters@0
|
120
|
tomwalters@0
|
121 int ispower( x )
|
tomwalters@0
|
122 int x ;
|
tomwalters@0
|
123 {
|
tomwalters@0
|
124 return ( x > 1 && log2(x) == (int)log2(x) ) ;
|
tomwalters@0
|
125 }
|
tomwalters@0
|
126
|
tomwalters@0
|
127
|
tomwalters@0
|
128 /*
|
tomwalters@0
|
129 Return a power of 2, either equal to x (if x is already a power of 2), or
|
tomwalters@0
|
130 the next power of 2 larger than x.
|
tomwalters@0
|
131 */
|
tomwalters@0
|
132
|
tomwalters@0
|
133 int getpower( x )
|
tomwalters@0
|
134 int x ;
|
tomwalters@0
|
135 {
|
tomwalters@0
|
136 if ( log2(x) > (int)log2(x) )
|
tomwalters@0
|
137 x = 1 << ( 1 + (int)log2(x) ) ;
|
tomwalters@0
|
138 return ( x ) ;
|
tomwalters@0
|
139 }
|
tomwalters@0
|
140
|
tomwalters@0
|
141
|
tomwalters@0
|
142 /*
|
tomwalters@0
|
143 Copy float array x into short array y, both length n points.
|
tomwalters@0
|
144 Scale each point using the given scale factor.
|
tomwalters@0
|
145 Return 1 if no 16-bit over or underflow.
|
tomwalters@0
|
146 Otherwise return a scale factor to replace the given scale factor.
|
tomwalters@0
|
147
|
tomwalters@0
|
148 */
|
tomwalters@0
|
149
|
tomwalters@0
|
150 float ftos( x, y, n, scale )
|
tomwalters@0
|
151 float *x ;
|
tomwalters@0
|
152 short *y ;
|
tomwalters@0
|
153 int n ;
|
tomwalters@0
|
154 float scale ;
|
tomwalters@0
|
155 {
|
tomwalters@0
|
156 float p ;
|
tomwalters@0
|
157 float min = MAXSHORT, fmin ;
|
tomwalters@0
|
158 float max = MINSHORT, fmax ;
|
tomwalters@0
|
159 int i ;
|
tomwalters@0
|
160
|
tomwalters@0
|
161 fmax = fmin = 1. ;
|
tomwalters@0
|
162
|
tomwalters@0
|
163 for ( i = 0 ; i < n ; i++ ) {
|
tomwalters@0
|
164 p = x[i] * scale ;
|
tomwalters@0
|
165
|
tomwalters@0
|
166 if ( p > max ) max = p ;
|
tomwalters@0
|
167 if ( p < min ) min = p ;
|
tomwalters@0
|
168
|
tomwalters@0
|
169 y[i] = (short)p ;
|
tomwalters@0
|
170 }
|
tomwalters@0
|
171
|
tomwalters@0
|
172 if ( max > MAXSHORT || min < MINSHORT ) {
|
tomwalters@0
|
173
|
tomwalters@0
|
174 if ( max > MAXSHORT ) fmax = MAXSHORT / max ;
|
tomwalters@0
|
175 if ( min < MINSHORT ) fmin = MINSHORT / min ;
|
tomwalters@0
|
176
|
tomwalters@0
|
177 if ( fmax < fmin ) return ( scale * fmax ) ;
|
tomwalters@0
|
178 else return ( scale * fmin ) ;
|
tomwalters@0
|
179 }
|
tomwalters@0
|
180
|
tomwalters@0
|
181 return ( 1. ) ;
|
tomwalters@0
|
182 }
|
tomwalters@0
|
183
|
tomwalters@0
|
184
|
tomwalters@0
|
185
|
tomwalters@0
|
186
|
tomwalters@0
|
187 /*************************** convolution **********************************/
|
tomwalters@0
|
188
|
tomwalters@0
|
189 /*
|
tomwalters@0
|
190 Time-domain convolution. An input signal y of length n points is convolved
|
tomwalters@0
|
191 with a window x of length m points (where m is assumed odd for symmetry).
|
tomwalters@0
|
192 Return convolution signal z which must have allocated space of length n.
|
tomwalters@0
|
193
|
tomwalters@0
|
194 Discrete convolution is defined:
|
tomwalters@0
|
195 z[i] = sum{j=-inf to inf} x[i-j].y[j] for i=-inf to inf
|
tomwalters@0
|
196 But the signal y and window x are assumed to be zero for all time outside
|
tomwalters@0
|
197 the given points so that:
|
tomwalters@0
|
198 z[i] = sum{j=-m/2 to m/2} x[i-j].y[j] for i=0,1,...,n-1
|
tomwalters@0
|
199
|
tomwalters@0
|
200 Since the response of a linear filter to an arbitiary input signal is the
|
tomwalters@0
|
201 convolution of the signal with the filter's impulse response, the window may
|
tomwalters@0
|
202 be seen as the impulse response characterising the filter, and the return
|
tomwalters@0
|
203 z is then the filter output in response to input y.
|
tomwalters@0
|
204
|
tomwalters@0
|
205 Alternatively the convolution may be seen as a local averaging operation
|
tomwalters@0
|
206 on y with weights obtained by time-reversing and shifting x.
|
tomwalters@0
|
207 */
|
tomwalters@0
|
208
|
tomwalters@0
|
209 convolve_time( y, n, x, m, z )
|
tomwalters@0
|
210 short *y ; /* input signal */
|
tomwalters@0
|
211 int n ; /* length of array y */
|
tomwalters@0
|
212 float *x ; /* convolution window or filter impulse response */
|
tomwalters@0
|
213 int m ; /* length of array x */
|
tomwalters@0
|
214 float *z ; /* output signal of length n (same as input) */
|
tomwalters@0
|
215 {
|
tomwalters@0
|
216 register int i, j, k, lim1, lim2 ;
|
tomwalters@0
|
217 register float sum ;
|
tomwalters@0
|
218
|
tomwalters@0
|
219 for ( i = 0 ; i < n ; i++ ) {
|
tomwalters@0
|
220
|
tomwalters@0
|
221 k = m - 1 ;
|
tomwalters@0
|
222 if ( ( lim1 = i - (m-1)/2 ) < 0 ) {
|
tomwalters@0
|
223 k += lim1 ;
|
tomwalters@0
|
224 lim1 = 0 ;
|
tomwalters@0
|
225 }
|
tomwalters@0
|
226 if ( ( lim2 = i + (m-1)/2 ) > n )
|
tomwalters@0
|
227 lim2 = n - 1 ;
|
tomwalters@0
|
228
|
tomwalters@0
|
229 sum = 0 ;
|
tomwalters@0
|
230 for ( j = lim1 ; j <= lim2 ; j++, --k )
|
tomwalters@0
|
231 sum += x[k] * y[j] ;
|
tomwalters@0
|
232
|
tomwalters@0
|
233 z[i] = sum ;
|
tomwalters@0
|
234 }
|
tomwalters@0
|
235 }
|
tomwalters@0
|
236
|
tomwalters@0
|
237
|
tomwalters@0
|
238 /*
|
tomwalters@0
|
239 Frequency-domain convolution.
|
tomwalters@0
|
240 */
|
tomwalters@0
|
241
|
tomwalters@0
|
242 convolve_freq( y, n, x, m, z )
|
tomwalters@0
|
243 short *y ; /* input signal */
|
tomwalters@0
|
244 int n ; /* length of array y */
|
tomwalters@0
|
245 float *x ; /* convolution window or filter impulse response */
|
tomwalters@0
|
246 int m ; /* length of array x */
|
tomwalters@0
|
247 float *z ; /* output signal of length n (same as input) */
|
tomwalters@0
|
248 {
|
tomwalters@0
|
249 int i, j, n1 ;
|
tomwalters@0
|
250 float *data, *respns, *ans ;
|
tomwalters@0
|
251
|
tomwalters@0
|
252 n1 = getpower( n + m ) ; /* padded length of input signal */
|
tomwalters@0
|
253
|
tomwalters@0
|
254 data = (float *)malloc( ( n1 + 1 ) * sizeof(float) ) ;
|
tomwalters@0
|
255 respns = (float *)malloc( ( n1 + 1 ) * sizeof(float) ) ;
|
tomwalters@0
|
256 ans = (float *)malloc( ( n1 * 2 + 1 ) * sizeof(float) ) ;
|
tomwalters@0
|
257
|
tomwalters@0
|
258 /* copy and pad signal */
|
tomwalters@0
|
259
|
tomwalters@0
|
260 for ( i = 0 ; i < n ; i++ )
|
tomwalters@0
|
261 data[i] = y[i] ;
|
tomwalters@0
|
262 for ( ; i < n1 ; i++ )
|
tomwalters@0
|
263 data[i] = (float)0 ;
|
tomwalters@0
|
264
|
tomwalters@0
|
265 /* copy window into wrap-around order */
|
tomwalters@0
|
266
|
tomwalters@0
|
267 for ( i = m/2, j = 0 ; i < m ; i++, j++ )
|
tomwalters@0
|
268 respns[i] = x[j] ;
|
tomwalters@0
|
269 for ( i = 0 ; i < m/2 ; i++, j++ )
|
tomwalters@0
|
270 respns[i] = x[j] ;
|
tomwalters@0
|
271
|
tomwalters@0
|
272 /* Convolve and copy output */
|
tomwalters@0
|
273
|
tomwalters@0
|
274 convlv( data-1, n1, respns-1, m, 1, ans-1 ) ;
|
tomwalters@0
|
275
|
tomwalters@0
|
276 for ( i = 0 ; i < n ; i++ )
|
tomwalters@0
|
277 z[i] = ans[i] ;
|
tomwalters@0
|
278
|
tomwalters@0
|
279 free( data ) ;
|
tomwalters@0
|
280 free( respns ) ;
|
tomwalters@0
|
281 free( ans ) ;
|
tomwalters@0
|
282 }
|
tomwalters@0
|
283
|
tomwalters@0
|
284
|
tomwalters@0
|
285 /*
|
tomwalters@0
|
286 Convolution of two functions. [See NR: pp407-413].
|
tomwalters@0
|
287 Function 1 (the input signal) is in `data', length n, (n power of 2).
|
tomwalters@0
|
288 Function 2 (the response function) is in `respns', length m, (m<=n and odd).
|
tomwalters@0
|
289 (However respns must have n space available).
|
tomwalters@0
|
290 The response file should be stored in respns in "wrap-around order", ie with
|
tomwalters@0
|
291 its last half first and first half last in the array.
|
tomwalters@0
|
292 Return is the first n numbers in `ans', (though ans must have 2*n space).
|
tomwalters@0
|
293 Return convolution if isign==1, or deconvolution if isign==(-1).
|
tomwalters@0
|
294
|
tomwalters@0
|
295 The data array should be padded with zeroes to a power of 2.
|
tomwalters@0
|
296 The recommended amount of padding [NR: p411] is at least m/2, but need not be
|
tomwalters@0
|
297 more than m.
|
tomwalters@0
|
298 */
|
tomwalters@0
|
299
|
tomwalters@0
|
300 static float sqrarg;
|
tomwalters@0
|
301 #define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
|
tomwalters@0
|
302
|
tomwalters@0
|
303
|
tomwalters@0
|
304 convlv( data, n, respns, m, isign, ans )
|
tomwalters@0
|
305 float data[], respns[], ans[] ;
|
tomwalters@0
|
306 int n, m, isign ;
|
tomwalters@0
|
307 {
|
tomwalters@0
|
308 int i, no2 ;
|
tomwalters@0
|
309 float dum, mag2, *fftbuf ;
|
tomwalters@0
|
310
|
tomwalters@0
|
311 fftbuf = (float *)malloc( 2 * n * sizeof(float) ) ;
|
tomwalters@0
|
312
|
tomwalters@0
|
313 for (i=1;i<=(m-1)/2;i++)
|
tomwalters@0
|
314 respns[n+1-i]=respns[m+1-i];
|
tomwalters@0
|
315 for (i=(m+3)/2;i<=n-(m-1)/2;i++)
|
tomwalters@0
|
316 respns[i]=0.0;
|
tomwalters@0
|
317
|
tomwalters@0
|
318 twofft(data,respns,fftbuf,ans,n);
|
tomwalters@0
|
319 no2=n/2;
|
tomwalters@0
|
320 for (i=2;i<=n+2;i+=2) {
|
tomwalters@0
|
321 if (isign == 1) {
|
tomwalters@0
|
322 ans[i-1]=(fftbuf[i-1]*(dum=ans[i-1])-fftbuf[i]*ans[i])/no2;
|
tomwalters@0
|
323 ans[i]=(fftbuf[i]*dum+fftbuf[i-1]*ans[i])/no2;
|
tomwalters@0
|
324 } else if (isign == -1) {
|
tomwalters@0
|
325 if ((mag2=SQR(ans[i-1])+SQR(ans[i])) == 0.0)
|
tomwalters@0
|
326 fprintf( stderr, "warning: deconvolving at response zero\n" ) ;
|
tomwalters@0
|
327 ans[i-1]=(fftbuf[i-1]*(dum=ans[i-1])+fftbuf[i]*ans[i])/mag2/no2;
|
tomwalters@0
|
328 ans[i]=(fftbuf[i]*dum-fftbuf[i-1]*ans[i])/mag2/no2;
|
tomwalters@0
|
329 }
|
tomwalters@0
|
330 else {
|
tomwalters@0
|
331 fprintf( stderr, "No meaning for ISIGN in CONVLV\n" ) ;
|
tomwalters@0
|
332 exit( 1 ) ;
|
tomwalters@0
|
333 }
|
tomwalters@0
|
334 }
|
tomwalters@0
|
335 ans[2]=ans[n+1];
|
tomwalters@0
|
336 realft(ans,no2,-1);
|
tomwalters@0
|
337
|
tomwalters@0
|
338 free( fftbuf ) ;
|
tomwalters@0
|
339 }
|
tomwalters@0
|
340
|
tomwalters@0
|
341
|
tomwalters@0
|
342
|
tomwalters@0
|
343 /************************ fft ********************************************/
|
tomwalters@0
|
344
|
tomwalters@0
|
345 /*
|
tomwalters@0
|
346 In-place FFT/IFFT routine for real-valued data.
|
tomwalters@0
|
347 (Ref Numerical recipes, pp417).
|
tomwalters@0
|
348
|
tomwalters@0
|
349 Arguments:
|
tomwalters@0
|
350 data = Input array of 2n floats,
|
tomwalters@0
|
351 also output data array of n complex numbers.
|
tomwalters@0
|
352 n = Number of data points, (must be a power of two).
|
tomwalters@0
|
353 Input data is 2n real numbers.
|
tomwalters@0
|
354 Output data is n complex numbers.
|
tomwalters@0
|
355 isign = FFT when 1; IFFT when -1.
|
tomwalters@0
|
356
|
tomwalters@0
|
357 Each complex number occupies two consecutive locations: real and imag.
|
tomwalters@0
|
358 The output data is n real and imag parts which are the positive frequency
|
tomwalters@0
|
359 half of the symmetric Fourier transform.
|
tomwalters@0
|
360
|
tomwalters@0
|
361 Indexing conversion:
|
tomwalters@0
|
362
|
tomwalters@0
|
363 Both input and output data are indexed: 1,..,n.
|
tomwalters@0
|
364 where: Input data is 2n real numbers.
|
tomwalters@0
|
365 Output data is n complex numbers, (ie 2n floats).
|
tomwalters@0
|
366 To convert to conventional indexing: 0,..,m-1
|
tomwalters@0
|
367 where: Input data is m real numbers (eg. input framesize).
|
tomwalters@0
|
368 Output data is m/2 complex numbers, (ie m floats).
|
tomwalters@0
|
369
|
tomwalters@0
|
370 allocated space for "data" of:
|
tomwalters@0
|
371
|
tomwalters@0
|
372 (m+1)*sizeof(float).
|
tomwalters@0
|
373
|
tomwalters@0
|
374 call to routine "realft":
|
tomwalters@0
|
375
|
tomwalters@0
|
376 realft( data-1, m/2, isign ) ;
|
tomwalters@0
|
377
|
tomwalters@0
|
378 for example via the define:
|
tomwalters@0
|
379
|
tomwalters@0
|
380 #define fft(data,m,isign) ( realft((float *)(data)-1, m>>1, isign) )
|
tomwalters@0
|
381
|
tomwalters@0
|
382 This works because the location (data-1) is never indexed in routine realft.
|
tomwalters@0
|
383 Output data will then be data[0] to data[m/2-1] complex numbers,
|
tomwalters@0
|
384 ie data[0] to data[m-1] floats, to be interpreted as m/2 (real,imag) pairs.
|
tomwalters@0
|
385
|
tomwalters@0
|
386 The first of the m/2 points of the magnitude spectrum is then:
|
tomwalters@0
|
387 sqrt( sq( data[0] ) + sq( data[1] ) )
|
tomwalters@0
|
388
|
tomwalters@0
|
389
|
tomwalters@0
|
390 The results of the IFFT are not normalized by multplication by 1/N.
|
tomwalters@0
|
391 The user should multiply each returned element by 1/n.
|
tomwalters@0
|
392
|
tomwalters@0
|
393 Routine realft returns the first and last real components in data[1] and
|
tomwalters@0
|
394 data[2]. To make this correspond with the return from twofft, the mod below
|
tomwalters@0
|
395 sets data[2]=0.
|
tomwalters@0
|
396 */
|
tomwalters@0
|
397
|
tomwalters@0
|
398
|
tomwalters@0
|
399 realft(data,n,isign)
|
tomwalters@0
|
400 float data[];
|
tomwalters@0
|
401 int n,isign;
|
tomwalters@0
|
402 {
|
tomwalters@0
|
403 int i,i1,i2,i3,i4,n2p3;
|
tomwalters@0
|
404 float c1=0.5,c2,h1r,h1i,h2r,h2i;
|
tomwalters@0
|
405 double wr,wi,wpr,wpi,wtemp,theta;
|
tomwalters@0
|
406
|
tomwalters@0
|
407 theta=3.141592653589793/(double) n;
|
tomwalters@0
|
408 if (isign == 1) {
|
tomwalters@0
|
409 c2 = -0.5;
|
tomwalters@0
|
410 four1(data,n,1);
|
tomwalters@0
|
411 } else {
|
tomwalters@0
|
412 c2=0.5;
|
tomwalters@0
|
413 theta = -theta;
|
tomwalters@0
|
414 }
|
tomwalters@0
|
415 wtemp=sin(0.5*theta);
|
tomwalters@0
|
416 wpr = -2.0*wtemp*wtemp;
|
tomwalters@0
|
417 wpi=sin(theta);
|
tomwalters@0
|
418 wr=1.0+wpr;
|
tomwalters@0
|
419 wi=wpi;
|
tomwalters@0
|
420 n2p3=2*n+3;
|
tomwalters@0
|
421 for (i=2;i<=n/2;i++) {
|
tomwalters@0
|
422 i4=1+(i3=n2p3-(i2=1+(i1=i+i-1)));
|
tomwalters@0
|
423 h1r=c1*(data[i1]+data[i3]);
|
tomwalters@0
|
424 h1i=c1*(data[i2]-data[i4]);
|
tomwalters@0
|
425 h2r = -c2*(data[i2]+data[i4]);
|
tomwalters@0
|
426 h2i=c2*(data[i1]-data[i3]);
|
tomwalters@0
|
427 data[i1]=h1r+wr*h2r-wi*h2i;
|
tomwalters@0
|
428 data[i2]=h1i+wr*h2i+wi*h2r;
|
tomwalters@0
|
429 data[i3]=h1r-wr*h2r+wi*h2i;
|
tomwalters@0
|
430 data[i4] = -h1i+wr*h2i+wi*h2r;
|
tomwalters@0
|
431 wr=(wtemp=wr)*wpr-wi*wpi+wr;
|
tomwalters@0
|
432 wi=wi*wpr+wtemp*wpi+wi;
|
tomwalters@0
|
433 }
|
tomwalters@0
|
434 if (isign == 1) {
|
tomwalters@0
|
435 data[1] = (h1r=data[1])+data[2];
|
tomwalters@0
|
436 data[2] = h1r-data[2];
|
tomwalters@0
|
437 } else {
|
tomwalters@0
|
438 data[1]=c1*((h1r=data[1])+data[2]);
|
tomwalters@0
|
439 data[2]=c1*(h1r-data[2]);
|
tomwalters@0
|
440 four1(data,n,-1);
|
tomwalters@0
|
441 }
|
tomwalters@0
|
442 }
|
tomwalters@0
|
443
|
tomwalters@0
|
444
|
tomwalters@0
|
445 #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
|
tomwalters@0
|
446
|
tomwalters@0
|
447 four1(data,nn,isign)
|
tomwalters@0
|
448 float data[];
|
tomwalters@0
|
449 int nn,isign;
|
tomwalters@0
|
450 {
|
tomwalters@0
|
451 int n,mmax,m,j,istep,i;
|
tomwalters@0
|
452 double wtemp,wr,wpr,wpi,wi,theta;
|
tomwalters@0
|
453 float tempr,tempi;
|
tomwalters@0
|
454
|
tomwalters@0
|
455 n=nn << 1;
|
tomwalters@0
|
456 j=1;
|
tomwalters@0
|
457 for (i=1;i<n;i+=2) {
|
tomwalters@0
|
458 if (j > i) {
|
tomwalters@0
|
459 SWAP(data[j],data[i]);
|
tomwalters@0
|
460 SWAP(data[j+1],data[i+1]);
|
tomwalters@0
|
461 }
|
tomwalters@0
|
462 m=n >> 1;
|
tomwalters@0
|
463 while (m >= 2 && j > m) {
|
tomwalters@0
|
464 j -= m;
|
tomwalters@0
|
465 m >>= 1;
|
tomwalters@0
|
466 }
|
tomwalters@0
|
467 j += m;
|
tomwalters@0
|
468 }
|
tomwalters@0
|
469 mmax=2;
|
tomwalters@0
|
470 while (n > mmax) {
|
tomwalters@0
|
471 istep=2*mmax;
|
tomwalters@0
|
472 theta=6.28318530717959/(isign*mmax);
|
tomwalters@0
|
473 wtemp=sin(0.5*theta);
|
tomwalters@0
|
474 wpr = -2.0*wtemp*wtemp;
|
tomwalters@0
|
475 wpi=sin(theta);
|
tomwalters@0
|
476 wr=1.0;
|
tomwalters@0
|
477 wi=0.0;
|
tomwalters@0
|
478 for (m=1;m<mmax;m+=2) {
|
tomwalters@0
|
479 for (i=m;i<=n;i+=istep) {
|
tomwalters@0
|
480 j=i+mmax;
|
tomwalters@0
|
481 tempr=wr*data[j]-wi*data[j+1];
|
tomwalters@0
|
482 tempi=wr*data[j+1]+wi*data[j];
|
tomwalters@0
|
483 data[j]=data[i]-tempr;
|
tomwalters@0
|
484 data[j+1]=data[i+1]-tempi;
|
tomwalters@0
|
485 data[i] += tempr;
|
tomwalters@0
|
486 data[i+1] += tempi;
|
tomwalters@0
|
487 }
|
tomwalters@0
|
488 wr=(wtemp=wr)*wpr-wi*wpi+wr;
|
tomwalters@0
|
489 wi=wi*wpr+wtemp*wpi+wi;
|
tomwalters@0
|
490 }
|
tomwalters@0
|
491 mmax=istep;
|
tomwalters@0
|
492 }
|
tomwalters@0
|
493 }
|
tomwalters@0
|
494
|
tomwalters@0
|
495
|
tomwalters@0
|
496 twofft(data1,data2,fft1,fft2,n)
|
tomwalters@0
|
497 float data1[],data2[],fft1[],fft2[];
|
tomwalters@0
|
498 int n;
|
tomwalters@0
|
499 {
|
tomwalters@0
|
500 int nn3,nn2,jj,j;
|
tomwalters@0
|
501 float rep,rem,aip,aim;
|
tomwalters@0
|
502
|
tomwalters@0
|
503 nn3=1+(nn2=2+n+n);
|
tomwalters@0
|
504 for (j=1,jj=2;j<=n;j++,jj+=2) {
|
tomwalters@0
|
505 fft1[jj-1]=data1[j];
|
tomwalters@0
|
506 fft1[jj]=data2[j];
|
tomwalters@0
|
507 }
|
tomwalters@0
|
508 four1(fft1,n,1);
|
tomwalters@0
|
509 fft2[1]=fft1[2];
|
tomwalters@0
|
510 fft1[2]=fft2[2]=0.0;
|
tomwalters@0
|
511 for (j=3;j<=n+1;j+=2) {
|
tomwalters@0
|
512 rep=0.5*(fft1[j]+fft1[nn2-j]);
|
tomwalters@0
|
513 rem=0.5*(fft1[j]-fft1[nn2-j]);
|
tomwalters@0
|
514 aip=0.5*(fft1[j+1]+fft1[nn3-j]);
|
tomwalters@0
|
515 aim=0.5*(fft1[j+1]-fft1[nn3-j]);
|
tomwalters@0
|
516 fft1[j]=rep;
|
tomwalters@0
|
517 fft1[j+1]=aim;
|
tomwalters@0
|
518 fft1[nn2-j]=rep;
|
tomwalters@0
|
519 fft1[nn3-j] = -aim;
|
tomwalters@0
|
520 fft2[j]=aip;
|
tomwalters@0
|
521 fft2[j+1] = -rem;
|
tomwalters@0
|
522 fft2[nn2-j]=aip;
|
tomwalters@0
|
523 fft2[nn3-j]=rem;
|
tomwalters@0
|
524 }
|
tomwalters@0
|
525 }
|
tomwalters@0
|
526
|
tomwalters@0
|
527
|
tomwalters@0
|
528 /*********************** windows *******************************************/
|
tomwalters@0
|
529
|
tomwalters@0
|
530 /*
|
tomwalters@0
|
531 Allocate space for and compute an n-point Hann or raised cosine window,
|
tomwalters@0
|
532 returning array.
|
tomwalters@0
|
533 */
|
tomwalters@0
|
534
|
tomwalters@0
|
535 float *raised_cosine( n )
|
tomwalters@0
|
536 int n ;
|
tomwalters@0
|
537 {
|
tomwalters@0
|
538 float *W ;
|
tomwalters@0
|
539 register int i ;
|
tomwalters@0
|
540 register double k ;
|
tomwalters@0
|
541
|
tomwalters@0
|
542 W = (float *)malloc( n * sizeof(float) ) ;
|
tomwalters@0
|
543
|
tomwalters@0
|
544 k = TWOPI/(double)(n-1);
|
tomwalters@0
|
545 for (i=0 ; i<n ; i++)
|
tomwalters@0
|
546 W[i] = 0.5 * ( 1.0 - cos(k*i) ) ;
|
tomwalters@0
|
547
|
tomwalters@0
|
548 return W ;
|
tomwalters@0
|
549 }
|
tomwalters@0
|
550
|
tomwalters@0
|
551
|
tomwalters@0
|
552 /*
|
tomwalters@0
|
553 Allocate space for and compute an n-point Hamming window, returning array.
|
tomwalters@0
|
554 */
|
tomwalters@0
|
555
|
tomwalters@0
|
556 float *hamming( n )
|
tomwalters@0
|
557 int n ;
|
tomwalters@0
|
558 {
|
tomwalters@0
|
559 float *W ;
|
tomwalters@0
|
560 register int i ;
|
tomwalters@0
|
561 register double k ;
|
tomwalters@0
|
562
|
tomwalters@0
|
563 W = (float *)malloc( n * sizeof(float) ) ;
|
tomwalters@0
|
564
|
tomwalters@0
|
565 k = TWOPI/(double)(n-1);
|
tomwalters@0
|
566 for (i=0 ; i<n ; i++)
|
tomwalters@0
|
567 W[i] = 0.54 - 0.46*cos(k*i) ;
|
tomwalters@0
|
568
|
tomwalters@0
|
569 return W ;
|
tomwalters@0
|
570 }
|
tomwalters@0
|
571
|
tomwalters@0
|
572
|
tomwalters@0
|
573 /*
|
tomwalters@0
|
574 Allocate space for and compute a Gaussian window with given standard deviation
|
tomwalters@0
|
575 `s' (samples) over a range of `n' standard deviations either side of a zero
|
tomwalters@0
|
576 mean. The size of the returned window (returned via variable `num') will be:
|
tomwalters@0
|
577 2 * n * s + 1 [points]
|
tomwalters@0
|
578 (This is always odd as the window is symmetrical).
|
tomwalters@0
|
579 */
|
tomwalters@0
|
580
|
tomwalters@0
|
581 float *gauss_window( s, n, num )
|
tomwalters@0
|
582 float s, n ;
|
tomwalters@0
|
583 int *num ;
|
tomwalters@0
|
584 {
|
tomwalters@0
|
585 float x, *y, var ;
|
tomwalters@0
|
586 int i, points ;
|
tomwalters@0
|
587
|
tomwalters@0
|
588 points = 2 * n * s + 1 ;
|
tomwalters@0
|
589 y = (float *)malloc( points * sizeof(float) ) ;
|
tomwalters@0
|
590
|
tomwalters@0
|
591 x = ( - n * s ) ;
|
tomwalters@0
|
592 var = s * s ;
|
tomwalters@0
|
593 for ( i = 0 ; i < points ; i++, x++ )
|
tomwalters@0
|
594 y[i] = exp( -(double)( 0.5 * x * x / var ) ) ;
|
tomwalters@0
|
595
|
tomwalters@0
|
596 *num = points ;
|
tomwalters@0
|
597 return y ;
|
tomwalters@0
|
598 }
|
tomwalters@0
|
599
|
tomwalters@0
|
600
|
tomwalters@0
|
601 /*********************** frames *******************************************/
|
tomwalters@0
|
602
|
tomwalters@0
|
603 /*
|
tomwalters@0
|
604 Return a ptr to the n'th frame (numbered 1,2,3,...,n), with given
|
tomwalters@0
|
605 framewidth (size) and frameshift (step). Return the null ptr if eof before
|
tomwalters@0
|
606 the n'th frame. Frame number n=0 refers to the last frame before eof.
|
tomwalters@0
|
607 Successive calls to getframe must request increasing frame numbers.
|
tomwalters@0
|
608
|
tomwalters@0
|
609 Data (binary shorts) is buffered in an array of "blocksize" shorts,
|
tomwalters@0
|
610 allocated internally, where:
|
tomwalters@0
|
611 blocksize = size + ( frames_per_block - 1 ) * step
|
tomwalters@0
|
612 This means that the buffer can hold "frames_per_block" frames of the given
|
tomwalters@0
|
613 size and step, and ensures that no frame crosses the boundary between
|
tomwalters@0
|
614 successive buffers. At the buffer boundary, the overlap part
|
tomwalters@0
|
615 (where overlap = size - step) of the last frame in the buffer must
|
tomwalters@0
|
616 be shifted to the start of the buffer, and the step part of the next frame
|
tomwalters@0
|
617 must be read so as to follow it in the buffer, completing the first frame of
|
tomwalters@0
|
618 the next buffer.
|
tomwalters@0
|
619 To protect the last frame (in the event that the next step part is actually
|
tomwalters@0
|
620 the eof), the first frame of the next buffer must not corrupt the last frame
|
tomwalters@0
|
621 of the previous buffer. This is ensured by arranging that:
|
tomwalters@0
|
622 size <= ( frames_per_block - 1 ) * step
|
tomwalters@0
|
623 This constrains frames_per_block to be:
|
tomwalters@0
|
624 frames_per_block >= ( size / step ) + 1
|
tomwalters@0
|
625 Therefore the minimum number of frames_per_block (when step = size, and there
|
tomwalters@0
|
626 is no overlap) is 2.
|
tomwalters@0
|
627 The actual value you give to frames_per_block is an efficiency issue, being
|
tomwalters@0
|
628 a trade-off between space usage and the number of times a shift is necessary
|
tomwalters@0
|
629 at a buffer boundary. A reasonable guess would be (see define below):
|
tomwalters@0
|
630 frames_per_block = ( size / step ) + 1 + FRAMES_PER_BLOCK
|
tomwalters@0
|
631
|
tomwalters@0
|
632 An example of a shifting frame buffer, from frame a to b inclusive in steps
|
tomwalters@0
|
633 of 1 frame, would be:
|
tomwalters@0
|
634
|
tomwalters@0
|
635 while ( ( buf = getframe( fp, a, size, step ) ) != (short *)0 && ( a<=b || b==0 ) ) {
|
tomwalters@0
|
636 process( buf, size ) ;
|
tomwalters@0
|
637 a++ ;
|
tomwalters@0
|
638 }
|
tomwalters@0
|
639 if ( a<=b && b>0 )
|
tomwalters@0
|
640 fprintf(stderr,"warning: not enough frames for request\n");
|
tomwalters@0
|
641
|
tomwalters@0
|
642 */
|
tomwalters@0
|
643
|
tomwalters@0
|
644 #define FRAMES_PER_BLOCK 10
|
tomwalters@0
|
645
|
tomwalters@0
|
646 short *getframe( fp, n, size, step )
|
tomwalters@0
|
647 FILE *fp ;
|
tomwalters@0
|
648 int n, size, step ;
|
tomwalters@0
|
649 {
|
tomwalters@0
|
650 static int first = 1 ;
|
tomwalters@0
|
651 static short *buf, *endptr ;
|
tomwalters@0
|
652 static short *bptr = (short *) 0 ;
|
tomwalters@0
|
653 static int blocksize, overlap, frames_per_block ;
|
tomwalters@0
|
654 static int m = 0 ; /* frame counter */
|
tomwalters@0
|
655 int startsize, i ;
|
tomwalters@0
|
656
|
tomwalters@0
|
657 if ( n < m ) /* catches invalid calls and also case of n==0 */
|
tomwalters@0
|
658 return (short *) 0 ;
|
tomwalters@0
|
659
|
tomwalters@0
|
660 if ( first ) {
|
tomwalters@0
|
661 first = 0 ;
|
tomwalters@0
|
662 frames_per_block = ( size / step ) + 1 + FRAMES_PER_BLOCK ;
|
tomwalters@0
|
663 blocksize = size + ( frames_per_block - 1 ) * step ;
|
tomwalters@0
|
664 overlap = size - step ;
|
tomwalters@0
|
665 bptr = buf = (short *)malloc( blocksize * sizeof(short) ) ;
|
tomwalters@0
|
666 endptr = buf + blocksize ;
|
tomwalters@0
|
667
|
tomwalters@0
|
668 if ( n > 0 ) {
|
tomwalters@0
|
669
|
tomwalters@0
|
670 /* seek the n'th frame in blocks of blocksize. */
|
tomwalters@0
|
671
|
tomwalters@0
|
672 startsize = ( n - 1 ) * step ;
|
tomwalters@0
|
673 for ( i = blocksize ; i < startsize ; i += blocksize )
|
tomwalters@0
|
674 if ( fread( buf, sizeof(short), blocksize, fp ) < blocksize )
|
tomwalters@0
|
675 return (short *) 0 ;
|
tomwalters@0
|
676 if ( ( startsize -= ( i - blocksize ) ) > 0 )
|
tomwalters@0
|
677 if ( fread( buf, sizeof(short), startsize, fp ) < startsize )
|
tomwalters@0
|
678 return (short *) 0 ;
|
tomwalters@0
|
679
|
tomwalters@0
|
680 if ( ( fread( bptr, sizeof(short), size, fp ) ) < size )
|
tomwalters@0
|
681 return (short *) 0 ;
|
tomwalters@0
|
682 m = n ;
|
tomwalters@0
|
683 }
|
tomwalters@0
|
684 else {
|
tomwalters@0
|
685
|
tomwalters@0
|
686 /* seek the last frame in blocks of blocksize */
|
tomwalters@0
|
687
|
tomwalters@0
|
688 if ( fread( buf, sizeof(short), size, fp ) < size )
|
tomwalters@0
|
689 return (short *) 0 ;
|
tomwalters@0
|
690 startsize = blocksize - size ;
|
tomwalters@0
|
691 for ( m = 1 ; ( i = fread( buf+size, sizeof(short), startsize, fp ) ) == startsize ; m += frames_per_block - 1 ) {
|
tomwalters@0
|
692 bptr = endptr-size ;
|
tomwalters@0
|
693 while ( bptr < endptr )
|
tomwalters@0
|
694 *buf++ = *bptr++ ;
|
tomwalters@0
|
695 buf -= size ;
|
tomwalters@0
|
696 }
|
tomwalters@0
|
697 bptr = buf + ( i / step) * step ;
|
tomwalters@0
|
698 m += i / step ;
|
tomwalters@0
|
699 }
|
tomwalters@0
|
700 return ( bptr ) ;
|
tomwalters@0
|
701 }
|
tomwalters@0
|
702
|
tomwalters@0
|
703 for ( ; m < n || n == 0 ; m++ ) {
|
tomwalters@0
|
704
|
tomwalters@0
|
705 if ( bptr + size >= endptr ) { /* shift last overlap to buf start */
|
tomwalters@0
|
706 while ( bptr < endptr )
|
tomwalters@0
|
707 *buf++ = *bptr++ ;
|
tomwalters@0
|
708 buf -= overlap ;
|
tomwalters@0
|
709 bptr = buf - step ;
|
tomwalters@0
|
710 }
|
tomwalters@0
|
711
|
tomwalters@0
|
712 if ( ( fread( bptr+size, sizeof(short), step, fp ) ) < step ) {
|
tomwalters@0
|
713 if ( n == 0 ) {
|
tomwalters@0
|
714 if ( bptr < buf ) return ( endptr - size ) ;
|
tomwalters@0
|
715 else return ( bptr ) ;
|
tomwalters@0
|
716 }
|
tomwalters@0
|
717 return (short *) 0 ;
|
tomwalters@0
|
718 }
|
tomwalters@0
|
719 bptr += step ;
|
tomwalters@0
|
720 }
|
tomwalters@0
|
721 return ( bptr ) ;
|
tomwalters@0
|
722 }
|
tomwalters@0
|
723
|
tomwalters@0
|
724
|
tomwalters@0
|
725 /*************************************************************************/
|
tomwalters@0
|
726
|
tomwalters@0
|
727 /*
|
tomwalters@0
|
728 Seek past n frames in blocks of blocksize.
|
tomwalters@0
|
729 Frames have width=size and shift=step.
|
tomwalters@0
|
730 When step == size, the seek reads ( n * size ) shorts from the i/p stream.
|
tomwalters@0
|
731 When step < size, the seek reads ( size + ( n - 1 ) * step ) shorts.
|
tomwalters@0
|
732 Return 1, or otherwise 0 for an improper seek (insufficient data in stream).
|
tomwalters@0
|
733 */
|
tomwalters@0
|
734
|
tomwalters@0
|
735 seekframes( fp, n, size, step )
|
tomwalters@0
|
736 FILE *fp ;
|
tomwalters@0
|
737 int n, size, step ;
|
tomwalters@0
|
738 {
|
tomwalters@0
|
739 static short *buf ;
|
tomwalters@0
|
740 static int first = 1 ;
|
tomwalters@0
|
741 static int blocksize, frames_per_block ;
|
tomwalters@0
|
742 int startsize = size + ( n - 1 ) * step ;
|
tomwalters@0
|
743 int i ;
|
tomwalters@0
|
744
|
tomwalters@0
|
745 if ( first ) {
|
tomwalters@0
|
746 first = 0 ;
|
tomwalters@0
|
747 frames_per_block = ( size / step ) + 1 + FRAMES_PER_BLOCK ;
|
tomwalters@0
|
748 blocksize = size + ( frames_per_block - 1 ) * step ;
|
tomwalters@0
|
749 buf = (short *)malloc( blocksize * sizeof(short) ) ;
|
tomwalters@0
|
750 }
|
tomwalters@0
|
751 for ( i = blocksize ; i < startsize ; i += blocksize )
|
tomwalters@0
|
752 if ( fread( buf, sizeof(short), blocksize, fp ) < blocksize )
|
tomwalters@0
|
753 return 0 ;
|
tomwalters@0
|
754 if ( (startsize -= (i - blocksize)) > 0 )
|
tomwalters@0
|
755 if ( fread( buf, sizeof(short), startsize, fp ) < startsize )
|
tomwalters@0
|
756 return 0 ;
|
tomwalters@0
|
757
|
tomwalters@0
|
758 return 1 ;
|
tomwalters@0
|
759 }
|
tomwalters@0
|
760
|
tomwalters@0
|
761 /*************************************************************************/
|
tomwalters@0
|
762
|
tomwalters@0
|
763 /*
|
tomwalters@0
|
764 Seek past n bytes from current position in stream.
|
tomwalters@0
|
765 Return 1, or otherwise 0 for an improper seek (insufficient data in stream).
|
tomwalters@0
|
766 */
|
tomwalters@0
|
767
|
tomwalters@0
|
768 seekbytes( fp, n )
|
tomwalters@0
|
769 FILE *fp ;
|
tomwalters@0
|
770 int n ;
|
tomwalters@0
|
771 {
|
tomwalters@0
|
772 static char *buf ;
|
tomwalters@0
|
773 static int first = 1 ;
|
tomwalters@0
|
774
|
tomwalters@0
|
775 if ( n > 0 ) {
|
tomwalters@0
|
776 if ( first ) {
|
tomwalters@0
|
777 first = 0 ;
|
tomwalters@0
|
778 buf = (char *)malloc( n ) ;
|
tomwalters@0
|
779 }
|
tomwalters@0
|
780
|
tomwalters@0
|
781 if ( fread( buf, 1, n, fp ) < n )
|
tomwalters@0
|
782 return 0 ;
|
tomwalters@0
|
783 }
|
tomwalters@0
|
784 return 1 ;
|
tomwalters@0
|
785 }
|
tomwalters@0
|
786
|
tomwalters@0
|
787
|
tomwalters@0
|
788
|
tomwalters@0
|
789 /*********************** normalizing **************************************/
|
tomwalters@0
|
790
|
tomwalters@0
|
791 /*
|
tomwalters@0
|
792 Normalize the n-array y so that the sum of the points (ie the area) is unity.
|
tomwalters@0
|
793 */
|
tomwalters@0
|
794
|
tomwalters@0
|
795 normalize_area( y, n )
|
tomwalters@0
|
796 float *y ;
|
tomwalters@0
|
797 int n ;
|
tomwalters@0
|
798 {
|
tomwalters@0
|
799 float sum = 0 ;
|
tomwalters@0
|
800 int i ;
|
tomwalters@0
|
801
|
tomwalters@0
|
802 for ( i=0 ; i < n ; i++ )
|
tomwalters@0
|
803 sum += y[i] ;
|
tomwalters@0
|
804 for ( i=0 ; i < n ; i++ )
|
tomwalters@0
|
805 y[i] /= sum ;
|
tomwalters@0
|
806 }
|
tomwalters@0
|
807
|
tomwalters@0
|
808
|
tomwalters@0
|
809 /*
|
tomwalters@0
|
810 Normalize the n-array y so that the range of y[i] is [0,1].
|
tomwalters@0
|
811 */
|
tomwalters@0
|
812
|
tomwalters@0
|
813 normalize_range( y, n )
|
tomwalters@0
|
814 float *y ;
|
tomwalters@0
|
815 int n ;
|
tomwalters@0
|
816 {
|
tomwalters@0
|
817 int i ;
|
tomwalters@0
|
818 float max = ( -256000. ) ;
|
tomwalters@0
|
819 float min = 256000. ;
|
tomwalters@0
|
820
|
tomwalters@0
|
821 for ( i = 0 ; i < n ; i++ ) { /* find max and min */
|
tomwalters@0
|
822 if ( y[i] > max ) max = y[i] ;
|
tomwalters@0
|
823 if ( y[i] < min ) min = y[i] ;
|
tomwalters@0
|
824 }
|
tomwalters@0
|
825
|
tomwalters@0
|
826 for ( i = 0 ; i < n ; i++ )
|
tomwalters@0
|
827 y[i] = ( y[i] - min ) / ( max - min ) ;
|
tomwalters@0
|
828 }
|
tomwalters@0
|
829
|
tomwalters@0
|
830
|