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