ftp.nice.ch/pub/next/unix/audio/cmusic.bs.N.tar.gz#/Apps/WaveFormEditor/fft.c

This is fft.c in view mode; [Download] [Up]

#include <stdio.h>
#include <math.h>


typedef struct { float re ; float im ; } complex ;

#define CABS(x) hypot( (x).re, (x).im )
#define TWOPI  6.28318530717958647692

complex cadd(), csub(), cmult(), smult(), cdiv(), conjg(), csqrt() ;

extern complex zero ;
extern complex one ;
extern float synt ;
/*
 * memory allocation macro
 */
#define fvec( name, size )\
if ( ( name = (float *) calloc( size, sizeof(float) ) ) == NULL) {\
    fprintf( stderr, "Insufficient memory\n" ) ;\
    exit( -1 ) ;\
}

/*
 * If forward is true, rfft replaces 2*N real data points in x with
 * N complex values representing the positive frequency half of their
 * Fourier spectrum, with x[1] replaced with the real part of the Nyquist
 * frequency value.  If forward is false, rfft expects x to contain a
 * positive frequency spectrum arranged as before, and replaces it with
 * 2*N real values.  N MUST be a power of 2.
 */
rfft( x, N, forward ) float x[] ; int N, forward ; {
 float c1, c2, h1r, h1i, h2r, h2i, wr, wi, wpr, wpi, temp, theta ;
 float xr, xi ;
 int i, i1, i2, i3, i4, N2p1 ;
 void cfft();
  
    theta = M_PI/N ;
    wr = 1. ;
    wi = 0. ;
    c1 = 0.5 ;
    if ( forward ) {
	c2 = -0.5 ;
	cfft( x, N, forward ) ;
	xr = x[0] ;
	xi = x[1] ;
    } else {
	c2 = 0.5 ;
	theta = -theta ;
	xr = x[1] ;
	xi = 0. ;
	x[1] = 0. ;
    }
    wpr = -2.*pow( sin( 0.5*theta ), 2. ) ;
    wpi = sin( theta ) ;
    N2p1 = (N<<1) + 1 ;
    for ( i = 0 ; i <= N>>1 ; i++ ) {
	i1 = i<<1 ;
	i2 = i1 + 1 ;
	i3 = N2p1 - i2 ;
	i4 = i3 + 1 ;
	if ( i == 0 ) {
	    h1r =  c1*(x[i1] + xr ) ;
	    h1i =  c1*(x[i2] - xi ) ;
	    h2r = -c2*(x[i2] + xi ) ;
	    h2i =  c2*(x[i1] - xr ) ;
	    x[i1] =  h1r + wr*h2r - wi*h2i ;
	    x[i2] =  h1i + wr*h2i + wi*h2r ;
	    xr =  h1r - wr*h2r + wi*h2i ;
	    xi = -h1i + wr*h2i + wi*h2r ;
	} else {
	    h1r =  c1*(x[i1] + x[i3] ) ;
	    h1i =  c1*(x[i2] - x[i4] ) ;
	    h2r = -c2*(x[i2] + x[i4] ) ;
	    h2i =  c2*(x[i1] - x[i3] ) ;
	    x[i1] =  h1r + wr*h2r - wi*h2i ;
	    x[i2] =  h1i + wr*h2i + wi*h2r ;
	    x[i3] =  h1r - wr*h2r + wi*h2i ;
	    x[i4] = -h1i + wr*h2i + wi*h2r ;
	}
	wr = (temp = wr)*wpr - wi*wpi + wr ;
	wi = wi*wpr + temp*wpi + wi ;
    }
    if ( forward )
	x[1] = xr ;
    else
	cfft( x, N, forward ) ;
}
/*
 * cfft replaces float array x containing NC complex values
 * (2*NC float values alternating real, imagininary, etc.)
 * by its Fourier transform if forward is true, or by its
 * inverse Fourier transform if forward is false, using a
 * recursive Fast Fourier transform method due to Danielson
 * and Lanczos.  NC MUST be a power of 2.
 */
cfft( x, NC, forward ) float x[] ; int NC, forward ; {
 float wr, wi, wpr, wpi, theta, scale ;
 int mmax, ND, m, i, j, delta ;
 void bitreverse();
 
    ND = NC<<1 ;
    bitreverse( x, ND ) ;
    for ( mmax = 2 ; mmax < ND ; mmax = delta ) {
	delta = mmax<<1 ;
	theta = TWOPI/( forward? mmax : -mmax ) ;
	wpr = -2.*pow( sin( 0.5*theta ), 2. ) ;
	wpi = sin( theta ) ;
	wr = 1. ;
	wi = 0. ;
	for ( m = 0 ; m < mmax ; m += 2 ) {
	 register float rtemp, itemp ;
	    for ( i = m ; i < ND ; i += delta ) {
		j = i + mmax ;
		rtemp = wr*x[j] - wi*x[j+1] ;
		itemp = wr*x[j+1] + wi*x[j] ;
		x[j] = x[i] - rtemp ;
		x[j+1] = x[i+1] - itemp ;
		x[i] += rtemp ;
		x[i+1] += itemp ;
	    }
	    wr = (rtemp = wr)*wpr - wi*wpi + wr ;
	    wi = wi*wpr + rtemp*wpi + wi ;
	}
    }
/*
 * scale output
 */
    scale = forward ? 1./ND : 2. ;
    { register float *xi=x, *xe=x+ND ;
	while ( xi < xe )
	    *xi++ *= scale ;
    }
}
/*
 * bitreverse places float array x containing N/2 complex values
 * into bit-reversed order
 */
bitreverse( x, N ) float x[] ; int N ; {
 float rtemp, itemp ;
 int i, j, m ;
    for ( i = j = 0 ; i < N ; i += 2, j += m ) {
	if ( j > i ) {
	    rtemp = x[j] ; itemp = x[j+1] ; /* complex exchange */
	    x[j] = x[i] ; x[j+1] = x[i+1] ;
	    x[i] = rtemp ; x[i+1] = itemp ;
	}
	for ( m = N>>1 ; m >= 2 && j >= m ; m >>= 1 )
	    j -= m ;
    }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.