123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- /* fftr.c
- *
- * FFT of Real Valued Sequence
- *
- *
- *
- * SYNOPSIS:
- *
- * double x[], sine[];
- * int m;
- *
- * fftr( x, m, sine );
- *
- *
- *
- * DESCRIPTION:
- *
- * Computes the (complex valued) discrete Fourier transform of
- * the real valued sequence x[]. The input sequence x[] contains
- * n = 2**m samples. The program fills array sine[k] with
- * n/4 + 1 values of sin( 2 PI k / n ).
- *
- * Data format for complex valued output is real part followed
- * by imaginary part. The output is developed in the input
- * array x[].
- *
- * The algorithm takes advantage of the fact that the FFT of an
- * n point real sequence can be obtained from an n/2 point
- * complex FFT.
- *
- * A radix 2 FFT algorithm is used.
- *
- * Execution time on an LSI-11/23 with floating point chip
- * is 1.0 sec for n = 256.
- *
- *
- *
- * REFERENCE:
- *
- * E. Oran Brigham, The Fast Fourier Transform;
- * Prentice-Hall, Inc., 1974
- *
- */
- #include <math.h>
- static short n0 = 0;
- static short n4 = 0;
- static short msav = 0;
- extern double PI;
- #ifdef ANSIPROT
- extern double sin ( double );
- static int bitrv(int, int);
- #else
- double sin();
- static int bitrv();
- #endif
- fftr( x, m0, sine )
- double x[];
- int m0;
- double sine[];
- {
- int th, nd, pth, nj, dth, m;
- int n, n2, j, k, l, r;
- double xr, xi, tr, ti, co, si;
- double a, b, c, d, bc, cs, bs, cc;
- double *p, *q;
- /* Array x assumed filled with real-valued data */
- /* m0 = log2(n0) */
- /* n0 is the number of real data samples */
- if( m0 != msav )
- {
- msav = m0;
- /* Find n0 = 2**m0 */
- n0 = 1;
- for( j=0; j<m0; j++ )
- n0 <<= 1;
- n4 = n0 >> 2;
- /* Calculate array of sines */
- xr = 2.0 * PI / n0;
- for( j=0; j<=n4; j++ )
- sine[j] = sin( j * xr );
- }
- n = n0 >> 1; /* doing half length transform */
- m = m0 - 1;
- /* fftr.c */
- /* Complex Fourier Transform of n Complex Data Points */
- /* First, bit reverse the input data */
- for( k=0; k<n; k++ )
- {
- j = bitrv( k, m );
- if( j > k )
- { /* executed approx. n/2 times */
- p = &x[2*k];
- tr = *p++;
- ti = *p;
- q = &x[2*j+1];
- *p = *q;
- *(--p) = *(--q);
- *q++ = tr;
- *q = ti;
- }
- }
-
- /* fftr.c */
- /* Radix 2 Complex FFT */
- n2 = n/2;
- nj = 1;
- pth = 1;
- dth = 0;
- th = 0;
- for( l=0; l<m; l++ )
- { /* executed log2(n) times, total */
- j = 0;
- do
- { /* executed n-1 times, total */
- r = th << 1;
- si = sine[r];
- co = sine[ n4 - r ];
- if( j >= pth )
- {
- th -= dth;
- co = -co;
- }
- else
- th += dth;
- nd = j;
- do
- { /* executed n/2 log2(n) times, total */
- r = (nd << 1) + (nj << 1);
- p = &x[ r ];
- xr = *p++;
- xi = *p;
- tr = xr * co + xi * si;
- ti = xi * co - xr * si;
- r = nd << 1;
- q = &x[ r ];
- xr = *q++;
- xi = *q;
- *p = xi - ti;
- *(--p) = xr - tr;
- *q = xi + ti;
- *(--q) = xr + tr;
- nd += nj << 1;
- }
- while( nd < n );
- }
- while( ++j < nj );
- n2 >>= 1;
- dth = n2;
- pth = nj;
- nj <<= 1;
- }
- /* fftr.c */
- /* Special trick algorithm */
- /* converts to spectrum of real series */
- /* Highest frequency term; add space to input array if wanted */
- /*
- x[2*n] = x[0] - x[1];
- x[2*n+1] = 0.0;
- */
- /* Zero frequency term */
- x[0] = x[0] + x[1];
- x[1] = 0.0;
- n2 = n/2;
- for( j=1; j<=n2; j++ )
- { /* executed n/2 times */
- si = sine[j];
- co = sine[ n4 - j ];
- p = &x[ 2*j ];
- xr = *p++;
- xi = *p;
- q = &x[ 2*(n-j) ];
- tr = *q++;
- ti = *q;
- a = xr + tr;
- b = xi + ti;
- c = xr - tr;
- d = xi - ti;
- bc = b * co;
- cs = c * si;
- bs = b * si;
- cc = c * co;
- *p = ( d - bs - cc )/2.0;
- *(--p) = ( a + bc - cs )/2.0;
- *q = -( d + bs + cc )/2.0;
- *(--q) = ( a - bc + cs )/2.0;
- }
- return(0);
- }
- /* fftr.c */
- /* Bit reverser */
- int bitrv( j, m )
- int j, m;
- {
- register int j1, ans;
- short k;
- ans = 0;
- j1 = j;
- for( k=0; k<m; k++ )
- {
- ans = (ans << 1) + (j1 & 1);
- j1 >>= 1;
- }
- return( ans );
- }
|