summaryrefslogtreecommitdiffstats
path: root/demos/spectrum/3rdparty/fftreal/testapp.dpr
blob: 54f2eb99a1614478be642e95b7b1c2949ada068f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
program testapp;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  fftreal in 'fftreal.pas',
  Math,
  Windows;

var
   nbr_points  : longint;
   x, f        : pflt_array;
   fft         : TFFTReal;
   i           : longint;
   PI          : double;
   areal, img  : double;
   f_abs       : double;
   buffer_size : longint;
   nbr_tests   : longint;
   time0, time1, time2 : int64;
   timereso    : int64;
   offset      : longint;
   t0, t1      : double;
   nbr_s_chn   : longint;
   tempp1, tempp2 : pflt_array;

begin
  (*______________________________________________
   *
   * Exactness test
   *______________________________________________
   *)

  WriteLn('Accuracy test:');
  WriteLn;

  nbr_points := 16;       // Power of 2
  GetMem(x, nbr_points * sizeof_flt);
  GetMem(f, nbr_points * sizeof_flt);
  fft := TFFTReal.Create(nbr_points);    // FFT object initialized here

  // Test signal
  PI := ArcTan(1) * 4;
  for i := 0 to nbr_points-1 do
  begin
    x^[i] := -1 + sin (3*2*PI*i/nbr_points)
                + cos (5*2*PI*i/nbr_points) * 2
                - sin (7*2*PI*i/nbr_points) * 3
                + cos (8*2*PI*i/nbr_points) * 5;
  end;

  // Compute FFT and IFFT
  fft.do_fft(f, x);
  fft.do_ifft(f, x);
  fft.rescale(x);

  // Display the result
  WriteLn('FFT:');
  for i := 0 to nbr_points div 2 do
  begin
    areal := f^[i];
    if (i > 0) and (i < nbr_points div 2) then
      img := f^[i + nbr_points div 2]
    else
      img := 0;

    f_abs := Sqrt(areal * areal + img * img);
    WriteLn(Format('%5d: %12.6f %12.6f (%12.6f)', [i, areal, img, f_abs]));
  end;

  WriteLn;
  WriteLn('IFFT:');
  for i := 0 to nbr_points-1 do
    WriteLn(Format('%5d: %f', [i, x^[i]]));

  WriteLn;

  FreeMem(x);
  FreeMem(f);
  fft.Free;


  (*______________________________________________
   *
   * Speed test
   *______________________________________________
   *)

  WriteLn('Speed test:');
  WriteLn('Please wait...');
  WriteLn;

  nbr_points := 1024;	          // Power of 2
  buffer_size := 256*nbr_points;  // Number of flt_t (float or double)
  nbr_tests := 10000;

  assert(nbr_points <= buffer_size);
  GetMem(x, buffer_size * sizeof_flt);
  GetMem(f, buffer_size * sizeof_flt);
  fft := TFFTReal.Create(nbr_points);					// FFT object initialized here

  // Test signal: noise
  for i := 0 to nbr_points-1 do
    x^[i] := Random($7fff) - ($7fff shr 1);

  // timing
  QueryPerformanceFrequency(timereso);
  QueryPerformanceCounter(time0);

  for i := 0 to nbr_tests-1 do
  begin
    offset := (i * nbr_points) and (buffer_size - 1);
    tempp1 := f;
    inc(tempp1, offset);
    tempp2 := x;
    inc(tempp2, offset);
    fft.do_fft(tempp1, tempp2);
  end;

  QueryPerformanceCounter(time1);

  for i := 0 to nbr_tests-1 do
  begin
    offset := (i * nbr_points) and (buffer_size - 1);
    tempp1 := f;
    inc(tempp1, offset);
    tempp2 := x;
    inc(tempp2, offset);
    fft.do_ifft(tempp1, tempp2);
    fft.rescale(x);
  end;

  QueryPerformanceCounter(time2);

  t0 := ((time1-time0) / timereso) / nbr_tests;
  t1 := ((time2-time1) / timereso) / nbr_tests;

  WriteLn(Format('%d-points FFT           : %.0f us.', [nbr_points, t0 * 1000000]));
  WriteLn(Format('%d-points IFFT + scaling: %.0f us.', [nbr_points, t1 * 1000000]));

  nbr_s_chn := Floor(nbr_points / ((t0 + t1) * 44100 * 2));
  WriteLn(Format('Peak performance: FFT+IFFT on %d mono channels at 44.1 KHz (with overlapping)', [nbr_s_chn]));
  WriteLn;

  FreeMem(x);
  FreeMem(f);
  fft.Free;

  WriteLn('Press [Return] key to terminate...');
  ReadLn;
end.