Beispiel #1
0
/* Run one inverse FFT test in test mode */
float RunOneInverseTest(int fft_log_size, int signal_type, float signal_value,
                        struct SnrResult* snr) {
  OMX_F32* x;
  OMX_FC32* y;
  OMX_F32* z;
  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;

  OMX_FC32* yTrue;
  struct AlignedPtr* yTrueAligned;

  OMX_INT n;
  OMX_INT fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_R_F32 * fft_fwd_spec = NULL;
  OMXFFTSpec_R_F32 * fft_inv_spec = NULL;
  int fft_size;

  fft_size = 1 << fft_log_size;

  status = omxSP_FFTGetBufSize_R_F32(fft_log_size, &fft_spec_buffer_size);
  if (verbose > 3) {
    printf("fft_spec_buffer_size = %d\n", fft_spec_buffer_size);
  }

  fft_inv_spec = (OMXFFTSpec_R_F32*)malloc(fft_spec_buffer_size);
  status = omxSP_FFTInit_R_F32(fft_inv_spec, fft_log_size);
  if (status) {
    fprintf(stderr, "Failed to init backward FFT:  status = %d\n", status);
    exit(1);
  }

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size / 2 + 1));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
  yTrueAligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size / 2 + 1));
  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  yTrue = yTrueAligned->aligned_pointer_;

  GenerateSignal(x, yTrue, fft_size, signal_type, signal_value);

  if (verbose > 255) {
    printf("input  = %p - %p\n", yTrue, yTrue + fft_size / 2 + 1);
    printf("output = %p - %p\n", z, z + fft_size);
    DumpFFTSpec(fft_inv_spec);
  }

  if (verbose > 63) {
    printf("Inverse FFT Input Signal\n");
    DumpArrayComplexFloat("y", 1 + fft_size / 2, yTrue);

    printf("Expected Inverse FFT output\n");
    DumpArrayFloat("x", fft_size, x);
  }

  status = InverseRFFT((OMX_F32 *) yTrue, z, fft_inv_spec);
  if (status) {
    fprintf(stderr, "Inverse FFT failed: status = %d\n", status);
    exit(1);
  }

  if (verbose > 63) {
    printf("Actual Inverse FFT Output\n");
    DumpArrayFloat("z", fft_size, z);
  }

  CompareFloat(snr, z, x, fft_size);

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  FreeAlignedPointer(yTrueAligned);
  free(fft_inv_spec);

  return snr->real_snr_;
}
Beispiel #2
0
/*
 * Like TestFFT, but do just the inverse FFT
 */
