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