MathgeomGLS
223 строки · 8.6 Кб
1unit UFourier;
2
3(**************************************************************************
4************************* UFourier ***************************************
5* Purpose: Implements Fast Fourier Transform and InverseFastFourierTrans *
6* *
7* *
8* procedures *
9* FFT(_NumSamples : Integer; *
10* _InValues, _OutValues : TComplex1DArray); *
11* *
12* IFFT(_NumSamples : Integer; *
13* _InValues, _OutValues : TComplex1DArray); *
14* *
15* Note: *
16* Based on the DMath Package by Jean Debord *
17* (http://www.unilim.fr/pages_perso/jean.debord/index.htm) *
18* *
19* Adapted to use TComplex and TComplex1DArrays - 06.09.2004 *
20* ---------------------------------------------------------------------- *
21* (c) W.Blecher 2004 - ITMC RWTH Aachen *
22**************************************************************************
23**************************************************************************)
24
25interface
26
27uses System.SysUtils,
28UGlobalTools;
29
30procedure FFT(_NumSamples : Integer;
31_InValues : TComplex1DArray;
32var _OutValues : TComplex1DArray);
33
34procedure IFFT(_NumSamples : Integer;
35_InValues : TComplex1DArray;
36var _OutValues : TComplex1DArray);
37
38implementation
39
40const MaxPowerOfTwo : integer = 25;
41
42(***************************************************************
43************************** IsPowerOfTwo ***********************
44* Purpose: Checks if an Integer is a Power of Two *
45* *
46* Input: _X : Integer *
47* *
48* Number to check *
49* Output: True/False *
50* ----------------------------------------------------------- *
51* http://www.unilim.fr/pages_perso/jean.debord/index.htm *
52***************************************************************
53***************************************************************)
54function IsPowerOfTwo(_X : Integer) : Boolean;
55var
56I, Y : Integer;
57begin
58Y := 2;
59for I := 1 to Pred(MaxPowerOfTwo) do
60begin
61if _X = Y then
62begin
63IsPowerOfTwo := True;
64Exit;
65end;
66Y := Y shl 1;
67end;
68IsPowerOfTwo := False;
69end;
70
71(***************************************************************
72************************** NumberOfBitsNeeded *****************
73* Purpose: How much Bits are needed to store the max value *
74* *
75* Input: _PowerOfTwo : Integer *
76* Max Array Index *
77
78* Output: Integer *
79* ----------------------------------------------------------- *
80* http://www.unilim.fr/pages_perso/jean.debord/index.htm *
81***************************************************************
82***************************************************************)
83function NumberOfBitsNeeded(_PowerOfTwo : Integer) : Integer;
84var
85I : Integer;
86begin
87for I := 0 to MaxPowerOfTwo do
88begin
89if (_PowerOfTwo and (1 shl I)) <> 0 then
90begin
91NumberOfBitsNeeded := I;
92Exit;
93end;
94end;
95NumberOfBitsNeeded := 0;
96end;
97
98(***************************************************************
99************************ ReverseBits **************************
100* ----------------------------------------------------------- *
101* http://www.unilim.fr/pages_perso/jean.debord/index.htm *
102***************************************************************
103***************************************************************)
104function ReverseBits(_Index, _NumBits : Integer) : Integer;
105var
106I, Rev : Integer;
107begin
108Rev := 0;
109for I := 0 to _NumBits - 1 do
110begin
111Rev := (Rev shl 1) or (_Index and 1);
112_Index := _Index shr 1;
113end;
114ReverseBits := Rev;
115end;
116
117(***************************************************************
118************************* FourierTransform ********************
119* Purpose: Calculate the Fourier Transform of _ValsIn *
120* ----------------------------------------------------------- *
121* http://www.unilim.fr/pages_perso/jean.debord/index.htm *
122***************************************************************
123***************************************************************)
124procedure FourierTransform(_AngleNumerator : Single;
125_NumSamples : Integer;
126_ValsIn : TComplex1DArray;
127var _ValsOut : TComplex1DArray);
128var
129NumBits, I, J, K, N, BlockSize, BlockEnd : Integer;
130Delta_angle, Delta_ar : Single;
131Alpha, Beta : Single;
132Tr, Ti, Ar, Ai : Single;
133begin
134if not IsPowerOfTwo(_NumSamples) or (_NumSamples < 2) then
135begin
136raise Exception.Create('Error in procedure Fourier: NumSamples=' + IntToStr(_NumSamples)+ ' is not a positive integer power of 2');
137end;
138
139NumBits := NumberOfBitsNeeded(_NumSamples);
140for I := 0 to _NumSamples - 1 do
141begin
142J := ReverseBits(I, NumBits);
143_ValsOut[J].Re := _ValsIn[I].Re;
144_ValsOut[J].img := _ValsIn[I].Img;
145end;
146
147BlockEnd := 1;
148BlockSize := 2;
149while BlockSize <= _NumSamples do
150begin
151Delta_angle := _AngleNumerator / BlockSize;
152Alpha := Sin(0.5 * Delta_angle);
153Alpha := 2.0 * Alpha * Alpha;
154Beta := Sin(Delta_angle);
155
156I := 0;
157while I < _NumSamples do
158begin
159Ar := 1.0; (* cos(0) *)
160Ai := 0.0; (* sin(0) *)
161
162J := I;
163for N := 0 to BlockEnd - 1 do
164begin
165K := J + BlockEnd;
166Tr := Ar * _ValsOut[K].Re - Ai * _ValsOut[K].Img;
167Ti := Ar * _ValsOut[K].Img + Ai * _ValsOut[K].Re;
168_ValsOut[K].Re := _ValsOut[J].Re - Tr;
169_ValsOut[K].Img := _ValsOut[J].Img - Ti;
170_ValsOut[J].Re := _ValsOut[J].Re + Tr;
171_ValsOut[J].Img := _ValsOut[J].Img + Ti;
172Delta_ar := Alpha * Ar + Beta * Ai;
173Ai := Ai - (Alpha * Ai - Beta * Ar);
174Ar := Ar - Delta_ar;
175Inc(J);
176end;
177
178I := I + BlockSize;
179end;
180
181BlockEnd := BlockSize;
182BlockSize := BlockSize shl 1;
183end;
184end;
185
186(***************************************************************
187************************* FFT *********************************
188* Purpose: Caller for calculation of Fast Fourier Transform *
189* ----------------------------------------------------------- *
190* http://www.unilim.fr/pages_perso/jean.debord/index.htm *
191***************************************************************
192***************************************************************)
193procedure FFT(_NumSamples : Integer;
194_InValues : TComplex1DArray;
195var _OutValues : TComplex1DArray);
196begin
197FourierTransform(2 * PI, _NumSamples, _InValues, _OutValues);
198end;
199
200(***************************************************************
201************************ IFFT *********************************
202* Purpose: Caller of Iverse Fast Fourier Transform *
203* ----------------------------------------------------------- *
204* http://www.unilim.fr/pages_perso/jean.debord/index.htm *
205***************************************************************
206***************************************************************)
207procedure IFFT(_NumSamples : Integer;
208_InValues : TComplex1DArray;
209var _OutValues : TComplex1DArray);
210var
211I : Integer;
212begin
213FourierTransform(- 2 * PI, _NumSamples, _InValues, _OutValues);
214
215{ Normalize the resulting time samples }
216for I := 0 to _NumSamples - 1 do
217begin
218_OutValues[I].Re := _OutValues[I].Re / _NumSamples;
219_OutValues[I].Img := _OutValues[I].Img / _NumSamples;
220end;
221end;
222
223end.
224