Issue with FFT plugin - Inverse Transformation


#1

Hi, here are some lines of code which do not work. I generate a sinus, try to make a forward then inverse fft transform. The output signal is just noise.

void MainContentComponent::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
    jassert( bufferToFill.buffer->getNumSamples() == 512 );   

    int numSamples = bufferToFill.buffer->getNumSamples();

    float lTime = 0.f;
    for (int channel = 0; channel < 2; ++channel)
    {
        lTime = mTime;

        FFT lFFT(9, false);

        float    * fftData = new float[numSamples * 2];
        // fill the fft data with a sinusoidal signal.
        for(int i = 0; i < numSamples * 2; i++)
        {
            if(i < numSamples)
            {
                lTime += 0.09;
                fftData[i] = 0.1f * cos(lTime);
            }
            else{
                fftData[i] = 0;
            }
        }

        lFFT.performRealOnlyForwardTransform(fftData);
        lFFT.performRealOnlyInverseTransform(fftData);

        bufferToFill.buffer->copyFrom(channel, 0, fftData, numSamples);
    }

    mTime = lTime;
}

I am lost, please help.

Thank you,

Baptiste


#2

Sorry, I wrote crap. the name of the method "performRealOnlyForwardTransform()" misled me.

You're misunderstanding lFFT.performRealOnlyForwardTransform(fftData);

It's not about "real data" vs. "fake data" but the real part of complex numbers. To restore the spatial information from the frequency domain you need the frequencies AND the phase information, which is in the real part.

Try perform() http://www.juce.com/doc/classFFT#a7b0dc3e67e914be1e76af5e77f148f2d instead.

And there are several optimizations, like not allocating to much inside a loop...

Read also Jules' hints in FFT: http://www.juce.com/doc/classFFT#details on where to allocate the FFT class.

HTH
 


#3

Maybe, but anyway I tried using perform() directly and this time it seems like it is working.

I already tried today but maybe something went wrong because I still had issues.

Anyway, here is the working code:

void MainContentComponent::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
    jassert( bufferToFill.buffer->getNumSamples() == 512 );

    int numSamples = bufferToFill.buffer->getNumSamples();

    float lTime = 0.f;

    FFT lForwardFFT(9, false);
    FFT lReverseFFT(9, true);

    for (int channel = 0; channel < 2; ++channel)
    {
        lTime = mTime;

        FFT::Complex lTData[numSamples];
        FFT::Complex lSpectrumData[numSamples];

        for(int i = 0; i < numSamples; i++)
        {
            lTime += 0.19;

            lTData[i].r = cos(lTime);

            lTData[i].i = 0.f;
        }

        lForwardFFT.perform(lTData, lSpectrumData);
        lReverseFFT.perform(lSpectrumData, lTData);

        float lTDataReal[numSamples];

        for(int i = 0; i < numSamples; i++)
        {
            lTDataReal[i] = lTData[i].r / (float)numSamples; // the division part, I am not sure about it.
        }

        bufferToFill.buffer->copyFrom(channel, 0, lTDataReal, numSamples);
    }

    mTime = lTime;
}

FFT : spectral transformation basic example
#4

Nice, glad you made it :-)


#5

About the optimisations I agree : the FFT should be member of the class and etc.

And thanks anyway.