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