Format For FFT Float Array


#1

Hi, I am looking at the JUCE FFT class, and was wondering in what format the array returned by FFT class function performRealOnlyForwardTransform returned the amplitude and phase components of the frequency bins.

The function performs the transformation on a float array twice the size of the number of samples to be processed and returns both the real and imaginary components.

Is this structured:

r, i, r, i, r, i, … where the real and imaginary components for each bin are adjacent
or r, r, r, r, …, i, i, i, i, … or where its all real, then all imaginary.

The documentation is unclear, and also conflicts with the actual juce_FFT.h file.


#2

I‘m pretty sure that it‘s r,i,r,i,r,i,… so that you can apply a reinterpret_cast<std::complex> to the results and use the complex numbers with all std::complex functions if needed.


#3

The format is r,i… for the default FFT implementation on Mac OS and Windows. I think the documentation is deliberately vague, to allow for the possibility of alternative implementations using other formats.

My synthesizer demo SARAH relies entirely on knowing the format, and you’ll find more details on my blog at http://getdunne.net/wiki/doku.php?id=sarah_oscillator_details.


#4

Okay, thanks. That makes sense.

I’ve also been trying to figure out how to use the perform method which uses the complex struct rather than a float array (that way of organizing the values makes way more sense to me). This one always seems to produce screaming feedback, even though I zero all the struct values out in my audioprocessor constructor.
Here is the declaration of the relevant variables in the .h:

FFT::Complex fftin[2048];
FFT::Complex fftout[2048];
FFT::Complex holdfft[2048];
FFT* fFFT;
FFT* iFFT;

Here is the constructor:

fFFT = new FFT(11, false); //2048 point fft
iFFT = new FFT(11, true); //2048 point fft
for(int i = 0; i < 2048; i++){
    fftin[i].r = fftin[i].i = 0;
    fftout[i].r = fftout[i].i = 0;
    holdfft[i].r = holdfft[i].i = 0;
}

Here is my processing:

    float* channelData = buffer.getWritePointer (channel);
    if(channel == 0){
        for(int i = 0; i < buffer.getNumSamples(); i++){
            if(fillIndex < 2048){
                fftin[fillIndex].r = channelData[i];
                channelData[i] = fftout[fillIndex].r;
                
                fillIndex++;
            }
            if(fillIndex == 2048){
                fillIndex = 0;
                fFFT->perform(fftin, holdfft);
                iFFT->perform(holdfft, fftout);

            }
        }
    }

Any idea what might be going on there?