/search.css" rel="stylesheet" type="text/css"/> /search.js">
Functions
DSPLIB - Transforms
Basic

Functions

void dsp16_trans_complexfft (dsp16_complex_t *vect1, dsp16_complex_t *vect2, int nlog)
 16-bit fixed point version of the complex FFT algorithm.
void dsp16_trans_complexifft (dsp16_complex_t *vect1, dsp16_complex_t *vect2, int nlog)
 16-bit fixed point version of the complex iFFT algorithm.
void dsp16_trans_realcomplexfft (dsp16_complex_t *vect1, dsp16_t *vect2, int nlog)
 16-bit fixed point version of the real to complex FFT algorithm.
void dsp32_trans_realcomplexfft (dsp32_complex_t *vect1, dsp32_t *vect2, int nlog)
 32-bit fixed point version of the real to complex FFT algorithm.

Detailed Description

All the transforms functions currently supported by the DSP library.

Complex Fast Fourier Transform

This function computes a complex FFT from an input signal. It uses the Radix-4 "Decimate In Time" algorithm and does not perform a calculation "in place" which means that the input buffer has to be different from the output buffer.
Here is the formula of the FFT:

transforms_fft_equation.gif

Relative functions:


Complex inverse Fast Fourier Transform

This function computes a complex inverse FFT from an input signal. It uses the Radix-4 "Decimate In Time" algorithm and does not perform a calculation "in place" which means that the input buffer has to be different from the output buffer.
Here is the formula of the iFFT:

transforms_ifft_equation.gif

Relative functions:


Real to complex Fast Fourier Transform

This function computes a complex FFT from a real input signal. It uses the Radix-4 "Decimate In Time" algorithm and does not perform a calculation "in place" which means that the input buffer has to be different from the output buffer.
Here is the formula of the FFT:

transforms_fft_equation.gif

Relative functions:



Function Documentation

void dsp16_trans_complexfft ( dsp16_complex_t vect1,
dsp16_complex_t vect2,
int  nlog 
)

16-bit fixed point version of the complex FFT algorithm.

Parameters:
vect1A pointer on a 16-bit complex vector which is the output buffer of this function.
vect2A pointer on a 16-bit complex vector which is the input buffer of this function.
nlogIt is the base-2-logarithm of the size of the input/output vector.
Due to its implementation, this function computes only 4^n-point complex FFT. Therefore, the nlog argument has to be even.
Note:
The following requirements have to be matched:
  • The size of the output buffer has to be the same as the size of the input buffer.
  • This function uses a static twiddle factors table which determines the maximal FFT size which can be performed. By default it is 1024. Please check the value of DSP16_N_TWIDDLE_FACTORS.
  • vect1 and vect2 MUST be 4-byte aligned. Please use A_ALIGNED to do so.
  • To avoid overflowing values, the resulting vector amplitude is scaled by 2^nlog.

Definition at line 72 of file trans_dsp16_complex_fft.c.

References DSP16_N_TWIDDLE_FACTORS, DSP16_QB, dsp16_twiddle_factors, dsp16_twiddle_factors2, dsp16_complex_t::imag, and dsp16_complex_t::real.

