shithub: aacenc

ref: ad1f6640329462fbea9a63ee7ace7e1aabbd373f
dir: /rdft_spectrum2.c/

View raw version

/* rdft_spectrum.c by James Salsman 25 April 1999 for public domain */

/* spectrum( double *f, unsigned lg2n ):
   input f[0...2^lg2n-1] amplitudes, modified in-place;
   output f[0...2^(lg2n-1)-1] magnitudes (scaling depends on lg2n;
                                          f[0] ill-defined);
   complspectrum( double *f, unsigned lg2n ): same as above but
   f[2^(lg2n-1)+1...2^lg2n-1] are also phases in radians 
                                         (f[2^(lg2n-1)] meaningless.) */

/* computes a power spectrum using a real discrete Fourier transform,
   faster than a full FFT but not exactly a Hartley transform.  */

/* adapted from Joerg Arndt's code found around 
     http://www.spektracom.de/~arndt/joerg.html 
   in turn from Ron Mayer's 1988 Stanford project, and Ron credits 
   Bracewell, Hartley, Gauss, and Euler.  Don't forget Pappus, 
   Pythagoras, and Euclid! */

#include <math.h>  /* we need sqrt(), sin(), cos(), and atan2(),
   and we want the sincos(x,*cos) FP primitive, but if we can't 
   have that, we should use floor() and fmod(,) instead of cos() */

#include "rdft.h"
#include <rfftw.h>


void fftw_init(){
rdft_plan11=rfftw_create_plan(11,FFTW_REAL_TO_COMPLEX,FFTW_MEASURE);
rdft_plan8=rfftw_create_plan(8,FFTW_REAL_TO_COMPLEX,FFTW_MEASURE);
}

void fftw_destroy(){
rfftw_destroy_plan(rdft_plan11);
rfftw_destroy_plan(rdft_plan8);
}

void rdft( double *fr, unsigned lg2n ) 
/* real discrete Fourier transform; not recursive */
{
rfftw_plan rdft_plan;
double fo[lg2n];
fftw_init();
// FIXME: has to be placed elsewhere
switch(lg2n) {
    case 11: rfftw_one(rdft_plan11,fr,fo);
	break;
    case 8: rfftw_one(rdft_plan8,fr,fo);
	break;
    default: rdft_plan=rfftw_create_plan(lg2n,FFTW_REAL_TO_COMPLEX, 
		    FFTW_ESTIMATE);
	rfftw_one(rdft_plan,fr,fo);
	rfftw_destroy_plan(rdft_plan);
	printf("ERROR: rdft with size %i",lg2n);
}
	memcpy(fr,fo,sizeof(fr));
fftw_destroy();
/*FIXME: has to be placed elsewhere*/
}

void spectrum( double *f, unsigned lg2n )
/* magnitude power spectrum from rdft */
{
    const int n=(1<<lg2n), k=(n>>1); /* k=n/2 */
    int i, j;

    rdft(f, lg2n);
    
    for ( i=1,j=n-1; i<k; i++,j-- )
    {
        double a, b;

        a = f[i] + f[j];  /* real part */
        b = f[i] - f[j];  /* imag part */

        f[i] = sqrt(a*a + b*b); /* magnitude -- please note that the
                                         scaling depends on size n */
    }

    f[0]=sqrt(f[0]*f[0]+f[n/2]*f[n/2]);  /* ill-defined bin */
        /* Reciprocated division by zero precludes any meaning 
           of "0 Hz" so please avoid using the f[0] output! */
}

void complspectrum( double *f, unsigned lg2n )
/* polar complex power spectrum from rdft */
{
    const int n=(1<<lg2n), k=(n>>1); /* k=n/2 */
    int i, j;

    rdft(f, lg2n);
    
    for ( i=1,j=n-1; i<k; i++,j-- )
    {
        double a, b;

        a = f[i] + f[j];  /* real part */
        b = f[i] - f[j];  /* imag part */ 

        f[i] = sqrt(a*a + b*b); /* magnitude -- please note that the
                                         scaling depends on size n */
        /* complex part: phase */

		if (a != 0.0) f[j] = atan2(b, a); /* magnitude f[i] has phase f[n-i] */
                   else f[j] = 0.0;
    }

    f[0]=sqrt(f[0]*f[0]+f[n/2]*f[n/2]);  /* ill-defined bin */

    /* The corresponding phase, f[k], should really be set to 
       some kind of not-a-number value because it is completely 
       meaningless, instead of just tainted like f[0]. */
}

/* end of rdft_spectrum.c :jps 26 April 1999 */#include <rfftw.h>