This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem with IFFT realized on C28x FPU Library Beta1

 

Hello,

I try to use C28x FPU Library Beta1 for realize IFFT but get unexpected amtlitude changing.

 

Source signal


FFT results

 

IFFT results - example 1

 

IFFT results - example 2

Source code

namespace measure
{
    const Uint16 fftSize=8192;

    const Uint16 fftStages=13;
   
    RFFT_F32_STRUCT fft;
    RFFT_F32_STRUCT ifft;
   
    float32 bufferA[fftSize];
    float32 bufferB[fftSize];
    float32 bufferC[fftSize];

}

Calling on startup:

void measure::init(){
    fft.InBuf=bufferA;
    fft.OutBuf=bufferB;
    fft.CosSinBuf=bufferC;
    fft.MagBuf=fft.InBuf;
    fft.FFTSize=fftSize;
    fft.FFTStages=fftStages;   
   
    ifft.InBuf=fft.OutBuf;
    ifft.OutBuf=fft.InBuf;
    ifft.CosSinBuf=fft.CosSinBuf;
    ifft.MagBuf=ifft.InBuf; 
    ifft.FFTSize=fftSize;
    ifft.FFTStages=fftStages;   
   
    RFFT_f32_sincostable(&fft);
}

And try to do FFT and IFFT:

         RFFT_f32u(&fft);
         RFFT_f32u(&ifft);

May be cause is difference between real FFT and complex FFT, may be in something else. I don't know exactly how do IFFT with real FFT algorithm. Anybody do IFFT with C28x FPU Library Beta1?

 

  • Hi,

    There are two things why this won't work

    -You will need a complex FFT to do the IFFT. Because your trying to place imaginaire data in the real FFT.
    - You need mirror the imaginaire part.

    (1)

    You can use the Real FFT to do IFFT, but you have to the following steps

    --Split--

        Re[0] = fft.OutBuf[0];
        Im[0] = 0;
        for (i=1; i<(FFTsize/2+1);i++)
        {
            Re[i]           =  fft.OutBuf[i];          // split real
            Im[i]           =  fft.OutBuf[FFTsize-i];  // split imag
        }
        Im[FFTsize/2] = 0;

    ----

    ---combine and split imag/real---

        for(i=0; i< FFTsize/2;i++)
        {
            tempR = Re[i] - Im[i];
            tempI = Re[i]] + Im[i];

            Re[i] = tempR; //can also be done in one step
            Im[i] = tempI;
        }

     

    --mirror---

     // ************* mirror ***************
        for (i=0; i<(FFTsize/2);i++)
        {
            Re[FFTsize-1-i] =   Re[i+1];
            Im[FFTsize-1-i] = - Im[i+1];
        }
        // ************ add *******************
        for (i=0; i<FFTsize;i++)
        {
            fft.InBuf[i] = Re[i] - Im[i];
        }

     

    And now you can do the FFT again to get the IFFT

    After this, you will need to the Split, Mirror routine again

    The last step is to divide the all the result by [fftSize]

    Greetings,

    Leo

     

     

     

     

  • Thanks, Leo. It's realy helpful.

    I optimize you code for pre-IFFT computation and I need to change last "add" section for post-IFFT computation. And IFFT result is shifted for 3 samples rigth from source signal.

    This is my code:

      RFFT_f32u(&fft1);
      
        for (int16 i=0; i<fftSize/2; i++){
            ifft.InBuf[i]=-2*fft1.OutBuf[fftSize-i];
            ifft.InBuf[fftSize-1-i]=2*fft1.OutBuf[i+1];
        }
        ifft.InBuf[0]=0;
        ifft.InBuf[fftSize/2]=fft1.OutBuf[fftSize/2];
          
        RFFT_f32u(&ifft);
           
    // Split   
        Re[0] = ifft.OutBuf[0];
        Im[0] = 0;
        for (int16 i=1; i<(fftSize/2+1); i++) {
            Re[i] = ifft.OutBuf[i];            // split real
            Im[i] = ifft.OutBuf[fftSize-i]; // split imag
        }
        Im[fftSize/2] = 0;
    // Combine and split imag/real
        for(int16 i=0; i<fftSize/2; i++){
            tempR = Re[i]-Im[i];
            tempI = Re[i]+Im[i];
            Re[i] = tempR; //can also be done in one step
            Im[i] = tempI;
        }

    // Mirror
        for (int16 i=0; i<(fftSize/2); i++){
            Re[fftSize-1-i] = Re[i+1];
            Im[fftSize-1-i] = -Im[i+1];
        }
        // Modifed
        for (int16 i=0; i<fftSize/2+1; i++) fft2.InBuf[i] = Re[i]/fftSize;
        for (int16 i=fftSize/2+1; i<fftSize; i++) fft2.InBuf[i] = -Im[i]/fftSize;

  • Sorry, but I can't make your and Leo's code working! RFFT_f32u(&fft1); Gives roght results(double check with KISS FFT results) But inverse FFT does not gives expecting results. First my approach was to take FFT first from real part then from imaging and "mix" results together, but then I have to do two FFTs. Your code using only one FFT to implement IFFT and is more interesting in performance aspect. Could you attach some comments to code. What is the goal of each operations like Split, Combine and split imag/real, Mirror.... In other words, HOW do we get REAL from complex?
  • Uf, I don't going this way now. I don't undestand theoretic side of this code and can't get complex IFFT output. I get solution with other code (sourcesdocumentation in Russian) witch used complex arithmetic.   

  • >I get solution with other code (sources, documentation in Russian) witch used complex arithmetic.

    C28x FPU Library RFFT is much more efficient then pure C realizations of FFT algo. I think pure C is not interested for using in real applications, where performance and efficiency of algorithm is often goes on the foreground.

     

    See attachment. Full theory with working code plus assembler optimization is provided.

    Idea and code is successfully used in my own Speex port for C28335 DSP  and was copy-paste with some edition after it to remove Speex specific code. Like malloc() instead of speex_alloc(), float * instead of  spx_word16_t *  and so on....

    I did not build and test the code after edition, but I do it before. So I think it will be easy to fix if there is some minor errors in the code(here I mean syntax errors, not logic / algorithmic errors).

    IFFT.zip