{
  int size;
  int m;
  int stage, j, r, indice, inc_indice, r_brev, r_temp;
  dsp16_t e_real, e_imag, e2_real, e2_imag, e3_real, e3_imag;
  dsp16_t temp;
  int i0, i1, i2, i3;
  dsp32_t a0_real, a0_imag, a1_real, a1_imag, a2_real, a2_imag, a3_real, a3_imag;

  size = 1 << nlog;

  for(r=0; r<size; r += 4)
  {
    r_brev = 0;
    r_temp = r;
    for(j=0; j<nlog; j++)
    {
      r_brev <<= 1;
      if (r_temp & 1)
        r_brev |= 1;
      r_temp >>= 1;
    }

    a0_real = vect2[r_brev].real;
    a0_imag = vect2[r_brev].imag;
    r_brev += size >> 2;
    a1_real = vect2[r_brev].real;
    a1_imag = vect2[r_brev].imag;
    r_brev += size >> 2;
    a2_real = vect2[r_brev].real;
    a2_imag = vect2[r_brev].imag;
    r_brev += size >> 2;
    a3_real = vect2[r_brev].real;
    a3_imag = vect2[r_brev].imag;

    vect1[r].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
    vect1[r].imag = (a0_imag + a2_imag + a1_imag + a3_imag) >> 2;
    vect1[r + 2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
    vect1[r + 2].imag = (a0_imag + a2_imag - a1_imag - a3_imag) >> 2;

    vect1[r + 1].real = (a0_real - a2_real + a1_imag - a3_imag) >> 2;
    vect1[r + 1].imag = (a0_imag - a2_imag - a1_real + a3_real) >> 2;
    vect1[r + 3].real = (a0_real - a2_real - a1_imag + a3_imag) >> 2;
    vect1[r + 3].imag = (a0_imag - a2_imag + a1_real - a3_real) >> 2;
  }

  m = 4;
  inc_indice = (DSP16_N_TWIDDLE_FACTORS/8);
  for(stage=4; stage <= nlog; stage+=2)
  {
    m <<= 2;

    indice = 0;

    for(r=0; r<size; r += m)
    {
      i0 = r;
      i1 = i0 + (m >> 2);
      i2 = i1 + (m >> 2);
      i3 = i2 + (m >> 2);

      a0_real = vect1[i0].real;
      a0_imag = vect1[i0].imag;
      a1_real = vect1[i2].real;
      a1_imag = vect1[i2].imag;
      a2_real = vect1[i1].real;
      a2_imag = vect1[i1].imag;
      a3_real = vect1[i3].real;
      a3_imag = vect1[i3].imag;

      vect1[i0].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
      vect1[i0].imag = (a0_imag + a2_imag + a1_imag + a3_imag) >> 2;
      vect1[i2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
      vect1[i2].imag = (a0_imag + a2_imag - a1_imag - a3_imag) >> 2;

      vect1[i1].real = (a0_real - a2_real + a1_imag - a3_imag) >> 2;
      vect1[i1].imag = (a0_imag - a2_imag - a1_real + a3_real) >> 2;
      vect1[i3].real = (a0_real - a2_real - a1_imag + a3_imag) >> 2;
      vect1[i3].imag = (a0_imag - a2_imag + a1_real - a3_real) >> 2;
    }

    for(j=1; j<(m >> 2); j++)
    {
      indice += inc_indice;

      //  e = exp(1.0*j*-2*PI*%i/m);
      e_real = dsp16_twiddle_factors[indice];
      e_imag = dsp16_twiddle_factors[indice + 1];

#if DSP_OPTIMIZATION & DSP_OPTI_SIZE
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      if (indice >= DSP16_N_TWIDDLE_FACTORS/4)
      {
        r = DSP16_N_TWIDDLE_FACTORS - (indice << 1);
        e2_real = -dsp16_twiddle_factors[r];
        e2_imag = dsp16_twiddle_factors[r + 1];

        if (r < DSP16_N_TWIDDLE_FACTORS/3)
        {
          r = indice - r;
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = -dsp16_twiddle_factors[r + 1];
        }
        else
        {
          r -= indice;
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
      }
      else
      {
        r = indice << 1;
        e2_real = dsp16_twiddle_factors[r];
        e2_imag = dsp16_twiddle_factors[r + 1];

        if (r >= DSP16_N_TWIDDLE_FACTORS/3)
        {
          r = DSP16_N_TWIDDLE_FACTORS - (indice + r);
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
        else
        {
          r += indice;
          e3_real = dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
      }

#else
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      e2_real = dsp16_twiddle_factors2[indice*2];
      e2_imag = dsp16_twiddle_factors2[indice*2 + 1];

      //  e3 = exp(3.0*j*-2*PI*%i/m);
      e3_real = dsp16_twiddle_factors2[indice*2 + 2];
      e3_imag = dsp16_twiddle_factors2[indice*2 + 3];
#endif

      for(r=0; r<size; r += m)
      {
        i0 = j + r;
        i1 = i0 + (m >> 2);
        i2 = i1 + (m >> 2);
        i3 = i2 + (m >> 2);

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY
        a0_real = vect1[i0].real;
        a0_imag = vect1[i0].imag;
#else
        a0_real = vect1[i0].real >> 2;
        a0_imag = vect1[i0].imag >> 2;
#endif

        a1_real = vect1[i2].real;
        a1_imag = vect1[i2].imag;
        a2_real = vect1[i1].real;
        a2_imag = vect1[i1].imag;
        a3_real = vect1[i3].real;
        a3_imag = vect1[i3].imag;

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY

        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP16_QB);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP16_QB);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP16_QB);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP16_QB);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP16_QB);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP16_QB);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real)) >> 2;
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag)) >> 2;
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real)) >> 2;
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag)) >> 2;

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag)) >> 2;
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real)) >> 2;
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag)) >> 2;
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real)) >> 2;
#else
        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP16_QB + 1);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP16_QB + 1);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP16_QB + 1);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP16_QB + 1);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP16_QB + 1);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP16_QB + 1);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real));
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag));
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real));
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag));

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag));
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real));
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag));
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real));
#endif
      }
    }
    inc_indice >>= 2;
  }
}
void dsp16_trans_complexifft ( dsp16_complex_t vect1,
dsp16_complex_t vect2,
int  nlog 
)

