Question

I'm using Apples vDSP APIs to calculate the FFT of audio. However, my results (in amp[]) aren't symmetrical around N/2, which they should be, from my understanding of FFTs on real inputs?

In the below frame is an array[128] of floats containing the audio samples.

        int numSamples = 128;
        vDSP_Length log2n = log2f(numSamples);
        FFTSetup fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
        int nOver2 = numSamples/2;

        COMPLEX_SPLIT A;
        A.realp = (float *) malloc(nOver2*sizeof(float));
        A.imagp = (float *) malloc(nOver2*sizeof(float));

        vDSP_ctoz((COMPLEX*)frame, 2, &A, 1, nOver2);

        //Perform FFT using fftSetup and A
        //Results are returned in A
        vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);

        //Convert COMPLEX_SPLIT A result to float array to be returned
        float amp[numSamples];
        amp[0] = A.realp[0]/(numSamples*2);
        for(int i=1;i<numSamples;i++) {
            amp[i]=A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i];
            printf("%f ",amp[i]);
        }

If I put the same float array into an online FFT calculator I do get a symmetrical output. Am I doing something wrong above?

For some reason, most values in amp[] are around 0 to 1e-5, but I also get one huge value of about 1e23. I'm not doing any windowing here, just trying to get a basic FFT working initially.

I've attached a picture of the two FFT outputs, using the same data. You can see they are similar upto 64, although not by a constant scaling factor, so I'm not sure what they are different by. Then over 64 they are completely different.

enter image description here

Was it helpful?

Solution 2

To get symmetric results from strictly real inout to a basic FFT, your complex data input and output arrays have to be the same length as your FFT. You seem to be allocating and copying only half your data into the FFT input, which could be feeding non-real memory garbage to the FFT.

OTHER TIPS

Because the mathematical output of a real-to-complex FFT is symmetrical, there is no value in returning the second half. There is also no space for it in the array that is passed to vDSP_fft_zrip. So vDSP_fft_zrip returns only the first half (except for the special N/2 point, discussed below). The second half is usually not needed explicitly and, if it is, you can compute it easily from the first half.

The output of vDSP_fft_zrip when used for a forward (real to complex) transformation has the H0 output (which is purely real; its imaginary part is zero) in A.realp[0]. The HN/2 output (which is also purely real) is stored in A.imagp[0]. The remaining values Hi, for 0 < i < N/2, are stored normally in A.realp[i] and A.imagp[i].

Documentation explaining this is here, in the section “Data Packing for Real FFTs”.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top