float RunOneInverseTest(int fft_log_size, int signal_type, float signal_value,
                        struct SnrResult* snr) {
  OMX_SC32* x;
  OMX_SC32* y;
  OMX_SC32* z;

  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;

  OMX_INT n, fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_C_SC32 * fft_fwd_spec = NULL;
  OMXFFTSpec_C_SC32 * fft_inv_spec = NULL;
  int fft_size;

  fft_size = 1 << fft_log_size;

  status = omxSP_FFTGetBufSize_C_SC32(fft_log_size, &fft_spec_buffer_size);
  if (verbose > 3) {
    printf("fft_spec_buffer_size = %d\n", fft_spec_buffer_size);
  }

  fft_inv_spec = (OMXFFTSpec_C_SC32*)malloc(fft_spec_buffer_size);
  status = omxSP_FFTInit_C_SC32(fft_inv_spec, fft_log_size);
  if (status) {
    fprintf(stderr, "Failed to init backward FFT:  status = %d\n", status);
    exit(1);
  }

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;

  GenerateSignal(x, y, fft_size, signal_type);

  if (verbose > 63) {
    printf("Inverse FFT Input Signal\n");
    printf("n\tx[n]\n");
    DumpArrayComplex32("x", fft_size, y);

    printf("Expected Inverse FFT output\n");
    DumpArrayComplex32("y", fft_size, x);
  }

  status = omxSP_FFTInv_CToC_SC32_Sfs(y, z, fft_inv_spec, 0);
  if (status) {
    fprintf(stderr, "Inverse FFT failed: status = %d\n", status);
    exit(1);
  }

  if (verbose > 63) {
    printf("Actual Inverse FFT Output\n");
    DumpArrayComplex32("y", fft_size, z);
  }

  CompareComplex32(snr, z, x, fft_size);

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  free(fft_inv_spec);

  return snr->complex_snr_;
}
Beispiel #3
0
/* Run one forward FFT test in test mode */
float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value,
                        struct SnrResult* snr) {
  OMX_F32* x;
  OMX_FC32* y;
  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;

  OMX_FC32* y_true;

  OMX_INT n;
  OMX_INT fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_R_F32 * fft_fwd_spec = NULL;
  int fft_size;

  fft_size = 1 << fft_log_size;

  status = omxSP_FFTGetBufSize_R_F32(fft_log_size, &fft_spec_buffer_size);
  if (verbose > 63) {
    printf("fft_spec_buffer_size = %d\n", fft_spec_buffer_size);
  }

  fft_fwd_spec = (OMXFFTSpec_R_F32*) malloc(fft_spec_buffer_size);
  status = omxSP_FFTInit_R_F32(fft_fwd_spec, fft_log_size);
  if (status) {
    fprintf(stderr, "Failed to init forward FFT:  status = %d\n", status);
    exit(1);
  }

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  y_true = (OMX_FC32*) malloc(sizeof(*y_true) * (fft_size / 2 + 1));

  GenerateSignal(x, y_true, fft_size, signal_type, signal_value);

  if (verbose > 255) {
    printf("input  = %p - %p\n", x, x + fft_size);
    printf("output = %p - %p\n", y, y + fft_size / 2 + 1);
    DumpFFTSpec(fft_fwd_spec);
  }

  if (verbose > 63) {
    printf("Signal\n");
    DumpArrayFloat("x", fft_size, x);

    printf("Expected FFT output\n");
    DumpArrayComplexFloat("y", 1 + fft_size / 2, y_true);
  }

  status = ForwardRFFT(x, (OMX_F32*) y, fft_fwd_spec);
  if (status) {
    fprintf(stderr, "Forward FFT failed: status = %d\n", status);
    exit(1);
  }

  if (verbose > 63) {
    printf("FFT Output\n");
    DumpArrayComplexFloat("y", 1 + fft_size / 2, y);
  }

  CompareComplexFloat(snr, y, y_true, fft_size / 2 + 1);

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  free(y_true);
  free(fft_fwd_spec);

  return snr->complex_snr_;
}
Beispiel #4
0
void TimeOneNE10RFFT(int count, int fft_log_size, float signal_value,
                     int signal_type) {
    OMX_F32* x;                   /* Source */
    OMX_FC32* y;                  /* Transform */
    OMX_F32* z;                   /* Inverse transform */
    OMX_F32* temp;

    OMX_F32* y_true;              /* True FFT */

    struct AlignedPtr* x_aligned;
    struct AlignedPtr* y_aligned;
    struct AlignedPtr* z_aligned;

    int n;
    ne10_result_t status;
    ne10_fft_r2c_cfg_float32_t fft_fwd_spec;

    int fft_size;
    struct timeval start_time;
    struct timeval end_time;
    double elapsed_time;
    struct SnrResult snr_forward;
    struct SnrResult snr_inverse;

    fft_size = 1 << fft_log_size;

    x_aligned = AllocAlignedPointer(32, sizeof(*x) * 4 * fft_size);
    /* The transformed value is in CCS format and is has fft_size + 2 values */
    y_aligned = AllocAlignedPointer(32, sizeof(*y) * (4 * fft_size + 2));
    z_aligned = AllocAlignedPointer(32, sizeof(*z) * 4 * fft_size);

    x = x_aligned->aligned_pointer_;
    y = y_aligned->aligned_pointer_;
    z = z_aligned->aligned_pointer_;

    y_true = (OMX_F32*) malloc(sizeof(*y_true) * (fft_size + 2));

    GenerateRealFloatSignal(x, (struct ComplexFloat*) y_true, fft_size, signal_type,
                            signal_value);

    fft_fwd_spec = ne10_fft_alloc_r2c_float32(fft_size);

    if (!fft_fwd_spec) {
        fprintf(stderr, "NE10 RFFT: Cannot initialize FFT structure for order %d\n", fft_log_size);
        return;
    }

    if (do_forward_test) {
        GetUserTime(&start_time);
        for (n = 0; n < count; ++n) {
            ne10_fft_r2c_1d_float32_neon((ne10_fft_cpx_float32_t *) y,
                                         x,
                                         fft_fwd_spec);
        }
        GetUserTime(&end_time);

        elapsed_time = TimeDifference(&start_time, &end_time);

        CompareComplexFloat(&snr_forward, (OMX_FC32*) y, (OMX_FC32*) y_true, fft_size / 2 + 1);

        PrintResult("Forward NE10 RFFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);

        if (verbose >= 255) {
            printf("FFT Actual:\n");
            DumpArrayComplexFloat("y", fft_size / 2 + 1, y);
            printf("FFT Expected:\n");
            DumpArrayComplexFloat("true", fft_size / 2 + 1, (OMX_FC32*) y_true);
        }
    }

    if (do_inverse_test) {
        // Ne10 FFTs destroy the input.

        GetUserTime(&start_time);
        for (n = 0; n < count; ++n) {
            //memcpy(y, y_true, (fft_size >> 1) * sizeof(*y));
            // The inverse appears not to be working.
            ne10_fft_c2r_1d_float32_neon(z,
                                         (ne10_fft_cpx_float32_t *) y_true,
                                         fft_fwd_spec);
        }
        GetUserTime(&end_time);

        elapsed_time = TimeDifference(&start_time, &end_time);

        CompareFloat(&snr_inverse, (OMX_F32*) z, (OMX_F32*) x, fft_size);

        PrintResult("Inverse NE10 RFFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);

        if (verbose >= 255) {
            printf("IFFT Actual:\n");
            DumpArrayFloat("z", fft_size, z);
            printf("IFFT Expected:\n");
            DumpArrayFloat("x", fft_size, x);
        }
    }

    ne10_fft_destroy_r2c_float32(fft_fwd_spec);
    FreeAlignedPointer(x_aligned);
    FreeAlignedPointer(y_aligned);
    FreeAlignedPointer(z_aligned);
}
Beispiel #5
0
void TimeOneNE10FFT(int count, int fft_log_size, float signal_value,
                    int signal_type) {
    struct AlignedPtr* x_aligned;
    struct AlignedPtr* y_aligned;
    struct AlignedPtr* z_aligned;

    struct ComplexFloat* x;
    struct ComplexFloat* y;
    OMX_FC32* z;

    struct ComplexFloat* y_true;

    int n;
    ne10_result_t status;
    ne10_fft_cfg_float32_t fft_fwd_spec;
    int fft_size;
    struct timeval start_time;
    struct timeval end_time;
    double elapsed_time;
    struct SnrResult snr_forward;
    struct SnrResult snr_inverse;

    fft_size = 1 << fft_log_size;

    x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
    y_aligned = AllocAlignedPointer(32, sizeof(*y) * 2 * fft_size);
    z_aligned = AllocAlignedPointer(32, sizeof(*z) * 2 * fft_size);

    y_true = (struct ComplexFloat*) malloc(sizeof(*y_true) * fft_size);

    x = x_aligned->aligned_pointer_;
    y = y_aligned->aligned_pointer_;
    z = z_aligned->aligned_pointer_;

    GenerateTestSignalAndFFT(x, y_true, fft_size, signal_type, signal_value, 0);

    fft_fwd_spec = ne10_fft_alloc_c2c_float32(fft_size);
    if (!fft_fwd_spec) {
        fprintf(stderr, "NE10 FFT: Cannot initialize FFT structure for order %d\n", fft_log_size);
        return;
    }

    if (do_forward_test) {
        GetUserTime(&start_time);
        for (n = 0; n < count; ++n) {
            ne10_fft_c2c_1d_float32_neon((ne10_fft_cpx_float32_t *) y,
                                         (ne10_fft_cpx_float32_t *) x,
                                         fft_fwd_spec,
                                         0);
        }
        GetUserTime(&end_time);

        elapsed_time = TimeDifference(&start_time, &end_time);

        CompareComplexFloat(&snr_forward, (OMX_FC32*) y, (OMX_FC32*) y_true, fft_size);

        PrintResult("Forward NE10 FFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);

        if (verbose >= 255) {
            printf("Input data:\n");
            DumpArrayComplexFloat("x", fft_size, (OMX_FC32*) x);
            printf("FFT Actual:\n");
            DumpArrayComplexFloat("y", fft_size, (OMX_FC32*) y);
            printf("FFT Expected:\n");
            DumpArrayComplexFloat("true", fft_size, (OMX_FC32*) y_true);
        }
    }

    if (do_inverse_test) {
        GetUserTime(&start_time);
        for (n = 0; n < count; ++n) {
            ne10_fft_c2c_1d_float32_neon((ne10_fft_cpx_float32_t *) z,
                                         (ne10_fft_cpx_float32_t *) y_true,
                                         fft_fwd_spec,
                                         1);
        }
        GetUserTime(&end_time);

        elapsed_time = TimeDifference(&start_time, &end_time);

        CompareComplexFloat(&snr_inverse, (OMX_FC32*) z, (OMX_FC32*) x, fft_size);

        PrintResult("Inverse NE10 FFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);

        if (verbose >= 255) {
            printf("Input data:\n");
            DumpArrayComplexFloat("y", fft_size, (OMX_FC32*) y_true);
            printf("IFFT Actual:\n");
            DumpArrayComplexFloat("z", fft_size, z);
            printf("IFFT Expected:\n");
            DumpArrayComplexFloat("x", fft_size, (OMX_FC32*) x);
        }
    }

    ne10_fft_destroy_c2c_float32(fft_fwd_spec);
    FreeAlignedPointer(x_aligned);
    FreeAlignedPointer(y_aligned);
    FreeAlignedPointer(z_aligned);
    free(y_true);
}
Beispiel #6
0
/* Argument s16s32:
 *     S32:       Calculate RFFT16 with 32 bit complex FFT;
 *     otherwise: Calculate RFFT16 with 16 bit complex FFT.
 */
void TimeOneRFFT16(int count, int fft_log_size, float signal_value,
                   int signal_type, s16_s32 s16s32) {
  OMX_S16* x;
  OMX_S32* y;
  OMX_S16* z;
  OMX_S32* y_true;
  OMX_F32* xr;
  OMX_F32* yrTrue;

  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;
  struct AlignedPtr* y_trueAligned;
  struct AlignedPtr* xr_aligned;
  struct AlignedPtr* yr_true_aligned;


  OMX_S16* temp16;
  OMX_S32* temp32;


  OMX_INT n, fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_R_S16 * fft_fwd_spec = NULL;
  OMXFFTSpec_R_S16 * fft_inv_spec = NULL;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  int scaleFactor;

  fft_size = 1 << fft_log_size;
  scaleFactor = fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);

  y_trueAligned = AllocAlignedPointer(32, sizeof(*y_true) * (fft_size + 2));

  xr_aligned = AllocAlignedPointer(32, sizeof(*xr) * fft_size);
  yr_true_aligned = AllocAlignedPointer(32, sizeof(*yrTrue) * (fft_size + 2));

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  y_true = y_trueAligned->aligned_pointer_;
  xr = xr_aligned->aligned_pointer_;
  yrTrue = yr_true_aligned->aligned_pointer_;

  temp16 = (OMX_S16*) malloc(sizeof(*temp16) * fft_size);
  temp32 = (OMX_S32*) malloc(sizeof(*temp32) * fft_size);


  GenerateRFFT16Signal(x, (OMX_SC32*) y_true, fft_size, signal_type,
                       signal_value);
  /*
   * Generate a real version so we can measure scaling costs
   */
  GenerateRealFloatSignal(xr, (OMX_FC32*) yrTrue, fft_size, signal_type,
                          signal_value);

  if(s16s32 == S32) {
    status = omxSP_FFTGetBufSize_R_S16S32(fft_log_size, &fft_spec_buffer_size);
    fft_fwd_spec = malloc(fft_spec_buffer_size);
    fft_inv_spec = malloc(fft_spec_buffer_size);
    status = omxSP_FFTInit_R_S16S32(fft_fwd_spec, fft_log_size);
    status = omxSP_FFTInit_R_S16S32(fft_inv_spec, fft_log_size);
  }
  else {
    status = omxSP_FFTGetBufSize_R_S16(fft_log_size, &fft_spec_buffer_size);
    fft_fwd_spec = malloc(fft_spec_buffer_size);
    fft_inv_spec = malloc(fft_spec_buffer_size);
    status = omxSP_FFTInit_R_S16(fft_fwd_spec, fft_log_size);
    status = omxSP_FFTInit_R_S16(fft_inv_spec, fft_log_size);
  }

  if (do_forward_test) {
    if (include_conversion) {
      int k;
      float factor = -1;

      GetUserTime(&start_time);
      for (k = 0; k < count; ++k) {
        /*
         * Spend some time computing the max of the signal, and then scaling it.
         */
        for (n = 0; n < fft_size; ++n) {
          if (abs(xr[n]) > factor) {
            factor = abs(xr[n]);
          }
        }

        factor = 32767 / factor;
        for (n = 0; n < fft_size; ++n) {
          temp16[n] = factor * xr[n];
        }

        if(s16s32 == S32) {
          status = omxSP_FFTFwd_RToCCS_S16S32_Sfs(x, y,
              (OMXFFTSpec_R_S16S32*)fft_fwd_spec, (OMX_INT) scaleFactor);
        }
        else {
          status = omxSP_FFTFwd_RToCCS_S16_Sfs(x,  (OMX_S16*)y,
              (OMXFFTSpec_R_S16*)fft_fwd_spec, (OMX_INT) scaleFactor);
        }
        /*
         * Now spend some time converting the fixed-point FFT back to float.
         */
        factor = 1 / factor;
        for (n = 0; n < fft_size + 2; ++n) {
          xr[n] = y[n] * factor;
        }
      }
      GetUserTime(&end_time);
    } else {
      float factor = -1;

      GetUserTime(&start_time);
      for (n = 0; n < count; ++n) {
      if(s16s32 == S32) {
        status = omxSP_FFTFwd_RToCCS_S16S32_Sfs(x, y, 
            (OMXFFTSpec_R_S16S32*)fft_fwd_spec, (OMX_INT) scaleFactor);
      }
      else {
        status = omxSP_FFTFwd_RToCCS_S16_Sfs(x, (OMX_S16*)y,
            (OMXFFTSpec_R_S16*)fft_fwd_spec, (OMX_INT) scaleFactor);
      }
      }
      GetUserTime(&end_time);
    }

    elapsed_time = TimeDifference(&start_time, &end_time);

    if(s16s32 == S32) {
      PrintResultNoSNR("Forward RFFT16 (with S32)",
                       fft_log_size, elapsed_time, count);
    }
    else {
      PrintResultNoSNR("Forward RFFT16 (with S16)",
                       fft_log_size, elapsed_time, count);
    }
  }

  if (do_inverse_test) {
    if (include_conversion) {
      int k;
      float factor = -1;

      GetUserTime(&start_time);
      for (k = 0; k < count; ++k) {
        /*
         * Spend some time scaling the FFT signal to fixed point.
         */
        for (n = 0; n < fft_size; ++n) {
          if (abs(yrTrue[n]) > factor) {
            factor = abs(yrTrue[n]);
          }
        }
        for (n = 0; n < fft_size; ++n) {
          temp32[n] = factor * yrTrue[n];
        }

        if(s16s32 == S32) {
          status = omxSP_FFTInv_CCSToR_S32S16_Sfs(y, z,
              (OMXFFTSpec_R_S16S32*)fft_inv_spec, 0);
        }
        else {
          status = omxSP_FFTInv_CCSToR_S16_Sfs((OMX_S16*)y, z,
              (OMXFFTSpec_R_S16*)fft_inv_spec, 0);
        }
        /*
         * Spend some time converting the result back to float
         */
        factor = 1 / factor;
        for (n = 0; n < fft_size; ++n) {
          xr[n] = factor * z[n];
        }
      }
      GetUserTime(&end_time);
    } else {
      GetUserTime(&start_time);
      for (n = 0; n < count; ++n) {
        if(s16s32 == S32) {
          status = omxSP_FFTInv_CCSToR_S32S16_Sfs(y, z,
              (OMXFFTSpec_R_S16S32*)fft_inv_spec, 0);
        }
        else {
          status = omxSP_FFTInv_CCSToR_S16_Sfs((OMX_S16*)y, z,
              (OMXFFTSpec_R_S16*)fft_inv_spec, 0);
        }
      }
      GetUserTime(&end_time);
    }

    elapsed_time = TimeDifference(&start_time, &end_time);

    if(s16s32 == S32) {
      PrintResultNoSNR("Inverse RFFT16 (with S32)",
                       fft_log_size, elapsed_time, count);
    }
    else {
      PrintResultNoSNR("Inverse RFFT16 (with S16)",
                       fft_log_size, elapsed_time, count);
    }
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  FreeAlignedPointer(y_trueAligned);
  FreeAlignedPointer(xr_aligned);
  FreeAlignedPointer(yr_true_aligned);
  free(fft_fwd_spec);
  free(fft_inv_spec);
}
Beispiel #7
0
void TimeOneRFFT32(int count, int fft_log_size, float signal_value,
                   int signal_type) {
  OMX_S32* x;
  OMX_S32* y;
  OMX_S32* z;
  OMX_S32* y_true;
  OMX_F32* xr;
  OMX_F32* yrTrue;

  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;
  struct AlignedPtr* y_true_aligned;

  OMX_S32* temp1;
  OMX_S32* temp2;

  OMX_INT n, fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_R_S16S32 * fft_fwd_spec = NULL;
  OMXFFTSpec_R_S16S32 * fft_inv_spec = NULL;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  int scaleFactor = 0;
  struct SnrResult snr_forward;
  struct SnrResult snr_inverse;

  fft_size = 1 << fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);

  y_true_aligned = AllocAlignedPointer(32, sizeof(*y_true) * (fft_size + 2));

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  y_true = y_true_aligned->aligned_pointer_;

  if (verbose > 3) {
    printf("x = %p\n", (void*)x);
    printf("y = %p\n", (void*)y);
    printf("z = %p\n", (void*)z);
  }

  xr = (OMX_F32*) malloc(sizeof(*x) * fft_size);
  yrTrue = (OMX_F32*) malloc(sizeof(*y) * (fft_size + 2));
  temp1 = (OMX_S32*) malloc(sizeof(*temp1) * fft_size);
  temp2 = (OMX_S32*) malloc(sizeof(*temp2) * (fft_size + 2));

  GenerateRFFT32Signal(x, (OMX_SC32*) y_true, fft_size, signal_type,
                       signal_value);

  if (verbose > 63) {
    printf("Signal\n");
    printf("n\tx[n]\n");
    for (n = 0; n < fft_size; ++n) {
      printf("%4d\t%d\n", n, x[n]);
    }
  }

  status = omxSP_FFTGetBufSize_R_S32(fft_log_size, &fft_spec_buffer_size);
  if (verbose > 3) {
    printf("fft_spec_buffer_size = %d\n", fft_spec_buffer_size);
  }

  fft_fwd_spec = (OMXFFTSpec_R_S32*) malloc(fft_spec_buffer_size);
  fft_inv_spec = (OMXFFTSpec_R_S32*) malloc(fft_spec_buffer_size);
  status = omxSP_FFTInit_R_S32(fft_fwd_spec, fft_log_size);
  if (status) {
    printf("Failed to init forward FFT:  status = %d\n", status);
  }

  status = omxSP_FFTInit_R_S32(fft_inv_spec, fft_log_size);
  if (status) {
    printf("Failed to init backward FFT:  status = %d\n", status);
  }

  if (do_forward_test) {
    if (include_conversion) {
      int k;
      float factor = -1;

      GetUserTime(&start_time);
      for (k = 0; k < count; ++k) {
        /*
         * Spend some time computing the max of the signal, and then scaling it.
         */
        for (n = 0; n < fft_size; ++n) {
          if (abs(xr[n]) > factor) {
            factor = abs(xr[n]);
          }
        }

        factor = (1 << 20) / factor;
        for (n = 0; n < fft_size; ++n) {
          temp1[n] = factor * xr[n];
        }

        status = omxSP_FFTFwd_RToCCS_S32_Sfs(x, y, fft_fwd_spec,
                                             (OMX_INT) scaleFactor);

        /*
         * Now spend some time converting the fixed-point FFT back to float.
         */
        factor = 1 / factor;
        for (n = 0; n < fft_size + 2; ++n) {
          xr[n] = y[n] * factor;
        }
      }
      GetUserTime(&end_time);
    } else {
      float factor = -1;

      GetUserTime(&start_time);
      for (n = 0; n < count; ++n) {
        status = omxSP_FFTFwd_RToCCS_S32_Sfs(x, y, fft_fwd_spec,
                                             (OMX_INT) scaleFactor);
      }
      GetUserTime(&end_time);
    }

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplex32(&snr_forward, (OMX_SC32*) y, (OMX_SC32*) y_true, fft_size / 2 + 1);

    PrintResult("Forward RFFT32", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);
  }

  if (do_inverse_test) {
    if (include_conversion) {
      int k;
      float factor = -1;

      GetUserTime(&start_time);
      for (k = 0; k < count; ++k) {
        /*
         * Spend some time scaling the FFT signal to fixed point.
         */
        for (n = 0; n < fft_size + 2; ++n) {
          if (abs(yrTrue[n]) > factor) {
            factor = abs(yrTrue[n]);
          }
        }
        for (n = 0; n < fft_size + 2; ++n) {
          temp2[n] = factor * yrTrue[n];
        }

        status = omxSP_FFTInv_CCSToR_S32_Sfs(y_true, z, fft_inv_spec, 0);

        /*
         * Spend some time converting the result back to float
         */
        factor = 1 / factor;
        for (n = 0; n < fft_size; ++n) {
          xr[n] = factor * z[n];
        }
      }
      GetUserTime(&end_time);
    } else {
      GetUserTime(&start_time);
      for (n = 0; n < count; ++n) {
        status = omxSP_FFTInv_CCSToR_S32_Sfs(y_true, z, fft_inv_spec, 0);
      }
      GetUserTime(&end_time);
    }

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareReal32(&snr_inverse, z, x, fft_size);

    PrintResult("Inverse RFFT32", fft_log_size, elapsed_time, count, snr_inverse.real_snr_);
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  FreeAlignedPointer(y_true_aligned);
  free(fft_fwd_spec);
  free(fft_inv_spec);
}
Beispiel #8
0
void TimeOneSC16FFT(int count, int fft_log_size, float signal_value,
                    int signal_type) {
  OMX_SC16* x;
  OMX_SC16* y;
  OMX_SC16* z;

  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;

  OMX_SC16* y_true;
  OMX_SC16* temp16a;
  OMX_SC16* temp16b;

  OMX_INT n, fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_C_SC16 * fft_fwd_spec = NULL;
  OMXFFTSpec_C_SC16 * fft_inv_spec = NULL;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  struct SnrResult snr_forward;
  struct SnrResult snr_inverse;

  fft_size = 1 << fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * fft_size);
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
  y_true = (OMX_SC16*) malloc(sizeof(*y_true) * fft_size);
  temp16a = (OMX_SC16*) malloc(sizeof(*temp16a) * fft_size);
  temp16b = (OMX_SC16*) malloc(sizeof(*temp16b) * fft_size);

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;

  generateSC16Signal(x, y_true, fft_size, signal_type, signal_value);

  status = omxSP_FFTGetBufSize_C_SC16(fft_log_size, &fft_spec_buffer_size);

  fft_fwd_spec = (OMXFFTSpec_C_SC16*) malloc(fft_spec_buffer_size);
  fft_inv_spec = (OMXFFTSpec_C_SC16*) malloc(fft_spec_buffer_size);
  status = omxSP_FFTInit_C_SC16(fft_fwd_spec, fft_log_size);

  status = omxSP_FFTInit_C_SC16(fft_inv_spec, fft_log_size);

  if (do_forward_test) {
    if (include_conversion) {
      int k;
      float factor = -1;

      GetUserTime(&start_time);
      for (k = 0; k < count; ++k) {
        for (n = 0; n < fft_size; ++n) {
          if (abs(x[n].Re) > factor) {
            factor = abs(x[n].Re);
          }
          if (abs(x[n].Im) > factor) {
            factor = abs(x[n].Im);
          }
        }

        factor = ((1 << 15) - 1) / factor;
        for (n = 0; n < fft_size; ++n) {
          temp16a[n].Re = factor * x[n].Re;
          temp16a[n].Im = factor * x[n].Im;
        }

        omxSP_FFTFwd_CToC_SC16_Sfs(x, y, fft_fwd_spec, 0);

        factor = 1 / factor;
        for (n = 0; n < fft_size; ++n) {
          temp16b[n].Re = y[n].Re * factor;
          temp16b[n].Im = y[n].Im * factor;
        }
      }
      GetUserTime(&end_time);
    } else {
      GetUserTime(&start_time);
      for (n = 0; n < count; ++n) {
        omxSP_FFTFwd_CToC_SC16_Sfs(x, y, fft_fwd_spec, 0);
      }
      GetUserTime(&end_time);
    }

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplex16(&snr_forward, y, y_true, fft_size);

    PrintResult("Forward SC16 FFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);
  }

  if (do_inverse_test) {
    if (include_conversion) {
      int k;
      float factor = -1;

      GetUserTime(&start_time);
      for (k = 0; k < count; ++k) {
        for (n = 0; n < fft_size; ++n) {
          if (abs(x[n].Re) > factor) {
            factor = abs(x[n].Re);
          }
          if (abs(x[n].Im) > factor) {
            factor = abs(x[n].Im);
          }
        }
        factor = ((1 << 15) - 1) / factor;
        for (n = 0; n < fft_size; ++n) {
          temp16a[n].Re = factor * x[n].Re;
          temp16a[n].Im = factor * x[n].Im;
        }

        status = omxSP_FFTInv_CToC_SC16_Sfs(y, z, fft_inv_spec, 0);

        factor = 1 / factor;
        for (n = 0; n < fft_size; ++n) {
          temp16b[n].Re = y[n].Re * factor;
          temp16b[n].Im = y[n].Im * factor;
        }
      }
      GetUserTime(&end_time);
    } else {
      GetUserTime(&start_time);
      for (n = 0; n < count; ++n) {
        status = omxSP_FFTInv_CToC_SC16_Sfs(y, z, fft_inv_spec, 0);
      }
      GetUserTime(&end_time);
    }

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplex16(&snr_inverse, z, x, fft_size);

    PrintResult("Inverse SC16 FFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  free(temp16a);
  free(temp16b);
  free(fft_fwd_spec);
  free(fft_inv_spec);
}
Beispiel #9
0
void TimeOneFloatFFT(int count, int fft_log_size, float signal_value,
                     int signal_type) {
  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;
  struct AlignedPtr* y_true_aligned;

  struct ComplexFloat* x;
  struct ComplexFloat* y;
  OMX_FC32* z;

  struct ComplexFloat* y_true;

  OMX_INT n, fft_spec_buffer_size;
  OMXFFTSpec_C_FC32 * fft_fwd_spec = NULL;
  OMXFFTSpec_C_FC32 * fft_inv_spec = NULL;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  struct SnrResult snr_forward;
  struct SnrResult snr_inverse;

  fft_size = 1 << fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
  y_true_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  y_true = y_true_aligned->aligned_pointer_;

  GenerateTestSignalAndFFT(x, y_true, fft_size, signal_type, signal_value, 0);

  omxSP_FFTGetBufSize_C_FC32(fft_log_size, &fft_spec_buffer_size);

  fft_fwd_spec = (OMXFFTSpec_C_FC32*) malloc(fft_spec_buffer_size);
  fft_inv_spec = (OMXFFTSpec_C_FC32*) malloc(fft_spec_buffer_size);
  omxSP_FFTInit_C_FC32(fft_fwd_spec, fft_log_size);
  omxSP_FFTInit_C_FC32(fft_inv_spec, fft_log_size);

  if (do_forward_test) {
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      FORWARD_FLOAT_FFT((OMX_FC32*) x, (OMX_FC32*) y, fft_fwd_spec);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplexFloat(&snr_forward, (OMX_FC32*) y, (OMX_FC32*) y_true, fft_size);

    PrintResult("Forward Float FFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);
  }

  if (do_inverse_test) {
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      INVERSE_FLOAT_FFT((OMX_FC32*) y_true, z, fft_inv_spec);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplexFloat(&snr_inverse, (OMX_FC32*) z, (OMX_FC32*) x, fft_size);

    PrintResult("Inverse Float FFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  FreeAlignedPointer(y_true_aligned);
  free(fft_fwd_spec);
  free(fft_inv_spec);
}
Beispiel #10
0
void TimeOneFloatRFFT(int count, int fft_log_size, float signal_value,
                      int signal_type) {
  OMX_F32* x;                   /* Source */
  OMX_F32* y;                   /* Transform */
  OMX_F32* z;                   /* Inverse transform */

  OMX_F32* y_true;              /* True FFT */

  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;
  struct AlignedPtr* y_true_aligned;


  OMX_INT n, fft_spec_buffer_size;
  OMXResult status;
  OMXFFTSpec_R_F32 * fft_fwd_spec = NULL;
  OMXFFTSpec_R_F32 * fft_inv_spec = NULL;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  struct SnrResult snr_forward;
  struct SnrResult snr_inverse;

  fft_size = 1 << fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  /* The transformed value is in CCS format and is has fft_size + 2 values */
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
  y_true_aligned = AllocAlignedPointer(32, sizeof(*z) * (fft_size + 2));

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  y_true = y_true_aligned->aligned_pointer_;

  GenerateRealFloatSignal(x, (OMX_FC32*) y_true, fft_size, signal_type,
                          signal_value);

  status = omxSP_FFTGetBufSize_R_F32(fft_log_size, &fft_spec_buffer_size);

  fft_fwd_spec = (OMXFFTSpec_R_F32*) malloc(fft_spec_buffer_size);
  fft_inv_spec = (OMXFFTSpec_R_F32*) malloc(fft_spec_buffer_size);
  status = omxSP_FFTInit_R_F32(fft_fwd_spec, fft_log_size);

  status = omxSP_FFTInit_R_F32(fft_inv_spec, fft_log_size);

  if (do_forward_test) {
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      FORWARD_FLOAT_RFFT(x, y, fft_fwd_spec);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplexFloat(&snr_forward, (OMX_FC32*) y, (OMX_FC32*) y_true, fft_size / 2 + 1);

    PrintResult("Forward Float RFFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);
  }

  if (do_inverse_test) {
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      INVERSE_FLOAT_RFFT(y_true, z, fft_inv_spec);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareFloat(&snr_inverse, (OMX_F32*) z, (OMX_F32*) x, fft_size);

    PrintResult("Inverse Float RFFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  free(fft_fwd_spec);
  free(fft_inv_spec);
}
Beispiel #11
0
void TimeOnePfFFT(int count, int fft_log_size, float signal_value,
                     int signal_type) {
  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;
  struct AlignedPtr* y_true_aligned;

  struct ComplexFloat* x;
  struct ComplexFloat* y;
  OMX_FC32* z;

  struct ComplexFloat* y_true;

  int n;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  PFFFT_Setup *s;
  struct SnrResult snr_forward;
  struct SnrResult snr_inverse;
  
  fft_size = 1 << fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
  y_true_aligned = AllocAlignedPointer(32, sizeof(*y_true) * fft_size);

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  y_true = y_true_aligned->aligned_pointer_;

  s = pffft_new_setup(fft_size, PFFFT_COMPLEX);
  if (!s) {
    fprintf(stderr, "TimeOnePfFFT: Could not initialize structure for order %d\n",
            fft_log_size);
  }

  GenerateTestSignalAndFFT(x, y_true, fft_size, signal_type, signal_value, 0);

  if (do_forward_test) {
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      pffft_transform_ordered(s, (float*)x, (float*)y, NULL, PFFFT_FORWARD);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplexFloat(&snr_forward, (OMX_FC32*) y, (OMX_FC32*) y_true, fft_size);

    PrintResult("Forward PFFFT FFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);

    if (verbose >= 255) {
      printf("FFT Actual:\n");
      DumpArrayComplexFloat("y", fft_size, (OMX_FC32*) y);
      printf("FFT Expected:\n");
      DumpArrayComplexFloat("true", fft_size, (OMX_FC32*) y_true);
    }
  }

  if (do_inverse_test) {
    float scale = 1.0 / fft_size;

    memcpy(y, y_true, sizeof(*y) * (fft_size + 2));
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      int m;
      
      pffft_transform_ordered(s, (float*)y_true, (float*)z, NULL, PFFFT_BACKWARD);
      /*
       * Need to include cost of scaling the inverse
       */
      ScaleVector((OMX_F32*) z, 2 * fft_size, fft_size);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareComplexFloat(&snr_inverse, (OMX_FC32*) z, (OMX_FC32*) x, fft_size);

    PrintResult("Inverse PFFFT FFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);

    if (verbose >= 255) {
      printf("IFFT Actual:\n");
      DumpArrayComplexFloat("z", fft_size, z);
      printf("IFFT Expected:\n");
      DumpArrayComplexFloat("x", fft_size, (OMX_FC32*) x);
    }
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  FreeAlignedPointer(y_true_aligned);
  pffft_destroy_setup(s);
}
Beispiel #12
0
void TimeOnePfRFFT(int count, int fft_log_size, float signal_value,
                     int signal_type) {
  struct AlignedPtr* x_aligned;
  struct AlignedPtr* y_aligned;
  struct AlignedPtr* z_aligned;
  struct AlignedPtr* y_tmp_aligned;

  float* x;
  struct ComplexFloat* y;
  OMX_F32* z;

  float* y_true;
  float* y_tmp;

  int n;
  int fft_size;
  struct timeval start_time;
  struct timeval end_time;
  double elapsed_time;
  PFFFT_Setup *s;
  struct SnrResult snr_forward;
  struct SnrResult snr_inverse;
  
  fft_size = 1 << fft_log_size;

  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
  y_tmp_aligned = AllocAlignedPointer(32, sizeof(*y_tmp) * (fft_size + 2));

  y_true = (float*) malloc(sizeof(*y_true) * 2 * fft_size);

  x = x_aligned->aligned_pointer_;
  y = y_aligned->aligned_pointer_;
  z = z_aligned->aligned_pointer_;
  y_tmp = y_tmp_aligned->aligned_pointer_;

  s = pffft_new_setup(fft_size, PFFFT_REAL);
  if (!s) {
    fprintf(stderr, "TimeOnePfRFFT: Could not initialize structure for order %d\n",
            fft_log_size);
  }

  GenerateRealFloatSignal(x, (struct ComplexFloat*) y_true, fft_size, signal_type, signal_value);

  if (do_forward_test) {
    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      pffft_transform_ordered(s, (float*)x, (float*)y, NULL, PFFFT_FORWARD);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    /*
     * Arrange the output of the FFT to match the expected output.
     */
    y[fft_size / 2].Re = y[0].Im;
    y[fft_size / 2].Im = 0;
    y[0].Im = 0;

    CompareComplexFloat(&snr_forward, (OMX_FC32*) y, (OMX_FC32*) y_true, fft_size / 2 + 1);

    PrintResult("Forward PFFFT RFFT", fft_log_size, elapsed_time, count, snr_forward.complex_snr_);

    if (verbose >= 255) {
      printf("FFT Actual:\n");
      DumpArrayComplexFloat("y", fft_size / 2 + 1, (OMX_FC32*) y);
      printf("FFT Expected:\n");
      DumpArrayComplexFloat("true", fft_size / 2 + 1, (OMX_FC32*) y_true);
    }
  }

  if (do_inverse_test) {
    float scale = 1.0 / fft_size;

    /* Copy y_true to true, but arrange the values according to what rdft wants. */

    memcpy(y_tmp, y_true, sizeof(y_tmp[0]) * fft_size);
    y_tmp[1] = y_true[fft_size / 2];

    GetUserTime(&start_time);
    for (n = 0; n < count; ++n) {
      int m;
      
      pffft_transform_ordered(s, (float*)y_tmp, (float*)z, NULL, PFFFT_BACKWARD);
      /*
       * Need to include cost of scaling the inverse
       */
      ScaleVector(z, fft_size, fft_size);
    }
    GetUserTime(&end_time);

    elapsed_time = TimeDifference(&start_time, &end_time);

    CompareFloat(&snr_inverse, (OMX_F32*) z, (OMX_F32*) x, fft_size);

    PrintResult("Inverse PFFFT RFFT", fft_log_size, elapsed_time, count, snr_inverse.complex_snr_);

    if (verbose >= 255) {
      printf("IFFT Actual:\n");
      DumpArrayFloat("z", fft_size, z);
      printf("IFFT Expected:\n");
      DumpArrayFloat("x", fft_size, x);
    }
  }

  FreeAlignedPointer(x_aligned);
  FreeAlignedPointer(y_aligned);
  FreeAlignedPointer(z_aligned);
  FreeAlignedPointer(y_tmp_aligned);
  pffft_destroy_setup(s);
  free(y_true);
}