16-bit fixed point version of the complex iFFT algorithm.

Parameters:
vect1A pointer on a 16-bit complex vector which is the output buffer of this function.
vect2A pointer on a 16-bit complex vector which is the input buffer of this function.
nlogIt is the base-2-logarithm of the size of the input/output vector.
Due to its implementation, this function computes only 4^n-point complex iFFT. Therefore, the nlog argument has to be even.
Note:
The following requirements have to be matched:
  • The size of the output buffer has to be the same as the size of the input buffer.
  • This function uses a static twiddle factors table which determines the maximal FFT size which can be performed. By default it is 1024. Please check the value of DSP16_N_TWIDDLE_FACTORS.
  • vect1 and vect2 MUST be 4-byte aligned. Please use A_ALIGNED to do so.
  • To avoid overflowing values, the resulting vector amplitude is scaled by 2^nlog.

Definition at line 72 of file trans_dsp16_complex_ifft.c.

References DSP16_N_TWIDDLE_FACTORS, DSP16_QB, dsp16_twiddle_factors, dsp16_twiddle_factors2, dsp16_vect_complex_conj(), dsp16_complex_t::imag, and dsp16_complex_t::real.

{
  int size;
  int m;
  int stage, j, r, indice, inc_indice, r_brev, r_temp;
  dsp16_t e_real, e_imag, e2_real, e2_imag, e3_real, e3_imag;
  dsp16_t temp;
  int i0, i1, i2, i3;
  dsp32_t a0_real, a0_imag, a1_real, a1_imag, a2_real, a2_imag, a3_real, a3_imag;

  size = 1 << nlog;

  for(r=0; r<size; r += 4)
  {
    r_brev = 0;
    r_temp = r;
    for(j=0; j<nlog; j++)
    {
      r_brev <<= 1;
      if (r_temp & 1)
        r_brev |= 1;
      r_temp >>= 1;
    }

    a0_real = vect2[r_brev].imag;
    a0_imag = vect2[r_brev].real;
    r_brev += size >> 2;
    a1_real = vect2[r_brev].imag;
    a1_imag = vect2[r_brev].real;
    r_brev += size >> 2;
    a2_real = vect2[r_brev].imag;
    a2_imag = vect2[r_brev].real;
    r_brev += size >> 2;
    a3_real = vect2[r_brev].imag;
    a3_imag = vect2[r_brev].real;

    vect1[r].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
    vect1[r].imag = (a0_imag + a2_imag + a1_imag + a3_imag) >> 2;
    vect1[r + 2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
    vect1[r + 2].imag = (a0_imag + a2_imag - a1_imag - a3_imag) >> 2;

    vect1[r + 1].real = (a0_real - a2_real + a1_imag - a3_imag) >> 2;
    vect1[r + 1].imag = (a0_imag - a2_imag - a1_real + a3_real) >> 2;
    vect1[r + 3].real = (a0_real - a2_real - a1_imag + a3_imag) >> 2;
    vect1[r + 3].imag = (a0_imag - a2_imag + a1_real - a3_real) >> 2;
  }

  m = 4;
  inc_indice = (DSP16_N_TWIDDLE_FACTORS/8);
  for(stage=4; stage <= nlog; stage+=2)
  {
    m <<= 2;

    indice = 0;

    for(r=0; r<size; r += m)
    {
      i0 = r;
      i1 = i0 + (m >> 2);
      i2 = i1 + (m >> 2);
      i3 = i2 + (m >> 2);

      a0_real = vect1[i0].real;
      a0_imag = vect1[i0].imag;
      a1_real = vect1[i2].real;
      a1_imag = vect1[i2].imag;
      a2_real = vect1[i1].real;
      a2_imag = vect1[i1].imag;
      a3_real = vect1[i3].real;
      a3_imag = vect1[i3].imag;

      vect1[i0].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
      vect1[i0].imag = (a0_imag + a2_imag + a1_imag + a3_imag) >> 2;
      vect1[i2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
      vect1[i2].imag = (a0_imag + a2_imag - a1_imag - a3_imag) >> 2;

      vect1[i1].real = (a0_real - a2_real + a1_imag - a3_imag) >> 2;
      vect1[i1].imag = (a0_imag - a2_imag - a1_real + a3_real) >> 2;
      vect1[i3].real = (a0_real - a2_real - a1_imag + a3_imag) >> 2;
      vect1[i3].imag = (a0_imag - a2_imag + a1_real - a3_real) >> 2;
    }

    for(j=1; j<(m >> 2); j++)
    {
      indice += inc_indice;

      //  e = exp(1.0*j*-2*PI*%i/m);
      e_real = dsp16_twiddle_factors[indice];
      e_imag = dsp16_twiddle_factors[indice + 1];

#if DSP_OPTIMIZATION & DSP_OPTI_SIZE
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      if (indice >= DSP16_N_TWIDDLE_FACTORS/4)
      {
        r = DSP16_N_TWIDDLE_FACTORS - (indice << 1);
        e2_real = -dsp16_twiddle_factors[r];
        e2_imag = dsp16_twiddle_factors[r + 1];

        if (r < DSP16_N_TWIDDLE_FACTORS/3)
        {
          r = indice - r;
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = -dsp16_twiddle_factors[r + 1];
        }
        else
        {
          r -= indice;
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
      }
      else
      {
        r = indice << 1;
        e2_real = dsp16_twiddle_factors[r];
        e2_imag = dsp16_twiddle_factors[r + 1];

        if (r >= DSP16_N_TWIDDLE_FACTORS/3)
        {
          r = DSP16_N_TWIDDLE_FACTORS - (indice + r);
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
        else
        {
          r += indice;
          e3_real = dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
      }

#else
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      e2_real = dsp16_twiddle_factors2[indice*2];
      e2_imag = dsp16_twiddle_factors2[indice*2 + 1];

      //  e3 = exp(3.0*j*-2*PI*%i/m);
      e3_real = dsp16_twiddle_factors2[indice*2 + 2];
      e3_imag = dsp16_twiddle_factors2[indice*2 + 3];
#endif

      for(r=0; r<size; r += m)
      {
        i0 = j + r;
        i1 = i0 + (m >> 2);
        i2 = i1 + (m >> 2);
        i3 = i2 + (m >> 2);

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY
        a0_real = vect1[i0].real;
        a0_imag = vect1[i0].imag;
#else
        a0_real = vect1[i0].real >> 2;
        a0_imag = vect1[i0].imag >> 2;
#endif

        a1_real = vect1[i2].real;
        a1_imag = vect1[i2].imag;
        a2_real = vect1[i1].real;
        a2_imag = vect1[i1].imag;
        a3_real = vect1[i3].real;
        a3_imag = vect1[i3].imag;

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY

        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP16_QB);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP16_QB);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP16_QB);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP16_QB);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP16_QB);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP16_QB);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real)) >> 2;
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag)) >> 2;
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real)) >> 2;
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag)) >> 2;

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag)) >> 2;
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real)) >> 2;
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag)) >> 2;
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real)) >> 2;

