1/*
2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <sys/resource.h>
15#include <sys/time.h>
16#include <unistd.h>
17
18#include "dl/sp/api/armSP.h"
19#include "dl/sp/api/omxSP.h"
20#include "dl/sp/src/test/aligned_ptr.h"
21#include "dl/sp/src/test/gensig.h"
22#include "dl/sp/src/test/test_util.h"
23
24#define MAX_FFT_ORDER TWIDDLE_TABLE_ORDER
25#define MAX_FFT_ORDER_FIXED_POINT 12
26
27#define ENABLE_FIXED_POINT_FFT_TESTS
28
29#if defined(FLOAT_ONLY) || defined(ARM_VFP_TEST)
30/*
31 * Fixed-point FFTs are disabled if we only want float tests or if
32 * we're building for non-NEON tests.
33 */
34#undef ENABLE_FIXED_POINT_FFT_TESTS
35#endif
36
37#if defined(ARM_VFP_TEST)
38#define FORWARD_FLOAT_FFT   omxSP_FFTFwd_CToC_FC32_Sfs_vfp
39#define INVERSE_FLOAT_FFT   omxSP_FFTInv_CToC_FC32_Sfs_vfp
40#define FORWARD_FLOAT_RFFT  omxSP_FFTFwd_RToCCS_F32_Sfs_vfp
41#define INVERSE_FLOAT_RFFT  omxSP_FFTInv_CCSToR_F32_Sfs_vfp
42#else
43#define FORWARD_FLOAT_FFT   omxSP_FFTFwd_CToC_FC32_Sfs
44#define INVERSE_FLOAT_FFT   omxSP_FFTInv_CToC_FC32_Sfs
45#define FORWARD_FLOAT_RFFT  omxSP_FFTFwd_RToCCS_F32_Sfs
46#define INVERSE_FLOAT_RFFT  omxSP_FFTInv_CCSToR_F32_Sfs
47#endif
48
49typedef enum {
50  S16,
51  S32,
52} s16_s32;
53
54#if defined(__arm__) || defined(__aarch64__)
55void TimeOneFloatFFT(int count, int fft_log_size, float signal_value,
56                     int signal_type);
57void TimeFloatFFT(int count, float signal_value, int signal_type);
58#endif
59
60void TimeOneFloatRFFT(int count, int fft_log_size, float signal_value,
61                      int signal_type);
62void TimeFloatRFFT(int count, float signal_value, int signal_type);
63
64#ifdef ENABLE_FIXED_POINT_FFT_TESTS
65void TimeOneSC16FFT(int count, int fft_log_size, float signal_value,
66                    int signal_type);
67void TimeSC16FFT(int count, float signal_value, int signal_type);
68void TimeOneRFFT16(int count, int fft_log_size, float signal_value,
69                   int signal_type, s16_s32 s16s32);
70void TimeRFFT16(int count, float signal_value, int signal_type);
71void TimeOneSC32FFT(int count, int fft_log_size, float signal_value,
72                    int signal_type);
73void TimeSC32FFT(int count, float signal_value, int signal_type);
74void TimeOneRFFT32(int count, int fft_log_size, float signal_value,
75                   int signal_type);
76void TimeRFFT32(int count, float signal_value, int signal_type);
77#endif
78
79static int verbose = 1;
80static int include_conversion = 0;
81static int adapt_count = 1;
82static int do_forward_test = 1;
83static int do_inverse_test = 1;
84static int min_fft_order = 2;
85static int max_fft_order = MAX_FFT_ORDER;
86
87void TimeFFTUsage(char* prog) {
88  fprintf(stderr,
89      "%s: [-hTFICA] [-f fft] [-c count] [-n logsize] [-s scale]\n"
90      "    [-g signal-type] [-S signal value]\n"
91      "    [-m minFFTsize] [-M maxFFTsize]\n",
92          ProgramName(prog));
93  fprintf(stderr,
94#ifndef ARM_VFP_TEST
95      "Simple FFT timing tests (NEON)\n"
96#else
97      "Simple FFT timing tests (non-NEON)\n"
98#endif
99      "  -h          This help\n"
100      "  -v level    Verbose output level (default = 1)\n"
101      "  -F          Skip forward FFT tests\n"
102      "  -I          Skip inverse FFT tests\n"
103      "  -C          Include float-to-fixed and fixed-to-float cost for\n"
104      "              fixed-point FFTs.\n"
105      "  -c count    Number of FFTs to compute for timing.  This is a\n"
106      "              lower limit; shorter FFTs will do more FFTs such\n"
107      "              that the elapsed time is very roughly constant, if\n"
108      "              -A is not given.\n"
109      "  -A          Don't adapt the count given by -c; use specified value\n"
110      "  -m min      Mininum FFT order to test\n"
111      "  -M max      Maximum FFT order to test\n"
112      "  -T          Run just one FFT timing test\n"
113      "  -f          FFT type:\n"
114      "              0 - Complex Float\n"
115#if defined(__arm__) || defined(__aarch64__)
116      "              1 - Real Float\n"
117#endif
118#ifdef ENABLE_FIXED_POINT_FFT_TESTS
119      "              2 - Complex 16-bit\n"
120      "              3 - Real 16-bit\n"
121      "              4 - Complex 32-bit\n"
122      "              5 - Real 32-bit\n"
123#else
124#endif
125      "  -n logsize  Log2 of FFT size\n"
126      "  -s scale    Scale factor for forward FFT (default = 0)\n"
127      "  -S signal   Base value for the test signal (default = 1024)\n"
128      "  -g type     Input signal type:\n"
129      "              0 - Constant signal S + i*S. (Default value.)\n"
130      "              1 - Real ramp starting at S/N, N = FFT size\n"
131      "              2 - Sine wave of amplitude S\n"
132      "              3 - Complex signal whose transform is a sine wave.\n"
133      "\n"
134      "Use -v 0 in combination with -F or -I to get output that can\n"
135      "be pasted into a spreadsheet.\n"
136      "\n"
137      "Most of the options listed after -T above are only applicable\n"
138      "when -T is given to test just one FFT size and FFT type.\n"
139      "\n");
140  exit(0);
141}
142
143/* TODO(kma/ajm/rtoy): use strings instead of numbers for fft_type. */
144int main(int argc, char* argv[]) {
145  int fft_log_size = 4;
146  float signal_value = 32767;
147  int signal_type = 0;
148  int test_mode = 1;
149  int count = 100;
150  int fft_type = 0;
151  int fft_type_given = 0;
152
153  int opt;
154
155  while ((opt = getopt(argc, argv, "hTFICAc:n:s:S:g:v:f:m:M:")) != -1) {
156    switch (opt) {
157      case 'h':
158        TimeFFTUsage(argv[0]);
159        break;
160      case 'T':
161        test_mode = 0;
162        break;
163      case 'C':
164        include_conversion = 1;
165        break;
166      case 'F':
167        do_forward_test = 0;
168        break;
169      case 'I':
170        do_inverse_test = 0;
171        break;
172      case 'A':
173        adapt_count = 0;
174        break;
175      case 'c':
176        count = atoi(optarg);
177        break;
178      case 'n':
179        fft_log_size = atoi(optarg);
180        break;
181      case 'S':
182        signal_value = atof(optarg);
183        break;
184      case 'g':
185        signal_type = atoi(optarg);
186        break;
187      case 'v':
188        verbose = atoi(optarg);
189        break;
190      case 'f':
191        fft_type = atoi(optarg);
192        fft_type_given = 1;
193        break;
194      case 'm':
195        min_fft_order = atoi(optarg);
196        if (min_fft_order <= 2) {
197          fprintf(stderr, "Setting min FFT order to 2 (from %d)\n",
198                  min_fft_order);
199          min_fft_order = 2;
200        }
201        break;
202      case 'M':
203        max_fft_order = atoi(optarg);
204        if (max_fft_order > MAX_FFT_ORDER) {
205          fprintf(stderr, "Setting max FFT order to %d (from %d)\n",
206                  MAX_FFT_ORDER, max_fft_order);
207          max_fft_order = MAX_FFT_ORDER;
208        }
209        break;
210      default:
211        TimeFFTUsage(argv[0]);
212        break;
213    }
214  }
215
216  if (test_mode && fft_type_given)
217    printf("Warning:  -f ignored when -T not specified\n");
218
219  if (test_mode) {
220#if defined(__arm__) || defined(__aarch64__)
221    TimeFloatFFT(count, signal_value, signal_type);
222#endif
223    TimeFloatRFFT(count, signal_value, signal_type);
224#ifdef ENABLE_FIXED_POINT_FFT_TESTS
225    TimeSC16FFT(count, signal_value, signal_type);
226    TimeRFFT16(count, signal_value, signal_type);
227    TimeSC32FFT(count, signal_value, signal_type);
228    TimeRFFT32(count, signal_value, signal_type);
229#endif
230  } else {
231    switch (fft_type) {
232#if defined(__arm__) || defined(__aarch64__)
233      case 0:
234        TimeOneFloatFFT(count, fft_log_size, signal_value, signal_type);
235        break;
236#endif
237      case 1:
238        TimeOneFloatRFFT(count, fft_log_size, signal_value, signal_type);
239        break;
240#ifdef ENABLE_FIXED_POINT_FFT_TESTS
241      case 2:
242        TimeOneSC16FFT(count, fft_log_size, signal_value, signal_type);
243        break;
244      case 3:
245        TimeOneRFFT16(count, fft_log_size, signal_value, signal_type, S32);
246        TimeOneRFFT16(count, fft_log_size, signal_value, signal_type, S16);
247        break;
248      case 4:
249        TimeOneSC32FFT(count, fft_log_size, signal_value, signal_type);
250        break;
251      case 5:
252        TimeOneRFFT32(count, fft_log_size, signal_value, signal_type);
253        break;
254#endif
255      default:
256        fprintf(stderr, "Unknown FFT type: %d\n", fft_type);
257        break;
258    }
259  }
260
261  return 0;
262}
263
264void GetUserTime(struct timeval* time) {
265  struct rusage usage;
266  getrusage(RUSAGE_SELF, &usage);
267  memcpy(time, &usage.ru_utime, sizeof(*time));
268}
269
270double TimeDifference(const struct timeval * start,
271                      const struct timeval * end) {
272  double start_time;
273  double end_time;
274  start_time = start->tv_sec + start->tv_usec * 1e-6;
275  end_time = end->tv_sec + end->tv_usec * 1e-6;
276
277  return end_time - start_time;
278}
279
280void PrintShortHeader(const char* message) {
281  if (do_forward_test && do_inverse_test) {
282    /* Do nothing if both forward and inverse tests are being run. */
283  } else if (do_forward_test) {
284    printf("Forward ");
285  } else {
286    printf("Inverse ");
287  }
288  printf("%s\n", message);
289}
290
291void PrintResult(const char* prefix, int fft_log_size, double elapsed_time,
292                 int count) {
293  if (verbose == 0) {
294    printf("%2d\t%8.4f\t%8d\t%.4e\n",
295           fft_log_size, elapsed_time, count, 1000 * elapsed_time / count);
296  } else {
297    printf("%-18s:  order %2d:  %8.4f sec for %8d FFTs:  %.4e msec/FFT\n",
298           prefix, fft_log_size, elapsed_time, count,
299           1000 * elapsed_time / count);
300  }
301}
302
303int ComputeCount(int nominal_count, int fft_log_size) {
304  /*
305   * Try to figure out how many repetitions to do for a given FFT
306   * order (fft_log_size) given that we want a repetition of
307   * nominal_count for order 15 FFTs to be the approsimate amount of
308   * time we want to for all tests.
309   */
310
311  int count;
312  if (adapt_count) {
313    double maxTime = ((double) nominal_count) * (1 << MAX_FFT_ORDER)
314        * MAX_FFT_ORDER;
315    double c = maxTime / ((1 << fft_log_size) * fft_log_size);
316    const int max_count = 10000000;
317
318    count = (c > max_count) ? max_count : c;
319  } else {
320    count = nominal_count;
321  }
322
323  return count;
324}
325
326#if defined(__arm__) || defined(__aarch64__)
327void TimeOneFloatFFT(int count, int fft_log_size, float signal_value,
328                     int signal_type) {
329  struct AlignedPtr* x_aligned;
330  struct AlignedPtr* y_aligned;
331  struct AlignedPtr* z_aligned;
332
333  struct ComplexFloat* x;
334  struct ComplexFloat* y;
335  OMX_FC32* z;
336
337  struct ComplexFloat* y_true;
338
339  OMX_INT n, fft_spec_buffer_size;
340  OMXFFTSpec_C_FC32 * fft_fwd_spec = NULL;
341  OMXFFTSpec_C_FC32 * fft_inv_spec = NULL;
342  int fft_size;
343  struct timeval start_time;
344  struct timeval end_time;
345  double elapsed_time;
346
347  fft_size = 1 << fft_log_size;
348
349  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
350  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
351  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
352
353  y_true = (struct ComplexFloat*) malloc(sizeof(*y_true) * fft_size);
354
355  x = x_aligned->aligned_pointer_;
356  y = y_aligned->aligned_pointer_;
357  z = z_aligned->aligned_pointer_;
358
359  GenerateTestSignalAndFFT(x, y_true, fft_size, signal_type, signal_value, 0);
360
361  omxSP_FFTGetBufSize_C_FC32(fft_log_size, &fft_spec_buffer_size);
362
363  fft_fwd_spec = (OMXFFTSpec_C_FC32*) malloc(fft_spec_buffer_size);
364  fft_inv_spec = (OMXFFTSpec_C_FC32*) malloc(fft_spec_buffer_size);
365  omxSP_FFTInit_C_FC32(fft_fwd_spec, fft_log_size);
366  omxSP_FFTInit_C_FC32(fft_inv_spec, fft_log_size);
367
368  if (do_forward_test) {
369    GetUserTime(&start_time);
370    for (n = 0; n < count; ++n) {
371      FORWARD_FLOAT_FFT((OMX_FC32*) x, (OMX_FC32*) y, fft_fwd_spec);
372    }
373    GetUserTime(&end_time);
374
375    elapsed_time = TimeDifference(&start_time, &end_time);
376
377    PrintResult("Forward Float FFT", fft_log_size, elapsed_time, count);
378  }
379
380  if (do_inverse_test) {
381    GetUserTime(&start_time);
382    for (n = 0; n < count; ++n) {
383      INVERSE_FLOAT_FFT((OMX_FC32*) y, z, fft_inv_spec);
384    }
385    GetUserTime(&end_time);
386
387    elapsed_time = TimeDifference(&start_time, &end_time);
388
389    PrintResult("Inverse Float FFT", fft_log_size, elapsed_time, count);
390  }
391
392  FreeAlignedPointer(x_aligned);
393  FreeAlignedPointer(y_aligned);
394  FreeAlignedPointer(z_aligned);
395  free(y_true);
396  free(fft_fwd_spec);
397  free(fft_inv_spec);
398}
399
400void TimeFloatFFT(int count, float signal_value, int signal_type) {
401  int k;
402
403  if (verbose == 0)
404    PrintShortHeader("Float FFT");
405
406  for (k = min_fft_order; k <= max_fft_order; ++k) {
407    int testCount = ComputeCount(count, k);
408    TimeOneFloatFFT(testCount, k, signal_value, signal_type);
409  }
410}
411#endif
412
413void GenerateRealFloatSignal(OMX_F32* x, OMX_FC32* fft, int size,
414                             int signal_type, float signal_value)
415{
416  int k;
417  struct ComplexFloat *test_signal;
418  struct ComplexFloat *true_fft;
419
420  test_signal = (struct ComplexFloat*) malloc(sizeof(*test_signal) * size);
421  true_fft = (struct ComplexFloat*) malloc(sizeof(*true_fft) * size);
422  GenerateTestSignalAndFFT(test_signal, true_fft, size, signal_type,
423                           signal_value, 1);
424
425  /*
426   * Convert the complex result to what we want
427   */
428
429  for (k = 0; k < size; ++k) {
430    x[k] = test_signal[k].Re;
431  }
432
433  for (k = 0; k < size / 2 + 1; ++k) {
434    fft[k].Re = true_fft[k].Re;
435    fft[k].Im = true_fft[k].Im;
436  }
437
438  free(test_signal);
439  free(true_fft);
440}
441
442void TimeOneFloatRFFT(int count, int fft_log_size, float signal_value,
443                      int signal_type) {
444  OMX_F32* x;                   /* Source */
445  OMX_F32* y;                   /* Transform */
446  OMX_F32* z;                   /* Inverse transform */
447
448  OMX_F32* y_true;              /* True FFT */
449
450  struct AlignedPtr* x_aligned;
451  struct AlignedPtr* y_aligned;
452  struct AlignedPtr* z_aligned;
453
454
455  OMX_INT n, fft_spec_buffer_size;
456  OMXResult status;
457  OMXFFTSpec_R_F32 * fft_fwd_spec = NULL;
458  OMXFFTSpec_R_F32 * fft_inv_spec = NULL;
459  int fft_size;
460  struct timeval start_time;
461  struct timeval end_time;
462  double elapsed_time;
463
464  fft_size = 1 << fft_log_size;
465
466  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
467  /* The transformed value is in CCS format and is has fft_size + 2 values */
468  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
469  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
470
471  x = x_aligned->aligned_pointer_;
472  y = y_aligned->aligned_pointer_;
473  z = z_aligned->aligned_pointer_;
474
475  y_true = (OMX_F32*) malloc(sizeof(*y_true) * (fft_size + 2));
476
477  GenerateRealFloatSignal(x, (OMX_FC32*) y_true, fft_size, signal_type,
478                          signal_value);
479
480  status = omxSP_FFTGetBufSize_R_F32(fft_log_size, &fft_spec_buffer_size);
481
482  fft_fwd_spec = (OMXFFTSpec_R_F32*) malloc(fft_spec_buffer_size);
483  fft_inv_spec = (OMXFFTSpec_R_F32*) malloc(fft_spec_buffer_size);
484  status = omxSP_FFTInit_R_F32(fft_fwd_spec, fft_log_size);
485
486  status = omxSP_FFTInit_R_F32(fft_inv_spec, fft_log_size);
487
488  if (do_forward_test) {
489    GetUserTime(&start_time);
490    for (n = 0; n < count; ++n) {
491      FORWARD_FLOAT_RFFT(x, y, fft_fwd_spec);
492    }
493    GetUserTime(&end_time);
494
495    elapsed_time = TimeDifference(&start_time, &end_time);
496
497    PrintResult("Forward Float RFFT", fft_log_size, elapsed_time, count);
498  }
499
500  if (do_inverse_test) {
501    GetUserTime(&start_time);
502    for (n = 0; n < count; ++n) {
503      INVERSE_FLOAT_RFFT(y, z, fft_inv_spec);
504    }
505    GetUserTime(&end_time);
506
507    elapsed_time = TimeDifference(&start_time, &end_time);
508
509    PrintResult("Inverse Float RFFT", fft_log_size, elapsed_time, count);
510  }
511
512  FreeAlignedPointer(x_aligned);
513  FreeAlignedPointer(y_aligned);
514  FreeAlignedPointer(z_aligned);
515  free(fft_fwd_spec);
516  free(fft_inv_spec);
517}
518
519void TimeFloatRFFT(int count, float signal_value, int signal_type) {
520  int k;
521
522  if (verbose == 0)
523    PrintShortHeader("Float RFFT");
524
525  for (k = min_fft_order; k <= max_fft_order; ++k) {
526    int testCount = ComputeCount(count, k);
527    TimeOneFloatRFFT(testCount, k, signal_value, signal_type);
528  }
529}
530
531#ifdef ENABLE_FIXED_POINT_FFT_TESTS
532void generateSC32Signal(OMX_SC32* x, OMX_SC32* fft, int size, int signal_type,
533                        float signal_value) {
534  int k;
535  struct ComplexFloat *test_signal;
536  struct ComplexFloat *true_fft;
537
538  test_signal = (struct ComplexFloat*) malloc(sizeof(*test_signal) * size);
539  true_fft = (struct ComplexFloat*) malloc(sizeof(*true_fft) * size);
540  GenerateTestSignalAndFFT(test_signal, true_fft, size, signal_type,
541                           signal_value, 0);
542
543  /*
544   * Convert the complex result to what we want
545   */
546
547  for (k = 0; k < size; ++k) {
548    x[k].Re = 0.5 + test_signal[k].Re;
549    x[k].Im = 0.5 + test_signal[k].Im;
550    fft[k].Re = 0.5 + true_fft[k].Re;
551    fft[k].Im = 0.5 + true_fft[k].Im;
552  }
553
554  free(test_signal);
555  free(true_fft);
556}
557
558void TimeOneSC32FFT(int count, int fft_log_size, float signal_value,
559                    int signal_type) {
560  OMX_SC32* x;
561  OMX_SC32* y;
562  OMX_SC32* z;
563
564  struct AlignedPtr* x_aligned;
565  struct AlignedPtr* y_aligned;
566  struct AlignedPtr* z_aligned;
567
568  OMX_SC32* y_true;
569  OMX_SC32* temp32a;
570  OMX_SC32* temp32b;
571
572  OMX_INT n, fft_spec_buffer_size;
573  OMXResult status;
574  OMXFFTSpec_C_SC32 * fft_fwd_spec = NULL;
575  OMXFFTSpec_C_SC32 * fft_inv_spec = NULL;
576  int fft_size;
577  struct timeval start_time;
578  struct timeval end_time;
579  double elapsed_time;
580
581  fft_size = 1 << fft_log_size;
582
583  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
584  y_aligned = AllocAlignedPointer(32, sizeof(*y) * fft_size);
585  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
586  y_true = (OMX_SC32*) malloc(sizeof(*y_true) * fft_size);
587  temp32a = (OMX_SC32*) malloc(sizeof(*temp32a) * fft_size);
588  temp32b = (OMX_SC32*) malloc(sizeof(*temp32b) * fft_size);
589
590  x = x_aligned->aligned_pointer_;
591  y = y_aligned->aligned_pointer_;
592  z = z_aligned->aligned_pointer_;
593
594  generateSC32Signal(x, y_true, fft_size, signal_type, signal_value);
595
596  status = omxSP_FFTGetBufSize_C_SC32(fft_log_size, &fft_spec_buffer_size);
597
598  fft_fwd_spec = (OMXFFTSpec_C_SC32*) malloc(fft_spec_buffer_size);
599  fft_inv_spec = (OMXFFTSpec_C_SC32*) malloc(fft_spec_buffer_size);
600  status = omxSP_FFTInit_C_SC32(fft_fwd_spec, fft_log_size);
601
602  status = omxSP_FFTInit_C_SC32(fft_inv_spec, fft_log_size);
603
604  if (do_forward_test) {
605    if (include_conversion) {
606      int k;
607      float factor = -1;
608
609      GetUserTime(&start_time);
610      for (k = 0; k < count; ++k) {
611        for (n = 0; n < fft_size; ++n) {
612          if (fabs(x[n].Re) > factor) {
613            factor = fabs(x[n].Re);
614          }
615          if (fabs(x[n].Im) > factor) {
616            factor = fabs(x[n].Im);
617          }
618        }
619
620        factor = ((1 << 18) - 1) / factor;
621        for (n = 0; n < fft_size; ++n) {
622          temp32a[n].Re = factor * x[n].Re;
623          temp32a[n].Im = factor * x[n].Im;
624        }
625
626        omxSP_FFTFwd_CToC_SC32_Sfs(x, y, fft_fwd_spec, 0);
627
628        factor = 1 / factor;
629        for (n = 0; n < fft_size; ++n) {
630          temp32b[n].Re = y[n].Re * factor;
631          temp32b[n].Im = y[n].Im * factor;
632        }
633      }
634      GetUserTime(&end_time);
635    } else {
636      GetUserTime(&start_time);
637      for (n = 0; n < count; ++n) {
638        omxSP_FFTFwd_CToC_SC32_Sfs(x, y, fft_fwd_spec, 0);
639      }
640      GetUserTime(&end_time);
641    }
642
643    elapsed_time = TimeDifference(&start_time, &end_time);
644
645    PrintResult("Forward SC32 FFT", fft_log_size, elapsed_time, count);
646  }
647
648  if (do_inverse_test) {
649    if (include_conversion) {
650      int k;
651      float factor = -1;
652
653      GetUserTime(&start_time);
654      for (k = 0; k < count; ++k) {
655        for (n = 0; n < fft_size; ++n) {
656          if (fabs(x[n].Re) > factor) {
657            factor = fabs(x[n].Re);
658          }
659          if (fabs(x[n].Im) > factor) {
660            factor = fabs(x[n].Im);
661          }
662        }
663        factor = ((1 << 18) - 1) / factor;
664        for (n = 0; n < fft_size; ++n) {
665          temp32a[n].Re = factor * x[n].Re;
666          temp32a[n].Im = factor * x[n].Im;
667        }
668
669        status = omxSP_FFTInv_CToC_SC32_Sfs(y, z, fft_inv_spec, 0);
670
671        factor = 1 / factor;
672        for (n = 0; n < fft_size; ++n) {
673          temp32b[n].Re = y[n].Re * factor;
674          temp32b[n].Im = y[n].Im * factor;
675        }
676      }
677      GetUserTime(&end_time);
678    } else {
679      GetUserTime(&start_time);
680      for (n = 0; n < count; ++n) {
681        status = omxSP_FFTInv_CToC_SC32_Sfs(y, z, fft_inv_spec, 0);
682      }
683      GetUserTime(&end_time);
684    }
685
686    elapsed_time = TimeDifference(&start_time, &end_time);
687
688    PrintResult("Inverse SC32 FFT", fft_log_size, elapsed_time, count);
689  }
690
691  FreeAlignedPointer(x_aligned);
692  FreeAlignedPointer(y_aligned);
693  FreeAlignedPointer(z_aligned);
694  free(temp32a);
695  free(temp32b);
696  free(fft_fwd_spec);
697  free(fft_inv_spec);
698}
699
700void TimeSC32FFT(int count, float signal_value, int signal_type) {
701  int k;
702  int max_order = (max_fft_order > MAX_FFT_ORDER_FIXED_POINT)
703      ? MAX_FFT_ORDER_FIXED_POINT : max_fft_order;
704
705  if (verbose == 0)
706    PrintShortHeader("SC32 FFT");
707
708  for (k = min_fft_order; k <= max_order; ++k) {
709    int testCount = ComputeCount(count, k);
710    TimeOneSC32FFT(testCount, k, signal_value, signal_type);
711  }
712}
713
714void generateSC16Signal(OMX_SC16* x, OMX_SC16* fft, int size, int signal_type,
715                        float signal_value) {
716  int k;
717  struct ComplexFloat *test_signal;
718  struct ComplexFloat *true_fft;
719
720  test_signal = (struct ComplexFloat*) malloc(sizeof(*test_signal) * size);
721  true_fft = (struct ComplexFloat*) malloc(sizeof(*true_fft) * size);
722  GenerateTestSignalAndFFT(test_signal, true_fft, size, signal_type,
723                           signal_value, 0);
724
725  /*
726   * Convert the complex result to what we want
727   */
728
729  for (k = 0; k < size; ++k) {
730    x[k].Re = 0.5 + test_signal[k].Re;
731    x[k].Im = 0.5 + test_signal[k].Im;
732    fft[k].Re = 0.5 + true_fft[k].Re;
733    fft[k].Im = 0.5 + true_fft[k].Im;
734  }
735
736  free(test_signal);
737  free(true_fft);
738}
739
740void TimeOneSC16FFT(int count, int fft_log_size, float signal_value,
741                    int signal_type) {
742  OMX_SC16* x;
743  OMX_SC16* y;
744  OMX_SC16* z;
745
746  struct AlignedPtr* x_aligned;
747  struct AlignedPtr* y_aligned;
748  struct AlignedPtr* z_aligned;
749
750  OMX_SC16* y_true;
751  OMX_SC16* temp16a;
752  OMX_SC16* temp16b;
753
754  OMX_INT n, fft_spec_buffer_size;
755  OMXResult status;
756  OMXFFTSpec_C_SC16 * fft_fwd_spec = NULL;
757  OMXFFTSpec_C_SC16 * fft_inv_spec = NULL;
758  int fft_size;
759  struct timeval start_time;
760  struct timeval end_time;
761  double elapsed_time;
762
763  fft_size = 1 << fft_log_size;
764
765  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
766  y_aligned = AllocAlignedPointer(32, sizeof(*y) * fft_size);
767  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
768  y_true = (OMX_SC16*) malloc(sizeof(*y_true) * fft_size);
769  temp16a = (OMX_SC16*) malloc(sizeof(*temp16a) * fft_size);
770  temp16b = (OMX_SC16*) malloc(sizeof(*temp16b) * fft_size);
771
772  x = x_aligned->aligned_pointer_;
773  y = y_aligned->aligned_pointer_;
774  z = z_aligned->aligned_pointer_;
775
776  generateSC16Signal(x, y_true, fft_size, signal_type, signal_value);
777
778  status = omxSP_FFTGetBufSize_C_SC16(fft_log_size, &fft_spec_buffer_size);
779
780  fft_fwd_spec = (OMXFFTSpec_C_SC16*) malloc(fft_spec_buffer_size);
781  fft_inv_spec = (OMXFFTSpec_C_SC16*) malloc(fft_spec_buffer_size);
782  status = omxSP_FFTInit_C_SC16(fft_fwd_spec, fft_log_size);
783
784  status = omxSP_FFTInit_C_SC16(fft_inv_spec, fft_log_size);
785
786  if (do_forward_test) {
787    if (include_conversion) {
788      int k;
789      float factor = -1;
790
791      GetUserTime(&start_time);
792      for (k = 0; k < count; ++k) {
793        for (n = 0; n < fft_size; ++n) {
794          if (fabs(x[n].Re) > factor) {
795            factor = fabs(x[n].Re);
796          }
797          if (fabs(x[n].Im) > factor) {
798            factor = fabs(x[n].Im);
799          }
800        }
801
802        factor = ((1 << 15) - 1) / factor;
803        for (n = 0; n < fft_size; ++n) {
804          temp16a[n].Re = factor * x[n].Re;
805          temp16a[n].Im = factor * x[n].Im;
806        }
807
808        omxSP_FFTFwd_CToC_SC16_Sfs(x, y, fft_fwd_spec, 0);
809
810        factor = 1 / factor;
811        for (n = 0; n < fft_size; ++n) {
812          temp16b[n].Re = y[n].Re * factor;
813          temp16b[n].Im = y[n].Im * factor;
814        }
815      }
816      GetUserTime(&end_time);
817    } else {
818      GetUserTime(&start_time);
819      for (n = 0; n < count; ++n) {
820        omxSP_FFTFwd_CToC_SC16_Sfs(x, y, fft_fwd_spec, 0);
821      }
822      GetUserTime(&end_time);
823    }
824
825    elapsed_time = TimeDifference(&start_time, &end_time);
826
827    PrintResult("Forward SC16 FFT", fft_log_size, elapsed_time, count);
828  }
829
830  if (do_inverse_test) {
831    if (include_conversion) {
832      int k;
833      float factor = -1;
834
835      GetUserTime(&start_time);
836      for (k = 0; k < count; ++k) {
837        for (n = 0; n < fft_size; ++n) {
838          if (fabs(x[n].Re) > factor) {
839            factor = fabs(x[n].Re);
840          }
841          if (fabs(x[n].Im) > factor) {
842            factor = fabs(x[n].Im);
843          }
844        }
845        factor = ((1 << 15) - 1) / factor;
846        for (n = 0; n < fft_size; ++n) {
847          temp16a[n].Re = factor * x[n].Re;
848          temp16a[n].Im = factor * x[n].Im;
849        }
850
851        status = omxSP_FFTInv_CToC_SC16_Sfs(y, z, fft_inv_spec, 0);
852
853        factor = 1 / factor;
854        for (n = 0; n < fft_size; ++n) {
855          temp16b[n].Re = y[n].Re * factor;
856          temp16b[n].Im = y[n].Im * factor;
857        }
858      }
859      GetUserTime(&end_time);
860    } else {
861      GetUserTime(&start_time);
862      for (n = 0; n < count; ++n) {
863        status = omxSP_FFTInv_CToC_SC16_Sfs(y, z, fft_inv_spec, 0);
864      }
865      GetUserTime(&end_time);
866    }
867
868    elapsed_time = TimeDifference(&start_time, &end_time);
869
870    PrintResult("Inverse SC16 FFT", fft_log_size, elapsed_time, count);
871  }
872
873  FreeAlignedPointer(x_aligned);
874  FreeAlignedPointer(y_aligned);
875  FreeAlignedPointer(z_aligned);
876  free(temp16a);
877  free(temp16b);
878  free(fft_fwd_spec);
879  free(fft_inv_spec);
880}
881
882void TimeSC16FFT(int count, float signal_value, int signal_type) {
883  int k;
884  int max_order = (max_fft_order > MAX_FFT_ORDER_FIXED_POINT)
885      ? MAX_FFT_ORDER_FIXED_POINT : max_fft_order;
886
887  if (verbose == 0)
888    PrintShortHeader("SC16 FFT");
889
890  for (k = min_fft_order; k <= max_order; ++k) {
891    int testCount = ComputeCount(count, k);
892    TimeOneSC16FFT(testCount, k, signal_value, signal_type);
893  }
894}
895
896void GenerateRFFT16Signal(OMX_S16* x, OMX_SC32* fft, int size, int signal_type,
897                          float signal_value) {
898  int k;
899  struct ComplexFloat *test_signal;
900  struct ComplexFloat *true_fft;
901
902  test_signal = (struct ComplexFloat*) malloc(sizeof(*test_signal) * size);
903  true_fft = (struct ComplexFloat*) malloc(sizeof(*true_fft) * size);
904  GenerateTestSignalAndFFT(test_signal, true_fft, size, signal_type,
905                           signal_value, 1);
906
907  /*
908   * Convert the complex result to what we want
909   */
910
911  for (k = 0; k < size; ++k) {
912    x[k] = test_signal[k].Re;
913  }
914
915  for (k = 0; k < size / 2 + 1; ++k) {
916    fft[k].Re = true_fft[k].Re;
917    fft[k].Im = true_fft[k].Im;
918  }
919
920  free(test_signal);
921  free(true_fft);
922}
923
924/* Argument s16s32:
925 *     S32:       Calculate RFFT16 with 32 bit complex FFT;
926 *     otherwise: Calculate RFFT16 with 16 bit complex FFT.
927 */
928void TimeOneRFFT16(int count, int fft_log_size, float signal_value,
929                   int signal_type, s16_s32 s16s32) {
930  OMX_S16* x;
931  OMX_S32* y;
932  OMX_S16* z;
933  OMX_S32* y_true;
934  OMX_F32* xr;
935  OMX_F32* yrTrue;
936
937  struct AlignedPtr* x_aligned;
938  struct AlignedPtr* y_aligned;
939  struct AlignedPtr* z_aligned;
940  struct AlignedPtr* y_trueAligned;
941  struct AlignedPtr* xr_aligned;
942  struct AlignedPtr* yr_true_aligned;
943
944
945  OMX_S16* temp16;
946  OMX_S32* temp32;
947
948
949  OMX_INT n, fft_spec_buffer_size;
950  OMXResult status;
951  OMXFFTSpec_R_S16 * fft_fwd_spec = NULL;
952  OMXFFTSpec_R_S16 * fft_inv_spec = NULL;
953  int fft_size;
954  struct timeval start_time;
955  struct timeval end_time;
956  double elapsed_time;
957  int scaleFactor;
958
959  fft_size = 1 << fft_log_size;
960  scaleFactor = fft_log_size;
961
962  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
963  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
964  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
965
966  y_trueAligned = AllocAlignedPointer(32, sizeof(*y_true) * (fft_size + 2));
967
968  xr_aligned = AllocAlignedPointer(32, sizeof(*xr) * fft_size);
969  yr_true_aligned = AllocAlignedPointer(32, sizeof(*yrTrue) * (fft_size + 2));
970
971  x = x_aligned->aligned_pointer_;
972  y = y_aligned->aligned_pointer_;
973  z = z_aligned->aligned_pointer_;
974  y_true = y_trueAligned->aligned_pointer_;
975  xr = xr_aligned->aligned_pointer_;
976  yrTrue = yr_true_aligned->aligned_pointer_;
977
978  temp16 = (OMX_S16*) malloc(sizeof(*temp16) * fft_size);
979  temp32 = (OMX_S32*) malloc(sizeof(*temp32) * fft_size);
980
981
982  GenerateRFFT16Signal(x, (OMX_SC32*) y_true, fft_size, signal_type,
983                       signal_value);
984  /*
985   * Generate a real version so we can measure scaling costs
986   */
987  GenerateRealFloatSignal(xr, (OMX_FC32*) yrTrue, fft_size, signal_type,
988                          signal_value);
989
990  if(s16s32 == S32) {
991    status = omxSP_FFTGetBufSize_R_S16S32(fft_log_size, &fft_spec_buffer_size);
992    fft_fwd_spec = malloc(fft_spec_buffer_size);
993    fft_inv_spec = malloc(fft_spec_buffer_size);
994    status = omxSP_FFTInit_R_S16S32(fft_fwd_spec, fft_log_size);
995    status = omxSP_FFTInit_R_S16S32(fft_inv_spec, fft_log_size);
996  }
997  else {
998    status = omxSP_FFTGetBufSize_R_S16(fft_log_size, &fft_spec_buffer_size);
999    fft_fwd_spec = malloc(fft_spec_buffer_size);
1000    fft_inv_spec = malloc(fft_spec_buffer_size);
1001    status = omxSP_FFTInit_R_S16(fft_fwd_spec, fft_log_size);
1002    status = omxSP_FFTInit_R_S16(fft_inv_spec, fft_log_size);
1003  }
1004
1005  if (do_forward_test) {
1006    if (include_conversion) {
1007      int k;
1008      float factor = -1;
1009
1010      GetUserTime(&start_time);
1011      for (k = 0; k < count; ++k) {
1012        /*
1013         * Spend some time computing the max of the signal, and then scaling it.
1014         */
1015        for (n = 0; n < fft_size; ++n) {
1016          if (fabs(xr[n]) > factor) {
1017            factor = fabs(xr[n]);
1018          }
1019        }
1020
1021        factor = 32767 / factor;
1022        for (n = 0; n < fft_size; ++n) {
1023          temp16[n] = factor * xr[n];
1024        }
1025
1026        if(s16s32 == S32) {
1027          status = omxSP_FFTFwd_RToCCS_S16S32_Sfs(x, y,
1028              (OMXFFTSpec_R_S16S32*)fft_fwd_spec, (OMX_INT) scaleFactor);
1029        }
1030        else {
1031          status = omxSP_FFTFwd_RToCCS_S16_Sfs(x,  (OMX_S16*)y,
1032              (OMXFFTSpec_R_S16*)fft_fwd_spec, (OMX_INT) scaleFactor);
1033        }
1034        /*
1035         * Now spend some time converting the fixed-point FFT back to float.
1036         */
1037        factor = 1 / factor;
1038        for (n = 0; n < fft_size + 2; ++n) {
1039          xr[n] = y[n] * factor;
1040        }
1041      }
1042      GetUserTime(&end_time);
1043    } else {
1044      float factor = -1;
1045
1046      GetUserTime(&start_time);
1047      for (n = 0; n < count; ++n) {
1048      if(s16s32 == S32) {
1049        status = omxSP_FFTFwd_RToCCS_S16S32_Sfs(x, y,
1050            (OMXFFTSpec_R_S16S32*)fft_fwd_spec, (OMX_INT) scaleFactor);
1051      }
1052      else {
1053        status = omxSP_FFTFwd_RToCCS_S16_Sfs(x, (OMX_S16*)y,
1054            (OMXFFTSpec_R_S16*)fft_fwd_spec, (OMX_INT) scaleFactor);
1055      }
1056      }
1057      GetUserTime(&end_time);
1058    }
1059
1060    elapsed_time = TimeDifference(&start_time, &end_time);
1061
1062    if(s16s32 == S32) {
1063      PrintResult("Forward RFFT16 (with S32)",
1064                  fft_log_size, elapsed_time, count);
1065    }
1066    else {
1067      PrintResult("Forward RFFT16 (with S16)",
1068                  fft_log_size, elapsed_time, count);
1069    }
1070  }
1071
1072  if (do_inverse_test) {
1073    if (include_conversion) {
1074      int k;
1075      float factor = -1;
1076
1077      GetUserTime(&start_time);
1078      for (k = 0; k < count; ++k) {
1079        /*
1080         * Spend some time scaling the FFT signal to fixed point.
1081         */
1082        for (n = 0; n < fft_size; ++n) {
1083          if (fabs(yrTrue[n]) > factor) {
1084            factor = fabs(yrTrue[n]);
1085          }
1086        }
1087        for (n = 0; n < fft_size; ++n) {
1088          temp32[n] = factor * yrTrue[n];
1089        }
1090
1091        if(s16s32 == S32) {
1092          status = omxSP_FFTInv_CCSToR_S32S16_Sfs(y, z,
1093              (OMXFFTSpec_R_S16S32*)fft_inv_spec, 0);
1094        }
1095        else {
1096          status = omxSP_FFTInv_CCSToR_S16_Sfs((OMX_S16*)y, z,
1097              (OMXFFTSpec_R_S16*)fft_inv_spec, 0);
1098        }
1099        /*
1100         * Spend some time converting the result back to float
1101         */
1102        factor = 1 / factor;
1103        for (n = 0; n < fft_size; ++n) {
1104          xr[n] = factor * z[n];
1105        }
1106      }
1107      GetUserTime(&end_time);
1108    } else {
1109      GetUserTime(&start_time);
1110      for (n = 0; n < count; ++n) {
1111        if(s16s32 == S32) {
1112          status = omxSP_FFTInv_CCSToR_S32S16_Sfs(y, z,
1113              (OMXFFTSpec_R_S16S32*)fft_inv_spec, 0);
1114        }
1115        else {
1116          status = omxSP_FFTInv_CCSToR_S16_Sfs((OMX_S16*)y, z,
1117              (OMXFFTSpec_R_S16*)fft_inv_spec, 0);
1118        }
1119      }
1120      GetUserTime(&end_time);
1121    }
1122
1123    elapsed_time = TimeDifference(&start_time, &end_time);
1124
1125    if(s16s32 == S32) {
1126      PrintResult("Inverse RFFT16 (with S32)",
1127                  fft_log_size, elapsed_time, count);
1128    }
1129    else {
1130      PrintResult("Inverse RFFT16 (with S16)",
1131                  fft_log_size, elapsed_time, count);
1132    }
1133  }
1134
1135  FreeAlignedPointer(x_aligned);
1136  FreeAlignedPointer(y_aligned);
1137  FreeAlignedPointer(z_aligned);
1138  FreeAlignedPointer(y_trueAligned);
1139  FreeAlignedPointer(xr_aligned);
1140  FreeAlignedPointer(yr_true_aligned);
1141  free(fft_fwd_spec);
1142  free(fft_inv_spec);
1143}
1144
1145void TimeRFFT16(int count, float signal_value, int signal_type) {
1146  int k;
1147  int max_order = (max_fft_order > MAX_FFT_ORDER_FIXED_POINT)
1148      ? MAX_FFT_ORDER_FIXED_POINT : max_fft_order;
1149
1150  if (verbose == 0)
1151    PrintShortHeader("RFFT16 (with S32)");
1152
1153  for (k = min_fft_order; k <= max_order; ++k) {
1154    int testCount = ComputeCount(count, k);
1155    TimeOneRFFT16(testCount, k, signal_value, signal_type, 1);
1156  }
1157
1158  if (verbose == 0)
1159    PrintShortHeader("RFFT16 (with S16)");
1160
1161  for (k = min_fft_order; k <= max_order; ++k) {
1162    int testCount = ComputeCount(count, k);
1163    TimeOneRFFT16(testCount, k, signal_value, signal_type, 0);
1164  }
1165}
1166
1167void GenerateRFFT32Signal(OMX_S32* x, OMX_SC32* fft, int size, int signal_type,
1168                          float signal_value) {
1169  int k;
1170  struct ComplexFloat *test_signal;
1171  struct ComplexFloat *true_fft;
1172
1173  test_signal = (struct ComplexFloat*) malloc(sizeof(*test_signal) * size);
1174  true_fft = (struct ComplexFloat*) malloc(sizeof(*true_fft) * size);
1175  GenerateTestSignalAndFFT(test_signal, true_fft, size, signal_type,
1176                           signal_value, 1);
1177
1178  /*
1179   * Convert the complex result to what we want
1180   */
1181
1182  for (k = 0; k < size; ++k) {
1183    x[k] = test_signal[k].Re;
1184  }
1185
1186  for (k = 0; k < size / 2 + 1; ++k) {
1187    fft[k].Re = true_fft[k].Re;
1188    fft[k].Im = true_fft[k].Im;
1189  }
1190
1191  free(test_signal);
1192  free(true_fft);
1193}
1194
1195void TimeOneRFFT32(int count, int fft_log_size, float signal_value,
1196                   int signal_type) {
1197  OMX_S32* x;
1198  OMX_S32* y;
1199  OMX_S32* z;
1200  OMX_S32* y_true;
1201  OMX_F32* xr;
1202  OMX_F32* yrTrue;
1203
1204  struct AlignedPtr* x_aligned;
1205  struct AlignedPtr* y_aligned;
1206  struct AlignedPtr* z_aligned;
1207  struct AlignedPtr* y_true_aligned;
1208
1209  OMX_S32* temp1;
1210  OMX_S32* temp2;
1211
1212  OMX_INT n, fft_spec_buffer_size;
1213  OMXResult status;
1214  OMXFFTSpec_R_S16S32 * fft_fwd_spec = NULL;
1215  OMXFFTSpec_R_S16S32 * fft_inv_spec = NULL;
1216  int fft_size;
1217  struct timeval start_time;
1218  struct timeval end_time;
1219  double elapsed_time;
1220  int scaleFactor;
1221
1222  fft_size = 1 << fft_log_size;
1223
1224  x_aligned = AllocAlignedPointer(32, sizeof(*x) * fft_size);
1225  y_aligned = AllocAlignedPointer(32, sizeof(*y) * (fft_size + 2));
1226  z_aligned = AllocAlignedPointer(32, sizeof(*z) * fft_size);
1227
1228  y_true_aligned = AllocAlignedPointer(32, sizeof(*y_true) * (fft_size + 2));
1229
1230  x = x_aligned->aligned_pointer_;
1231  y = y_aligned->aligned_pointer_;
1232  z = z_aligned->aligned_pointer_;
1233  y_true = y_true_aligned->aligned_pointer_;
1234
1235  if (verbose > 3) {
1236    printf("x = %p\n", (void*)x);
1237    printf("y = %p\n", (void*)y);
1238    printf("z = %p\n", (void*)z);
1239  }
1240
1241  xr = (OMX_F32*) malloc(sizeof(*x) * fft_size);
1242  yrTrue = (OMX_F32*) malloc(sizeof(*y) * (fft_size + 2));
1243  temp1 = (OMX_S32*) malloc(sizeof(*temp1) * fft_size);
1244  temp2 = (OMX_S32*) malloc(sizeof(*temp2) * (fft_size + 2));
1245
1246  GenerateRFFT32Signal(x, (OMX_SC32*) y_true, fft_size, signal_type,
1247                       signal_value);
1248
1249  if (verbose > 63) {
1250    printf("Signal\n");
1251    printf("n\tx[n]\n");
1252    for (n = 0; n < fft_size; ++n) {
1253      printf("%4d\t%d\n", n, x[n]);
1254    }
1255  }
1256
1257  status = omxSP_FFTGetBufSize_R_S32(fft_log_size, &fft_spec_buffer_size);
1258  if (verbose > 3) {
1259    printf("fft_spec_buffer_size = %d\n", fft_spec_buffer_size);
1260  }
1261
1262  fft_fwd_spec = (OMXFFTSpec_R_S32*) malloc(fft_spec_buffer_size);
1263  fft_inv_spec = (OMXFFTSpec_R_S32*) malloc(fft_spec_buffer_size);
1264  status = omxSP_FFTInit_R_S32(fft_fwd_spec, fft_log_size);
1265  if (status) {
1266    printf("Failed to init forward FFT:  status = %d\n", status);
1267  }
1268
1269  status = omxSP_FFTInit_R_S32(fft_inv_spec, fft_log_size);
1270  if (status) {
1271    printf("Failed to init backward FFT:  status = %d\n", status);
1272  }
1273
1274  if (do_forward_test) {
1275    if (include_conversion) {
1276      int k;
1277      float factor = -1;
1278
1279      GetUserTime(&start_time);
1280      for (k = 0; k < count; ++k) {
1281        /*
1282         * Spend some time computing the max of the signal, and then scaling it.
1283         */
1284        for (n = 0; n < fft_size; ++n) {
1285          if (fabs(xr[n]) > factor) {
1286            factor = fabs(xr[n]);
1287          }
1288        }
1289
1290        factor = (1 << 20) / factor;
1291        for (n = 0; n < fft_size; ++n) {
1292          temp1[n] = factor * xr[n];
1293        }
1294
1295        status = omxSP_FFTFwd_RToCCS_S32_Sfs(x, y, fft_fwd_spec,
1296                                             (OMX_INT) scaleFactor);
1297
1298        /*
1299         * Now spend some time converting the fixed-point FFT back to float.
1300         */
1301        factor = 1 / factor;
1302        for (n = 0; n < fft_size + 2; ++n) {
1303          xr[n] = y[n] * factor;
1304        }
1305      }
1306      GetUserTime(&end_time);
1307    } else {
1308      float factor = -1;
1309
1310      GetUserTime(&start_time);
1311      for (n = 0; n < count; ++n) {
1312        status = omxSP_FFTFwd_RToCCS_S32_Sfs(x, y, fft_fwd_spec,
1313                                             (OMX_INT) scaleFactor);
1314      }
1315      GetUserTime(&end_time);
1316    }
1317
1318    elapsed_time = TimeDifference(&start_time, &end_time);
1319
1320    PrintResult("Forward RFFT32", fft_log_size, elapsed_time, count);
1321  }
1322
1323  if (do_inverse_test) {
1324    if (include_conversion) {
1325      int k;
1326      float factor = -1;
1327
1328      GetUserTime(&start_time);
1329      for (k = 0; k < count; ++k) {
1330        /*
1331         * Spend some time scaling the FFT signal to fixed point.
1332         */
1333        for (n = 0; n < fft_size + 2; ++n) {
1334          if (fabs(yrTrue[n]) > factor) {
1335            factor = fabs(yrTrue[n]);
1336          }
1337        }
1338        for (n = 0; n < fft_size + 2; ++n) {
1339          temp2[n] = factor * yrTrue[n];
1340        }
1341
1342        status = omxSP_FFTInv_CCSToR_S32_Sfs(y, z, fft_inv_spec, 0);
1343
1344        /*
1345         * Spend some time converting the result back to float
1346         */
1347        factor = 1 / factor;
1348        for (n = 0; n < fft_size; ++n) {
1349          xr[n] = factor * z[n];
1350        }
1351      }
1352      GetUserTime(&end_time);
1353    } else {
1354      GetUserTime(&start_time);
1355      for (n = 0; n < count; ++n) {
1356        status = omxSP_FFTInv_CCSToR_S32_Sfs(y, z, fft_inv_spec, 0);
1357      }
1358      GetUserTime(&end_time);
1359    }
1360
1361    elapsed_time = TimeDifference(&start_time, &end_time);
1362
1363    PrintResult("Inverse RFFT32", fft_log_size, elapsed_time, count);
1364  }
1365
1366  FreeAlignedPointer(x_aligned);
1367  FreeAlignedPointer(y_aligned);
1368  FreeAlignedPointer(z_aligned);
1369  FreeAlignedPointer(y_true_aligned);
1370  free(fft_fwd_spec);
1371  free(fft_inv_spec);
1372}
1373
1374void TimeRFFT32(int count, float signal_value, int signal_type) {
1375  int k;
1376  int max_order = (max_fft_order > MAX_FFT_ORDER_FIXED_POINT)
1377      ? MAX_FFT_ORDER_FIXED_POINT : max_fft_order;
1378
1379  if (verbose == 0)
1380    PrintShortHeader("RFFT32");
1381
1382  for (k = min_fft_order; k <= max_order; ++k) {
1383    int testCount = ComputeCount(count, k);
1384    TimeOneRFFT32(testCount, k, signal_value, signal_type);
1385  }
1386}
1387#endif
1388