| 1 | program testapp;
|
|---|
| 2 | {$APPTYPE CONSOLE}
|
|---|
| 3 | uses
|
|---|
| 4 | SysUtils,
|
|---|
| 5 | fftreal in 'fftreal.pas',
|
|---|
| 6 | Math,
|
|---|
| 7 | Windows;
|
|---|
| 8 |
|
|---|
| 9 | var
|
|---|
| 10 | nbr_points : longint;
|
|---|
| 11 | x, f : pflt_array;
|
|---|
| 12 | fft : TFFTReal;
|
|---|
| 13 | i : longint;
|
|---|
| 14 | PI : double;
|
|---|
| 15 | areal, img : double;
|
|---|
| 16 | f_abs : double;
|
|---|
| 17 | buffer_size : longint;
|
|---|
| 18 | nbr_tests : longint;
|
|---|
| 19 | time0, time1, time2 : int64;
|
|---|
| 20 | timereso : int64;
|
|---|
| 21 | offset : longint;
|
|---|
| 22 | t0, t1 : double;
|
|---|
| 23 | nbr_s_chn : longint;
|
|---|
| 24 | tempp1, tempp2 : pflt_array;
|
|---|
| 25 |
|
|---|
| 26 | begin
|
|---|
| 27 | (*______________________________________________
|
|---|
| 28 | *
|
|---|
| 29 | * Exactness test
|
|---|
| 30 | *______________________________________________
|
|---|
| 31 | *)
|
|---|
| 32 |
|
|---|
| 33 | WriteLn('Accuracy test:');
|
|---|
| 34 | WriteLn;
|
|---|
| 35 |
|
|---|
| 36 | nbr_points := 16; // Power of 2
|
|---|
| 37 | GetMem(x, nbr_points * sizeof_flt);
|
|---|
| 38 | GetMem(f, nbr_points * sizeof_flt);
|
|---|
| 39 | fft := TFFTReal.Create(nbr_points); // FFT object initialized here
|
|---|
| 40 |
|
|---|
| 41 | // Test signal
|
|---|
| 42 | PI := ArcTan(1) * 4;
|
|---|
| 43 | for i := 0 to nbr_points-1 do
|
|---|
| 44 | begin
|
|---|
| 45 | x^[i] := -1 + sin (3*2*PI*i/nbr_points)
|
|---|
| 46 | + cos (5*2*PI*i/nbr_points) * 2
|
|---|
| 47 | - sin (7*2*PI*i/nbr_points) * 3
|
|---|
| 48 | + cos (8*2*PI*i/nbr_points) * 5;
|
|---|
| 49 | end;
|
|---|
| 50 |
|
|---|
| 51 | // Compute FFT and IFFT
|
|---|
| 52 | fft.do_fft(f, x);
|
|---|
| 53 | fft.do_ifft(f, x);
|
|---|
| 54 | fft.rescale(x);
|
|---|
| 55 |
|
|---|
| 56 | // Display the result
|
|---|
| 57 | WriteLn('FFT:');
|
|---|
| 58 | for i := 0 to nbr_points div 2 do
|
|---|
| 59 | begin
|
|---|
| 60 | areal := f^[i];
|
|---|
| 61 | if (i > 0) and (i < nbr_points div 2) then
|
|---|
| 62 | img := f^[i + nbr_points div 2]
|
|---|
| 63 | else
|
|---|
| 64 | img := 0;
|
|---|
| 65 |
|
|---|
| 66 | f_abs := Sqrt(areal * areal + img * img);
|
|---|
| 67 | WriteLn(Format('%5d: %12.6f %12.6f (%12.6f)', [i, areal, img, f_abs]));
|
|---|
| 68 | end;
|
|---|
| 69 |
|
|---|
| 70 | WriteLn;
|
|---|
| 71 | WriteLn('IFFT:');
|
|---|
| 72 | for i := 0 to nbr_points-1 do
|
|---|
| 73 | WriteLn(Format('%5d: %f', [i, x^[i]]));
|
|---|
| 74 |
|
|---|
| 75 | WriteLn;
|
|---|
| 76 |
|
|---|
| 77 | FreeMem(x);
|
|---|
| 78 | FreeMem(f);
|
|---|
| 79 | fft.Free;
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 | (*______________________________________________
|
|---|
| 83 | *
|
|---|
| 84 | * Speed test
|
|---|
| 85 | *______________________________________________
|
|---|
| 86 | *)
|
|---|
| 87 |
|
|---|
| 88 | WriteLn('Speed test:');
|
|---|
| 89 | WriteLn('Please wait...');
|
|---|
| 90 | WriteLn;
|
|---|
| 91 |
|
|---|
| 92 | nbr_points := 1024; // Power of 2
|
|---|
| 93 | buffer_size := 256*nbr_points; // Number of flt_t (float or double)
|
|---|
| 94 | nbr_tests := 10000;
|
|---|
| 95 |
|
|---|
| 96 | assert(nbr_points <= buffer_size);
|
|---|
| 97 | GetMem(x, buffer_size * sizeof_flt);
|
|---|
| 98 | GetMem(f, buffer_size * sizeof_flt);
|
|---|
| 99 | fft := TFFTReal.Create(nbr_points); // FFT object initialized here
|
|---|
| 100 |
|
|---|
| 101 | // Test signal: noise
|
|---|
| 102 | for i := 0 to nbr_points-1 do
|
|---|
| 103 | x^[i] := Random($7fff) - ($7fff shr 1);
|
|---|
| 104 |
|
|---|
| 105 | // timing
|
|---|
| 106 | QueryPerformanceFrequency(timereso);
|
|---|
| 107 | QueryPerformanceCounter(time0);
|
|---|
| 108 |
|
|---|
| 109 | for i := 0 to nbr_tests-1 do
|
|---|
| 110 | begin
|
|---|
| 111 | offset := (i * nbr_points) and (buffer_size - 1);
|
|---|
| 112 | tempp1 := f;
|
|---|
| 113 | inc(tempp1, offset);
|
|---|
| 114 | tempp2 := x;
|
|---|
| 115 | inc(tempp2, offset);
|
|---|
| 116 | fft.do_fft(tempp1, tempp2);
|
|---|
| 117 | end;
|
|---|
| 118 |
|
|---|
| 119 | QueryPerformanceCounter(time1);
|
|---|
| 120 |
|
|---|
| 121 | for i := 0 to nbr_tests-1 do
|
|---|
| 122 | begin
|
|---|
| 123 | offset := (i * nbr_points) and (buffer_size - 1);
|
|---|
| 124 | tempp1 := f;
|
|---|
| 125 | inc(tempp1, offset);
|
|---|
| 126 | tempp2 := x;
|
|---|
| 127 | inc(tempp2, offset);
|
|---|
| 128 | fft.do_ifft(tempp1, tempp2);
|
|---|
| 129 | fft.rescale(x);
|
|---|
| 130 | end;
|
|---|
| 131 |
|
|---|
| 132 | QueryPerformanceCounter(time2);
|
|---|
| 133 |
|
|---|
| 134 | t0 := ((time1-time0) / timereso) / nbr_tests;
|
|---|
| 135 | t1 := ((time2-time1) / timereso) / nbr_tests;
|
|---|
| 136 |
|
|---|
| 137 | WriteLn(Format('%d-points FFT : %.0f us.', [nbr_points, t0 * 1000000]));
|
|---|
| 138 | WriteLn(Format('%d-points IFFT + scaling: %.0f us.', [nbr_points, t1 * 1000000]));
|
|---|
| 139 |
|
|---|
| 140 | nbr_s_chn := Floor(nbr_points / ((t0 + t1) * 44100 * 2));
|
|---|
| 141 | WriteLn(Format('Peak performance: FFT+IFFT on %d mono channels at 44.1 KHz (with overlapping)', [nbr_s_chn]));
|
|---|
| 142 | WriteLn;
|
|---|
| 143 |
|
|---|
| 144 | FreeMem(x);
|
|---|
| 145 | FreeMem(f);
|
|---|
| 146 | fft.Free;
|
|---|
| 147 |
|
|---|
| 148 | WriteLn('Press [Return] key to terminate...');
|
|---|
| 149 | ReadLn;
|
|---|
| 150 | end.
|
|---|