1Q15 data to short or float (for FFT project)

14 Jul 2010

Greetings all!

I am trying to make an FFT audio spectrum analyzer (very similar to the projects already posted here).  I am using the FFT code written by Ivan Mellen to perform the FFT itself.

--> I understand that the code is designed for an input array using 1Q15 data format, and that it returns the FFT result in 1Q15 format as well.  I am currently using the MBed "ADC.read" command to sample the data [samples are in the range of  0.0 to 1.0, floating point].

1) How do I "format" the floating point data [0.0 to 1.0], to a 1Q15 format for the FFT function?

2) When I get the FFT results (in 1Q15 format), how do I return them to a floating point number (or unsigned int number)?

Thank you for your help!

14 Jul 2010

Hi Richard,

Not even sure what 1Q15 means, but I used adc.read and got the data into the mellen fft functions.

Are you using the Mellen real functions, or the real and imaginary input functions? For the real FFT here's what I did:

First of all on a timer interrupt we read the adc value into a buffer:

   float s;
   s = adc.read(p20);
   Buffer[Counter] = (s -2048)*16;
   Counter += 1;

Then when we're ready to do an FFT, copy the buffer into an input array for realFFT:

        #define MN 1024
        short x[MN];  // input array
        short y[MN+2];  // one extra element in input to last stage
        short m[MN+2];
       memcpy(x, Buffer, sizeof x);

Rather than using memcpy, you can use the mellen windowing function if you need to apply a window eg hamming to the fft:

Window16b_realxixo(Buffer,x,Hamming1024_16b,MN);

The output is still real / imaginary, easiest (quickest) to use the mellen magnitude function like this (rather than sqrt the sum of the squares of the parts by hand):

        magnitude16_16bIn(y,(MN/2));  //DC and FS/2 bins are real, but can be negative!
        m32=(unsigned int *) y;

if you're using real and imaginary FFT, you need to load your inputs into the real parts of the array:

        #define MN 1024 //Number of points
        short mx[MN*2]; // input data 16 bit, 4 byte aligned  x0r,x0i,x1r,x1i,....
        short my[MN*2]; // output data 16 bit,4 byte aligned  y0r,y0i,y1r,y1i,....
        for (int i=0;i<MN*2;i++) mx[i]=0;
        for (int i=0;i<MN;i=i+1)
            { mx[i*2]=Buffer[i];}

And again you'll need to calculate magnitudes either with mellen function or for example:

sqrt(float(   (my[i]*my[i])  +(my[i+1]*my[i+1])     ) )

Don't know if that's helpful.

James Cobb

10 Mar 2014

hey, i want to know why have you subtracted 2048 to read the adc values;