#else

        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP16_QB + 1);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP16_QB + 1);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP16_QB + 1);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP16_QB + 1);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP16_QB + 1);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP16_QB + 1);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real));
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag));
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real));
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag));

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag));
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real));
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag));
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real));

#endif
      }
    }
    inc_indice >>= 2;
  }

  dsp16_vect_complex_conj(vect1, vect1, size);
}
void dsp16_trans_realcomplexfft ( dsp16_complex_t vect1,
dsp16_t vect2,
int  nlog 
)

16-bit fixed point version of the real to complex FFT algorithm.

Parameters:
vect1A pointer on a 16-bit complex vector which is the output buffer of this function.
vect2A pointer on a 16-bit real vector which is the input buffer of this function.
nlogIt is the base-2-logarithm of the size of the input/output vector.
Due to its implementation, this function computes only 4^n-point complex FFT. Therefore, the nlog argument has to be even.
Note:
The following requirements have to be matched:
  • The size of the output buffer has to be the same as the size of the input buffer.
  • This function uses a static twiddle factors table which determines the maximal FFT size which can be performed. By default it is 1024. Please check the value of DSP16_N_TWIDDLE_FACTORS.
  • vect1 and vect2 MUST be 4-byte aligned. Please use A_ALIGNED to do so.
  • To avoid overflowing values, the resulting vector amplitude is scaled by 2^nlog.

Definition at line 52 of file trans_dsp16_realcomplex_fft.c.

References DSP16_N_TWIDDLE_FACTORS, DSP16_QB, dsp16_twiddle_factors, dsp16_twiddle_factors2, dsp16_complex_t::imag, and dsp16_complex_t::real.

Referenced by main().

{
  int size;
  int m;
  int stage, j, r, indice, inc_indice, r_brev, r_temp;
  dsp16_t e_real, e_imag, e2_real, e2_imag, e3_real, e3_imag;
  dsp16_t temp;
  int i0, i1, i2, i3;
  dsp32_t a0_real, a0_imag, a1_real, a1_imag, a2_real, a2_imag, a3_real, a3_imag;

  size = 1 << nlog;

  for(r=0; r<size; r += 4)
  {
    r_brev = 0;
    r_temp = r;
    for(j=0; j<nlog; j++)
    {
      r_brev <<= 1;
      if (r_temp & 1)
        r_brev |= 1;
      r_temp >>= 1;
    }

    a0_real = vect2[r_brev];
    r_brev += size >> 2;
    a1_real = vect2[r_brev];
    r_brev += size >> 2;
    a2_real = vect2[r_brev];
    r_brev += size >> 2;
    a3_real = vect2[r_brev];

    vect1[r].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
    vect1[r].imag = 0;
    vect1[r + 2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
    vect1[r + 2].imag = 0;

    vect1[r + 1].real = (a0_real - a2_real) >> 2;
    vect1[r + 1].imag = (-a1_real + a3_real) >> 2;
    vect1[r + 3].real = (a0_real - a2_real) >> 2;
    vect1[r + 3].imag = (a1_real - a3_real) >> 2;
  }

  m = 4;
  inc_indice = (DSP16_N_TWIDDLE_FACTORS/8);
  for(stage=4; stage <= nlog; stage+=2)
  {
    m <<= 2;

    indice = 0;

    for(r=0; r<size; r += m)
    {
      i0 = r;
      i1 = i0 + (m >> 2);
      i2 = i1 + (m >> 2);
      i3 = i2 + (m >> 2);

      a0_real = vect1[i0].real;
      a0_imag = vect1[i0].imag;
      a1_real = vect1[i2].real;
      a1_imag = vect1[i2].imag;
      a2_real = vect1[i1].real;
      a2_imag = vect1[i1].imag;
      a3_real = vect1[i3].real;
      a3_imag = vect1[i3].imag;

      vect1[i0].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
      vect1[i0].imag = (a0_imag + a2_imag + a1_imag + a3_imag) >> 2;
      vect1[i2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
      vect1[i2].imag = (a0_imag + a2_imag - a1_imag - a3_imag) >> 2;

      vect1[i1].real = (a0_real - a2_real + a1_imag - a3_imag) >> 2;
      vect1[i1].imag = (a0_imag - a2_imag - a1_real + a3_real) >> 2;
      vect1[i3].real = (a0_real - a2_real - a1_imag + a3_imag) >> 2;
      vect1[i3].imag = (a0_imag - a2_imag + a1_real - a3_real) >> 2;
    }

    for(j=1; j<(m >> 2); j++)
    {
      indice += inc_indice;

      //  e = exp(1.0*j*-2*PI*%i/m);
      e_real = dsp16_twiddle_factors[indice];
      e_imag = dsp16_twiddle_factors[indice + 1];

#if DSP_OPTIMIZATION & DSP_OPTI_SIZE
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      if (indice >= DSP16_N_TWIDDLE_FACTORS/4)
      {
        r = DSP16_N_TWIDDLE_FACTORS - (indice << 1);
        e2_real = -dsp16_twiddle_factors[r];
        e2_imag = dsp16_twiddle_factors[r + 1];

        if (r < DSP16_N_TWIDDLE_FACTORS/3)
        {
          r = indice - r;
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = -dsp16_twiddle_factors[r + 1];
        }
        else
        {
          r -= indice;
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
      }
      else
      {
        r = indice << 1;
        e2_real = dsp16_twiddle_factors[r];
        e2_imag = dsp16_twiddle_factors[r + 1];

        if (r >= DSP16_N_TWIDDLE_FACTORS/3)
        {
          r = DSP16_N_TWIDDLE_FACTORS - (indice + r);
          e3_real = -dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
        else
        {
          r += indice;
          e3_real = dsp16_twiddle_factors[r];
          e3_imag = dsp16_twiddle_factors[r + 1];
        }
      }

#else
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      e2_real = dsp16_twiddle_factors2[indice*2];
      e2_imag = dsp16_twiddle_factors2[indice*2 + 1];

      //  e3 = exp(3.0*j*-2*PI*%i/m);
      e3_real = dsp16_twiddle_factors2[indice*2 + 2];
      e3_imag = dsp16_twiddle_factors2[indice*2 + 3];
#endif

      for(r=0; r<size; r += m)
      {
        i0 = j + r;
        i1 = i0 + (m >> 2);
        i2 = i1 + (m >> 2);
        i3 = i2 + (m >> 2);

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY
        a0_real = vect1[i0].real;
        a0_imag = vect1[i0].imag;
#else
        a0_real = vect1[i0].real >> 2;
        a0_imag = vect1[i0].imag >> 2;
#endif

        a1_real = vect1[i2].real;
        a1_imag = vect1[i2].imag;
        a2_real = vect1[i1].real;
        a2_imag = vect1[i1].imag;
        a3_real = vect1[i3].real;
        a3_imag = vect1[i3].imag;

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY

        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP16_QB);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP16_QB);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP16_QB);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP16_QB);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP16_QB);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP16_QB);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real)) >> 2;
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag)) >> 2;
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real)) >> 2;
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag)) >> 2;

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag)) >> 2;
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real)) >> 2;
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag)) >> 2;
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real)) >> 2;
#else
        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP16_QB + 1);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP16_QB + 1);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP16_QB + 1);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP16_QB + 1);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP16_QB + 1);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP16_QB + 1);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real));
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag));
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real));
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag));

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag));
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real));
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag));
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real));
#endif
      }
    }
    inc_indice >>= 2;
  }
}
void dsp32_trans_realcomplexfft ( dsp32_complex_t vect1,
dsp32_t vect2,
int  nlog 
)

32-bit fixed point version of the real to complex FFT algorithm.

Parameters:
vect1A pointer on a 32-bit complex vector which is the output buffer of this function.
vect2A pointer on a 32-bit real vector which is the input buffer of this function.
nlogIt is the base-2-logarithm of the size of the input/output vector.
Due to its implementation, this function computes only 4^n-point complex FFT. Therefore, the nlog argument has to be even.
Note:
The following requirements have to be matched:
  • The size of the output buffer has to be the same as the size of the input buffer.
  • This function uses a static twiddle factors table which determines the maximal FFT size which can be performed. By default it is 1024. Please check the value of DSP32_N_TWIDDLE_FACTORS.
  • vect1 and vect2 MUST be 4-byte aligned. Please use A_ALIGNED to do so.
  • To avoid overflowing values, the resulting vector amplitude is scaled by 2^nlog.

Definition at line 51 of file trans_dsp32_realcomplex_fft.c.

References DSP32_N_TWIDDLE_FACTORS, DSP32_QB, dsp32_twiddle_factors, dsp32_twiddle_factors2, dsp32_complex_t::imag, and dsp32_complex_t::real.

{
  int size;
  int m;
  int stage, j, r, indice, inc_indice, r_brev, r_temp;
  dsp32_t e_real, e_imag, e2_real, e2_imag, e3_real, e3_imag;
  dsp32_t temp;
  int i0, i1, i2, i3;
    // 64-bit type
  long long a0_real, a0_imag, a1_real, a1_imag, a2_real, a2_imag, a3_real, a3_imag;

  size = 1 << nlog;

  for(r=0; r<size; r += 4)
  {
    r_brev = 0;
    r_temp = r;
    for(j=0; j<nlog; j++)
    {
      r_brev <<= 1;
      if (r_temp & 1)
        r_brev |= 1;
      r_temp >>= 1;
    }

    a0_real = vect2[r_brev];
    r_brev += size >> 2;
    a1_real = vect2[r_brev];
    r_brev += size >> 2;
    a2_real = vect2[r_brev];
    r_brev += size >> 2;
    a3_real = vect2[r_brev];

    vect1[r].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
    vect1[r].imag = 0;
    vect1[r + 2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
    vect1[r + 2].imag = 0;

    vect1[r + 1].real = (a0_real - a2_real) >> 2;
    vect1[r + 1].imag = (-a1_real + a3_real) >> 2;
    vect1[r + 3].real = (a0_real - a2_real) >> 2;
    vect1[r + 3].imag = (a1_real - a3_real) >> 2;
  }

  m = 4;
  inc_indice = (DSP32_N_TWIDDLE_FACTORS/8);
  for(stage=4; stage <= nlog; stage+=2)
  {
    m <<= 2;

    indice = 0;

    for(r=0; r<size; r += m)
    {
      i0 = r;
      i1 = i0 + (m >> 2);
      i2 = i1 + (m >> 2);
      i3 = i2 + (m >> 2);

      a0_real = vect1[i0].real;
      a0_imag = vect1[i0].imag;
      a1_real = vect1[i2].real;
      a1_imag = vect1[i2].imag;
      a2_real = vect1[i1].real;
      a2_imag = vect1[i1].imag;
      a3_real = vect1[i3].real;
      a3_imag = vect1[i3].imag;

      vect1[i0].real = (a0_real + a2_real + a1_real + a3_real) >> 2;
      vect1[i0].imag = (a0_imag + a2_imag + a1_imag + a3_imag) >> 2;
      vect1[i2].real = (a0_real + a2_real - a1_real - a3_real) >> 2;
      vect1[i2].imag = (a0_imag + a2_imag - a1_imag - a3_imag) >> 2;

      vect1[i1].real = (a0_real - a2_real + a1_imag - a3_imag) >> 2;
      vect1[i1].imag = (a0_imag - a2_imag - a1_real + a3_real) >> 2;
      vect1[i3].real = (a0_real - a2_real - a1_imag + a3_imag) >> 2;
      vect1[i3].imag = (a0_imag - a2_imag + a1_real - a3_real) >> 2;
    }

    for(j=1; j<(m >> 2); j++)
    {
      indice += inc_indice;

      //  e = exp(1.0*j*-2*PI*%i/m);
      e_real = dsp32_twiddle_factors[indice];
      e_imag = dsp32_twiddle_factors[indice + 1];

#if DSP_OPTIMIZATION & DSP_OPTI_SIZE
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      if (indice >= DSP32_N_TWIDDLE_FACTORS/4)
      {
        r = DSP32_N_TWIDDLE_FACTORS - (indice << 1);
        e2_real = -dsp32_twiddle_factors[r];
        e2_imag = dsp32_twiddle_factors[r + 1];

        if (r < DSP32_N_TWIDDLE_FACTORS/3)
        {
          r = indice - r;
          e3_real = -dsp32_twiddle_factors[r];
          e3_imag = -dsp32_twiddle_factors[r + 1];
        }
        else
        {
          r -= indice;
          e3_real = -dsp32_twiddle_factors[r];
          e3_imag = dsp32_twiddle_factors[r + 1];
        }
      }
      else
      {
        r = indice << 1;
        e2_real = dsp32_twiddle_factors[r];
        e2_imag = dsp32_twiddle_factors[r + 1];

        if (r >= DSP32_N_TWIDDLE_FACTORS/3)
        {
          r = DSP32_N_TWIDDLE_FACTORS - (indice + r);
          e3_real = -dsp32_twiddle_factors[r];
          e3_imag = dsp32_twiddle_factors[r + 1];
        }
        else
        {
          r += indice;
          e3_real = dsp32_twiddle_factors[r];
          e3_imag = dsp32_twiddle_factors[r + 1];
        }
      }

#else
      //  e2 = exp(2.0*j*-2*PI*%i/m);
      e2_real = dsp32_twiddle_factors2[indice*2];
      e2_imag = dsp32_twiddle_factors2[indice*2 + 1];

      //  e3 = exp(3.0*j*-2*PI*%i/m);
      e3_real = dsp32_twiddle_factors2[indice*2 + 2];
      e3_imag = dsp32_twiddle_factors2[indice*2 + 3];
#endif

      for(r=0; r<size; r += m)
      {
        i0 = j + r;
        i1 = i0 + (m >> 2);
        i2 = i1 + (m >> 2);
        i3 = i2 + (m >> 2);

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY
        a0_real = vect1[i0].real;
        a0_imag = vect1[i0].imag;
#else
        a0_real = vect1[i0].real >> 2;
        a0_imag = vect1[i0].imag >> 2;
#endif

        a1_real = vect1[i2].real;
        a1_imag = vect1[i2].imag;
        a2_real = vect1[i1].real;
        a2_imag = vect1[i1].imag;
        a3_real = vect1[i3].real;
        a3_imag = vect1[i3].imag;

#if DSP_OPTIMIZATION & DSP_OPTI_ACCURACY

        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP32_QB);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP32_QB);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP32_QB);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP32_QB);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP32_QB);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP32_QB);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real)) >> 2;
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag)) >> 2;
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real)) >> 2;
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag)) >> 2;

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag)) >> 2;
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real)) >> 2;
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag)) >> 2;
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real)) >> 2;
#else
        temp = (a1_real*e_real - a1_imag*e_imag) >> (DSP32_QB + 1);
        a1_imag = (a1_real*e_imag + a1_imag*e_real) >> (DSP32_QB + 1);
        a1_real = temp;
        temp = (a2_real*e2_real - a2_imag*e2_imag) >> (DSP32_QB + 1);
        a2_imag = (a2_real*e2_imag + a2_imag*e2_real) >> (DSP32_QB + 1);
        a2_real = temp;
        temp = (a3_real*e3_real - a3_imag*e3_imag) >> (DSP32_QB + 1);
        a3_imag = (a3_real*e3_imag + a3_imag*e3_real) >> (DSP32_QB + 1);
        a3_real = temp;

        vect1[i0].real = (a0_real + a2_real + (a1_real + a3_real));
        vect1[i0].imag = (a0_imag + a2_imag + (a1_imag + a3_imag));
        vect1[i2].real = (a0_real + a2_real - (a1_real + a3_real));
        vect1[i2].imag = (a0_imag + a2_imag - (a1_imag + a3_imag));

        vect1[i1].real = (a0_real - a2_real + (a1_imag - a3_imag));
        vect1[i1].imag = (a0_imag - a2_imag - (a1_real - a3_real));
        vect1[i3].real = (a0_real - a2_real - (a1_imag - a3_imag));
        vect1[i3].imag = (a0_imag - a2_imag + (a1_real - a3_real));
#endif
      }
    }
    inc_indice >>= 2;
  }
}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines