lbajardsilogic@79
|
1 /*****************************************************************************
|
lbajardsilogic@79
|
2 * *
|
lbajardsilogic@79
|
3 * DIGITAL SIGNAL PROCESSING TOOLS *
|
lbajardsilogic@79
|
4 * Version 1.01, 1999/11/07 *
|
lbajardsilogic@79
|
5 * (c) 1999 - Laurent de Soras *
|
lbajardsilogic@79
|
6 * *
|
lbajardsilogic@79
|
7 * FFTReal.cpp *
|
lbajardsilogic@79
|
8 * Fourier transformation of real number arrays. *
|
lbajardsilogic@79
|
9 * Portable ISO C++ *
|
lbajardsilogic@79
|
10 * *
|
lbajardsilogic@79
|
11 * Tab = 3 *
|
lbajardsilogic@79
|
12 *****************************************************************************/
|
lbajardsilogic@79
|
13
|
lbajardsilogic@79
|
14
|
lbajardsilogic@79
|
15
|
lbajardsilogic@79
|
16 /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
|
lbajardsilogic@79
|
17
|
lbajardsilogic@79
|
18 #include "FFTReal.h"
|
lbajardsilogic@79
|
19
|
lbajardsilogic@79
|
20 #include <cassert>
|
lbajardsilogic@79
|
21 #include <cmath>
|
lbajardsilogic@79
|
22
|
lbajardsilogic@79
|
23
|
lbajardsilogic@79
|
24
|
lbajardsilogic@79
|
25 #if defined (_MSC_VER)
|
lbajardsilogic@79
|
26 #pragma pack (push, 8)
|
lbajardsilogic@79
|
27 #endif // _MSC_VER
|
lbajardsilogic@79
|
28
|
lbajardsilogic@79
|
29
|
lbajardsilogic@79
|
30
|
lbajardsilogic@79
|
31 /*\\\ PUBLIC MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
|
lbajardsilogic@79
|
32
|
lbajardsilogic@79
|
33
|
lbajardsilogic@79
|
34
|
lbajardsilogic@79
|
35 /*==========================================================================*/
|
lbajardsilogic@79
|
36 /* Name: Constructor */
|
lbajardsilogic@79
|
37 /* Input parameters: */
|
lbajardsilogic@79
|
38 /* - length: length of the array on which we want to do a FFT. */
|
lbajardsilogic@79
|
39 /* Range: power of 2 only, > 0. */
|
lbajardsilogic@79
|
40 /* Throws: std::bad_alloc, anything */
|
lbajardsilogic@79
|
41 /*==========================================================================*/
|
lbajardsilogic@79
|
42
|
lbajardsilogic@79
|
43
|
lbajardsilogic@79
|
44 FFTReal::FFTReal (const long length)
|
lbajardsilogic@79
|
45 : _length (length)
|
lbajardsilogic@79
|
46 , _nbr_bits (int (floor (log ((float)length) / log (2.0f) + 0.5f)))
|
lbajardsilogic@79
|
47 , _bit_rev_lut (int (floor (log ((float)length) / log (2.0f) + 0.5f)))
|
lbajardsilogic@79
|
48 , _trigo_lut (int (floor (log ((float)length) / log (2.0f) + 0.5f)))
|
lbajardsilogic@79
|
49 , _sqrt2_2 (flt_t (sqrt (2.0f) * 0.5))
|
lbajardsilogic@79
|
50 {
|
lbajardsilogic@79
|
51 assert ((1L << _nbr_bits) == length);
|
lbajardsilogic@79
|
52
|
lbajardsilogic@79
|
53 _buffer_ptr = 0;
|
lbajardsilogic@79
|
54 if (_nbr_bits > 2)
|
lbajardsilogic@79
|
55 {
|
lbajardsilogic@79
|
56 _buffer_ptr = new flt_t [_length];
|
lbajardsilogic@79
|
57 }
|
lbajardsilogic@79
|
58 }
|
lbajardsilogic@79
|
59
|
lbajardsilogic@79
|
60
|
lbajardsilogic@79
|
61
|
lbajardsilogic@79
|
62 /*==========================================================================*/
|
lbajardsilogic@79
|
63 /* Name: Destructor */
|
lbajardsilogic@79
|
64 /*==========================================================================*/
|
lbajardsilogic@79
|
65
|
lbajardsilogic@79
|
66 FFTReal::~FFTReal (void)
|
lbajardsilogic@79
|
67 {
|
lbajardsilogic@79
|
68 delete [] _buffer_ptr;
|
lbajardsilogic@79
|
69 _buffer_ptr = 0;
|
lbajardsilogic@79
|
70 }
|
lbajardsilogic@79
|
71
|
lbajardsilogic@79
|
72
|
lbajardsilogic@79
|
73
|
lbajardsilogic@79
|
74 /*==========================================================================*/
|
lbajardsilogic@79
|
75 /* Name: do_fft */
|
lbajardsilogic@79
|
76 /* Description: Compute the FFT of the array. */
|
lbajardsilogic@79
|
77 /* Input parameters: */
|
lbajardsilogic@79
|
78 /* - x: pointer on the source array (time). */
|
lbajardsilogic@79
|
79 /* Output parameters: */
|
lbajardsilogic@79
|
80 /* - f: pointer on the destination array (frequencies). */
|
lbajardsilogic@79
|
81 /* f [0...length(x)/2] = real values, */
|
lbajardsilogic@79
|
82 /* f [length(x)/2+1...length(x)-1] = imaginary values of */
|
lbajardsilogic@79
|
83 /* coefficents 1...length(x)/2-1. */
|
lbajardsilogic@79
|
84 /* Throws: Nothing */
|
lbajardsilogic@79
|
85 /*==========================================================================*/
|
lbajardsilogic@79
|
86
|
lbajardsilogic@79
|
87 void FFTReal::do_fft (flt_t f [], const flt_t x []) const
|
lbajardsilogic@79
|
88 {
|
lbajardsilogic@79
|
89
|
lbajardsilogic@79
|
90 /*______________________________________________
|
lbajardsilogic@79
|
91 *
|
lbajardsilogic@79
|
92 * General case
|
lbajardsilogic@79
|
93 *______________________________________________
|
lbajardsilogic@79
|
94 */
|
lbajardsilogic@79
|
95
|
lbajardsilogic@79
|
96 if (_nbr_bits > 2)
|
lbajardsilogic@79
|
97 {
|
lbajardsilogic@79
|
98 flt_t * sf;
|
lbajardsilogic@79
|
99 flt_t * df;
|
lbajardsilogic@79
|
100
|
lbajardsilogic@79
|
101 if (_nbr_bits & 1)
|
lbajardsilogic@79
|
102 {
|
lbajardsilogic@79
|
103 df = _buffer_ptr;
|
lbajardsilogic@79
|
104 sf = f;
|
lbajardsilogic@79
|
105 }
|
lbajardsilogic@79
|
106 else
|
lbajardsilogic@79
|
107 {
|
lbajardsilogic@79
|
108 df = f;
|
lbajardsilogic@79
|
109 sf = _buffer_ptr;
|
lbajardsilogic@79
|
110 }
|
lbajardsilogic@79
|
111
|
lbajardsilogic@79
|
112 /* Do the transformation in several pass */
|
lbajardsilogic@79
|
113 {
|
lbajardsilogic@79
|
114 int pass;
|
lbajardsilogic@79
|
115 long nbr_coef;
|
lbajardsilogic@79
|
116 long h_nbr_coef;
|
lbajardsilogic@79
|
117 long d_nbr_coef;
|
lbajardsilogic@79
|
118 long coef_index;
|
lbajardsilogic@79
|
119
|
lbajardsilogic@79
|
120 /* First and second pass at once */
|
lbajardsilogic@79
|
121 {
|
lbajardsilogic@79
|
122 const long * const bit_rev_lut_ptr = _bit_rev_lut.get_ptr ();
|
lbajardsilogic@79
|
123 coef_index = 0;
|
lbajardsilogic@79
|
124 do
|
lbajardsilogic@79
|
125 {
|
lbajardsilogic@79
|
126 const long rev_index_0 = bit_rev_lut_ptr [coef_index];
|
lbajardsilogic@79
|
127 const long rev_index_1 = bit_rev_lut_ptr [coef_index + 1];
|
lbajardsilogic@79
|
128 const long rev_index_2 = bit_rev_lut_ptr [coef_index + 2];
|
lbajardsilogic@79
|
129 const long rev_index_3 = bit_rev_lut_ptr [coef_index + 3];
|
lbajardsilogic@79
|
130
|
lbajardsilogic@79
|
131 flt_t * const df2 = df + coef_index;
|
lbajardsilogic@79
|
132 df2 [1] = x [rev_index_0] - x [rev_index_1];
|
lbajardsilogic@79
|
133 df2 [3] = x [rev_index_2] - x [rev_index_3];
|
lbajardsilogic@79
|
134
|
lbajardsilogic@79
|
135 const flt_t sf_0 = x [rev_index_0] + x [rev_index_1];
|
lbajardsilogic@79
|
136 const flt_t sf_2 = x [rev_index_2] + x [rev_index_3];
|
lbajardsilogic@79
|
137
|
lbajardsilogic@79
|
138 df2 [0] = sf_0 + sf_2;
|
lbajardsilogic@79
|
139 df2 [2] = sf_0 - sf_2;
|
lbajardsilogic@79
|
140
|
lbajardsilogic@79
|
141 coef_index += 4;
|
lbajardsilogic@79
|
142 }
|
lbajardsilogic@79
|
143 while (coef_index < _length);
|
lbajardsilogic@79
|
144 }
|
lbajardsilogic@79
|
145
|
lbajardsilogic@79
|
146 /* Third pass */
|
lbajardsilogic@79
|
147 {
|
lbajardsilogic@79
|
148 coef_index = 0;
|
lbajardsilogic@79
|
149 const flt_t sqrt2_2 = _sqrt2_2;
|
lbajardsilogic@79
|
150 do
|
lbajardsilogic@79
|
151 {
|
lbajardsilogic@79
|
152 flt_t v;
|
lbajardsilogic@79
|
153
|
lbajardsilogic@79
|
154 sf [coef_index] = df [coef_index] + df [coef_index + 4];
|
lbajardsilogic@79
|
155 sf [coef_index + 4] = df [coef_index] - df [coef_index + 4];
|
lbajardsilogic@79
|
156 sf [coef_index + 2] = df [coef_index + 2];
|
lbajardsilogic@79
|
157 sf [coef_index + 6] = df [coef_index + 6];
|
lbajardsilogic@79
|
158
|
lbajardsilogic@79
|
159 v = (df [coef_index + 5] - df [coef_index + 7]) * sqrt2_2;
|
lbajardsilogic@79
|
160 sf [coef_index + 1] = df [coef_index + 1] + v;
|
lbajardsilogic@79
|
161 sf [coef_index + 3] = df [coef_index + 1] - v;
|
lbajardsilogic@79
|
162
|
lbajardsilogic@79
|
163 v = (df [coef_index + 5] + df [coef_index + 7]) * sqrt2_2;
|
lbajardsilogic@79
|
164 sf [coef_index + 5] = v + df [coef_index + 3];
|
lbajardsilogic@79
|
165 sf [coef_index + 7] = v - df [coef_index + 3];
|
lbajardsilogic@79
|
166
|
lbajardsilogic@79
|
167 coef_index += 8;
|
lbajardsilogic@79
|
168 }
|
lbajardsilogic@79
|
169 while (coef_index < _length);
|
lbajardsilogic@79
|
170 }
|
lbajardsilogic@79
|
171
|
lbajardsilogic@79
|
172 /* Next pass */
|
lbajardsilogic@79
|
173 for (pass = 3; pass < _nbr_bits; ++pass)
|
lbajardsilogic@79
|
174 {
|
lbajardsilogic@79
|
175 coef_index = 0;
|
lbajardsilogic@79
|
176 nbr_coef = 1 << pass;
|
lbajardsilogic@79
|
177 h_nbr_coef = nbr_coef >> 1;
|
lbajardsilogic@79
|
178 d_nbr_coef = nbr_coef << 1;
|
lbajardsilogic@79
|
179 const flt_t * const cos_ptr = _trigo_lut.get_ptr (pass);
|
lbajardsilogic@79
|
180 do
|
lbajardsilogic@79
|
181 {
|
lbajardsilogic@79
|
182 long i;
|
lbajardsilogic@79
|
183 const flt_t * const sf1r = sf + coef_index;
|
lbajardsilogic@79
|
184 const flt_t * const sf2r = sf1r + nbr_coef;
|
lbajardsilogic@79
|
185 flt_t * const dfr = df + coef_index;
|
lbajardsilogic@79
|
186 flt_t * const dfi = dfr + nbr_coef;
|
lbajardsilogic@79
|
187
|
lbajardsilogic@79
|
188 /* Extreme coefficients are always real */
|
lbajardsilogic@79
|
189 dfr [0] = sf1r [0] + sf2r [0];
|
lbajardsilogic@79
|
190 dfi [0] = sf1r [0] - sf2r [0]; // dfr [nbr_coef] =
|
lbajardsilogic@79
|
191 dfr [h_nbr_coef] = sf1r [h_nbr_coef];
|
lbajardsilogic@79
|
192 dfi [h_nbr_coef] = sf2r [h_nbr_coef];
|
lbajardsilogic@79
|
193
|
lbajardsilogic@79
|
194 /* Others are conjugate complex numbers */
|
lbajardsilogic@79
|
195 const flt_t * const sf1i = sf1r + h_nbr_coef;
|
lbajardsilogic@79
|
196 const flt_t * const sf2i = sf1i + nbr_coef;
|
lbajardsilogic@79
|
197 for (i = 1; i < h_nbr_coef; ++ i)
|
lbajardsilogic@79
|
198 {
|
lbajardsilogic@79
|
199 const flt_t c = cos_ptr [i]; // cos (i*PI/nbr_coef);
|
lbajardsilogic@79
|
200 const flt_t s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef);
|
lbajardsilogic@79
|
201 flt_t v;
|
lbajardsilogic@79
|
202
|
lbajardsilogic@79
|
203 v = sf2r [i] * c - sf2i [i] * s;
|
lbajardsilogic@79
|
204 dfr [i] = sf1r [i] + v;
|
lbajardsilogic@79
|
205 dfi [-i] = sf1r [i] - v; // dfr [nbr_coef - i] =
|
lbajardsilogic@79
|
206
|
lbajardsilogic@79
|
207 v = sf2r [i] * s + sf2i [i] * c;
|
lbajardsilogic@79
|
208 dfi [i] = v + sf1i [i];
|
lbajardsilogic@79
|
209 dfi [nbr_coef - i] = v - sf1i [i];
|
lbajardsilogic@79
|
210 }
|
lbajardsilogic@79
|
211
|
lbajardsilogic@79
|
212 coef_index += d_nbr_coef;
|
lbajardsilogic@79
|
213 }
|
lbajardsilogic@79
|
214 while (coef_index < _length);
|
lbajardsilogic@79
|
215
|
lbajardsilogic@79
|
216 /* Prepare to the next pass */
|
lbajardsilogic@79
|
217 {
|
lbajardsilogic@79
|
218 flt_t * const temp_ptr = df;
|
lbajardsilogic@79
|
219 df = sf;
|
lbajardsilogic@79
|
220 sf = temp_ptr;
|
lbajardsilogic@79
|
221 }
|
lbajardsilogic@79
|
222 }
|
lbajardsilogic@79
|
223 }
|
lbajardsilogic@79
|
224 }
|
lbajardsilogic@79
|
225
|
lbajardsilogic@79
|
226 /*______________________________________________
|
lbajardsilogic@79
|
227 *
|
lbajardsilogic@79
|
228 * Special cases
|
lbajardsilogic@79
|
229 *______________________________________________
|
lbajardsilogic@79
|
230 */
|
lbajardsilogic@79
|
231
|
lbajardsilogic@79
|
232 /* 4-point FFT */
|
lbajardsilogic@79
|
233 else if (_nbr_bits == 2)
|
lbajardsilogic@79
|
234 {
|
lbajardsilogic@79
|
235 f [1] = x [0] - x [2];
|
lbajardsilogic@79
|
236 f [3] = x [1] - x [3];
|
lbajardsilogic@79
|
237
|
lbajardsilogic@79
|
238 const flt_t b_0 = x [0] + x [2];
|
lbajardsilogic@79
|
239 const flt_t b_2 = x [1] + x [3];
|
lbajardsilogic@79
|
240
|
lbajardsilogic@79
|
241 f [0] = b_0 + b_2;
|
lbajardsilogic@79
|
242 f [2] = b_0 - b_2;
|
lbajardsilogic@79
|
243 }
|
lbajardsilogic@79
|
244
|
lbajardsilogic@79
|
245 /* 2-point FFT */
|
lbajardsilogic@79
|
246 else if (_nbr_bits == 1)
|
lbajardsilogic@79
|
247 {
|
lbajardsilogic@79
|
248 f [0] = x [0] + x [1];
|
lbajardsilogic@79
|
249 f [1] = x [0] - x [1];
|
lbajardsilogic@79
|
250 }
|
lbajardsilogic@79
|
251
|
lbajardsilogic@79
|
252 /* 1-point FFT */
|
lbajardsilogic@79
|
253 else
|
lbajardsilogic@79
|
254 {
|
lbajardsilogic@79
|
255 f [0] = x [0];
|
lbajardsilogic@79
|
256 }
|
lbajardsilogic@79
|
257 }
|
lbajardsilogic@79
|
258
|
lbajardsilogic@79
|
259
|
lbajardsilogic@79
|
260
|
lbajardsilogic@79
|
261 /*==========================================================================*/
|
lbajardsilogic@79
|
262 /* Name: do_ifft */
|
lbajardsilogic@79
|
263 /* Description: Compute the inverse FFT of the array. Notice that */
|
lbajardsilogic@79
|
264 /* IFFT (FFT (x)) = x * length (x). Data must be */
|
lbajardsilogic@79
|
265 /* post-scaled. */
|
lbajardsilogic@79
|
266 /* Input parameters: */
|
lbajardsilogic@79
|
267 /* - f: pointer on the source array (frequencies). */
|
lbajardsilogic@79
|
268 /* f [0...length(x)/2] = real values, */
|
lbajardsilogic@79
|
269 /* f [length(x)/2+1...length(x)] = imaginary values of */
|
lbajardsilogic@79
|
270 /* coefficents 1...length(x)-1. */
|
lbajardsilogic@79
|
271 /* Output parameters: */
|
lbajardsilogic@79
|
272 /* - x: pointer on the destination array (time). */
|
lbajardsilogic@79
|
273 /* Throws: Nothing */
|
lbajardsilogic@79
|
274 /*==========================================================================*/
|
lbajardsilogic@79
|
275
|
lbajardsilogic@79
|
276 void FFTReal::do_ifft (const flt_t f [], flt_t x []) const
|
lbajardsilogic@79
|
277 {
|
lbajardsilogic@79
|
278
|
lbajardsilogic@79
|
279 /*______________________________________________
|
lbajardsilogic@79
|
280 *
|
lbajardsilogic@79
|
281 * General case
|
lbajardsilogic@79
|
282 *______________________________________________
|
lbajardsilogic@79
|
283 */
|
lbajardsilogic@79
|
284
|
lbajardsilogic@79
|
285 if (_nbr_bits > 2)
|
lbajardsilogic@79
|
286 {
|
lbajardsilogic@79
|
287 flt_t * sf = const_cast <flt_t *> (f);
|
lbajardsilogic@79
|
288 flt_t * df;
|
lbajardsilogic@79
|
289 flt_t * df_temp;
|
lbajardsilogic@79
|
290
|
lbajardsilogic@79
|
291 if (_nbr_bits & 1)
|
lbajardsilogic@79
|
292 {
|
lbajardsilogic@79
|
293 df = _buffer_ptr;
|
lbajardsilogic@79
|
294 df_temp = x;
|
lbajardsilogic@79
|
295 }
|
lbajardsilogic@79
|
296 else
|
lbajardsilogic@79
|
297 {
|
lbajardsilogic@79
|
298 df = x;
|
lbajardsilogic@79
|
299 df_temp = _buffer_ptr;
|
lbajardsilogic@79
|
300 }
|
lbajardsilogic@79
|
301
|
lbajardsilogic@79
|
302 /* Do the transformation in several pass */
|
lbajardsilogic@79
|
303 {
|
lbajardsilogic@79
|
304 int pass;
|
lbajardsilogic@79
|
305 long nbr_coef;
|
lbajardsilogic@79
|
306 long h_nbr_coef;
|
lbajardsilogic@79
|
307 long d_nbr_coef;
|
lbajardsilogic@79
|
308 long coef_index;
|
lbajardsilogic@79
|
309
|
lbajardsilogic@79
|
310 /* First pass */
|
lbajardsilogic@79
|
311 for (pass = _nbr_bits - 1; pass >= 3; --pass)
|
lbajardsilogic@79
|
312 {
|
lbajardsilogic@79
|
313 coef_index = 0;
|
lbajardsilogic@79
|
314 nbr_coef = 1 << pass;
|
lbajardsilogic@79
|
315 h_nbr_coef = nbr_coef >> 1;
|
lbajardsilogic@79
|
316 d_nbr_coef = nbr_coef << 1;
|
lbajardsilogic@79
|
317 const flt_t *const cos_ptr = _trigo_lut.get_ptr (pass);
|
lbajardsilogic@79
|
318 do
|
lbajardsilogic@79
|
319 {
|
lbajardsilogic@79
|
320 long i;
|
lbajardsilogic@79
|
321 const flt_t * const sfr = sf + coef_index;
|
lbajardsilogic@79
|
322 const flt_t * const sfi = sfr + nbr_coef;
|
lbajardsilogic@79
|
323 flt_t * const df1r = df + coef_index;
|
lbajardsilogic@79
|
324 flt_t * const df2r = df1r + nbr_coef;
|
lbajardsilogic@79
|
325
|
lbajardsilogic@79
|
326 /* Extreme coefficients are always real */
|
lbajardsilogic@79
|
327 df1r [0] = sfr [0] + sfi [0]; // + sfr [nbr_coef]
|
lbajardsilogic@79
|
328 df2r [0] = sfr [0] - sfi [0]; // - sfr [nbr_coef]
|
lbajardsilogic@79
|
329 df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2;
|
lbajardsilogic@79
|
330 df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2;
|
lbajardsilogic@79
|
331
|
lbajardsilogic@79
|
332 /* Others are conjugate complex numbers */
|
lbajardsilogic@79
|
333 flt_t * const df1i = df1r + h_nbr_coef;
|
lbajardsilogic@79
|
334 flt_t * const df2i = df1i + nbr_coef;
|
lbajardsilogic@79
|
335 for (i = 1; i < h_nbr_coef; ++ i)
|
lbajardsilogic@79
|
336 {
|
lbajardsilogic@79
|
337 df1r [i] = sfr [i] + sfi [-i]; // + sfr [nbr_coef - i]
|
lbajardsilogic@79
|
338 df1i [i] = sfi [i] - sfi [nbr_coef - i];
|
lbajardsilogic@79
|
339
|
lbajardsilogic@79
|
340 const flt_t c = cos_ptr [i]; // cos (i*PI/nbr_coef);
|
lbajardsilogic@79
|
341 const flt_t s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef);
|
lbajardsilogic@79
|
342 const flt_t vr = sfr [i] - sfi [-i]; // - sfr [nbr_coef - i]
|
lbajardsilogic@79
|
343 const flt_t vi = sfi [i] + sfi [nbr_coef - i];
|
lbajardsilogic@79
|
344
|
lbajardsilogic@79
|
345 df2r [i] = vr * c + vi * s;
|
lbajardsilogic@79
|
346 df2i [i] = vi * c - vr * s;
|
lbajardsilogic@79
|
347 }
|
lbajardsilogic@79
|
348
|
lbajardsilogic@79
|
349 coef_index += d_nbr_coef;
|
lbajardsilogic@79
|
350 }
|
lbajardsilogic@79
|
351 while (coef_index < _length);
|
lbajardsilogic@79
|
352
|
lbajardsilogic@79
|
353 /* Prepare to the next pass */
|
lbajardsilogic@79
|
354 if (pass < _nbr_bits - 1)
|
lbajardsilogic@79
|
355 {
|
lbajardsilogic@79
|
356 flt_t * const temp_ptr = df;
|
lbajardsilogic@79
|
357 df = sf;
|
lbajardsilogic@79
|
358 sf = temp_ptr;
|
lbajardsilogic@79
|
359 }
|
lbajardsilogic@79
|
360 else
|
lbajardsilogic@79
|
361 {
|
lbajardsilogic@79
|
362 sf = df;
|
lbajardsilogic@79
|
363 df = df_temp;
|
lbajardsilogic@79
|
364 }
|
lbajardsilogic@79
|
365 }
|
lbajardsilogic@79
|
366
|
lbajardsilogic@79
|
367 /* Antepenultimate pass */
|
lbajardsilogic@79
|
368 {
|
lbajardsilogic@79
|
369 const flt_t sqrt2_2 = _sqrt2_2;
|
lbajardsilogic@79
|
370 coef_index = 0;
|
lbajardsilogic@79
|
371 do
|
lbajardsilogic@79
|
372 {
|
lbajardsilogic@79
|
373 df [coef_index] = sf [coef_index] + sf [coef_index + 4];
|
lbajardsilogic@79
|
374 df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4];
|
lbajardsilogic@79
|
375 df [coef_index + 2] = sf [coef_index + 2] * 2;
|
lbajardsilogic@79
|
376 df [coef_index + 6] = sf [coef_index + 6] * 2;
|
lbajardsilogic@79
|
377
|
lbajardsilogic@79
|
378 df [coef_index + 1] = sf [coef_index + 1] + sf [coef_index + 3];
|
lbajardsilogic@79
|
379 df [coef_index + 3] = sf [coef_index + 5] - sf [coef_index + 7];
|
lbajardsilogic@79
|
380
|
lbajardsilogic@79
|
381 const flt_t vr = sf [coef_index + 1] - sf [coef_index + 3];
|
lbajardsilogic@79
|
382 const flt_t vi = sf [coef_index + 5] + sf [coef_index + 7];
|
lbajardsilogic@79
|
383
|
lbajardsilogic@79
|
384 df [coef_index + 5] = (vr + vi) * sqrt2_2;
|
lbajardsilogic@79
|
385 df [coef_index + 7] = (vi - vr) * sqrt2_2;
|
lbajardsilogic@79
|
386
|
lbajardsilogic@79
|
387 coef_index += 8;
|
lbajardsilogic@79
|
388 }
|
lbajardsilogic@79
|
389 while (coef_index < _length);
|
lbajardsilogic@79
|
390 }
|
lbajardsilogic@79
|
391
|
lbajardsilogic@79
|
392 /* Penultimate and last pass at once */
|
lbajardsilogic@79
|
393 {
|
lbajardsilogic@79
|
394 coef_index = 0;
|
lbajardsilogic@79
|
395 const long * bit_rev_lut_ptr = _bit_rev_lut.get_ptr ();
|
lbajardsilogic@79
|
396 const flt_t * sf2 = df;
|
lbajardsilogic@79
|
397 do
|
lbajardsilogic@79
|
398 {
|
lbajardsilogic@79
|
399 {
|
lbajardsilogic@79
|
400 const flt_t b_0 = sf2 [0] + sf2 [2];
|
lbajardsilogic@79
|
401 const flt_t b_2 = sf2 [0] - sf2 [2];
|
lbajardsilogic@79
|
402 const flt_t b_1 = sf2 [1] * 2;
|
lbajardsilogic@79
|
403 const flt_t b_3 = sf2 [3] * 2;
|
lbajardsilogic@79
|
404
|
lbajardsilogic@79
|
405 x [bit_rev_lut_ptr [0]] = b_0 + b_1;
|
lbajardsilogic@79
|
406 x [bit_rev_lut_ptr [1]] = b_0 - b_1;
|
lbajardsilogic@79
|
407 x [bit_rev_lut_ptr [2]] = b_2 + b_3;
|
lbajardsilogic@79
|
408 x [bit_rev_lut_ptr [3]] = b_2 - b_3;
|
lbajardsilogic@79
|
409 }
|
lbajardsilogic@79
|
410 {
|
lbajardsilogic@79
|
411 const flt_t b_0 = sf2 [4] + sf2 [6];
|
lbajardsilogic@79
|
412 const flt_t b_2 = sf2 [4] - sf2 [6];
|
lbajardsilogic@79
|
413 const flt_t b_1 = sf2 [5] * 2;
|
lbajardsilogic@79
|
414 const flt_t b_3 = sf2 [7] * 2;
|
lbajardsilogic@79
|
415
|
lbajardsilogic@79
|
416 x [bit_rev_lut_ptr [4]] = b_0 + b_1;
|
lbajardsilogic@79
|
417 x [bit_rev_lut_ptr [5]] = b_0 - b_1;
|
lbajardsilogic@79
|
418 x [bit_rev_lut_ptr [6]] = b_2 + b_3;
|
lbajardsilogic@79
|
419 x [bit_rev_lut_ptr [7]] = b_2 - b_3;
|
lbajardsilogic@79
|
420 }
|
lbajardsilogic@79
|
421
|
lbajardsilogic@79
|
422 sf2 += 8;
|
lbajardsilogic@79
|
423 coef_index += 8;
|
lbajardsilogic@79
|
424 bit_rev_lut_ptr += 8;
|
lbajardsilogic@79
|
425 }
|
lbajardsilogic@79
|
426 while (coef_index < _length);
|
lbajardsilogic@79
|
427 }
|
lbajardsilogic@79
|
428 }
|
lbajardsilogic@79
|
429 }
|
lbajardsilogic@79
|
430
|
lbajardsilogic@79
|
431 /*______________________________________________
|
lbajardsilogic@79
|
432 *
|
lbajardsilogic@79
|
433 * Special cases
|
lbajardsilogic@79
|
434 *______________________________________________
|
lbajardsilogic@79
|
435 */
|
lbajardsilogic@79
|
436
|
lbajardsilogic@79
|
437 /* 4-point IFFT */
|
lbajardsilogic@79
|
438 else if (_nbr_bits == 2)
|
lbajardsilogic@79
|
439 {
|
lbajardsilogic@79
|
440 const flt_t b_0 = f [0] + f [2];
|
lbajardsilogic@79
|
441 const flt_t b_2 = f [0] - f [2];
|
lbajardsilogic@79
|
442
|
lbajardsilogic@79
|
443 x [0] = b_0 + f [1] * 2;
|
lbajardsilogic@79
|
444 x [2] = b_0 - f [1] * 2;
|
lbajardsilogic@79
|
445 x [1] = b_2 + f [3] * 2;
|
lbajardsilogic@79
|
446 x [3] = b_2 - f [3] * 2;
|
lbajardsilogic@79
|
447 }
|
lbajardsilogic@79
|
448
|
lbajardsilogic@79
|
449 /* 2-point IFFT */
|
lbajardsilogic@79
|
450 else if (_nbr_bits == 1)
|
lbajardsilogic@79
|
451 {
|
lbajardsilogic@79
|
452 x [0] = f [0] + f [1];
|
lbajardsilogic@79
|
453 x [1] = f [0] - f [1];
|
lbajardsilogic@79
|
454 }
|
lbajardsilogic@79
|
455
|
lbajardsilogic@79
|
456 /* 1-point IFFT */
|
lbajardsilogic@79
|
457 else
|
lbajardsilogic@79
|
458 {
|
lbajardsilogic@79
|
459 x [0] = f [0];
|
lbajardsilogic@79
|
460 }
|
lbajardsilogic@79
|
461 }
|
lbajardsilogic@79
|
462
|
lbajardsilogic@79
|
463
|
lbajardsilogic@79
|
464
|
lbajardsilogic@79
|
465 /*==========================================================================*/
|
lbajardsilogic@79
|
466 /* Name: rescale */
|
lbajardsilogic@79
|
467 /* Description: Scale an array by divide each element by its length. */
|
lbajardsilogic@79
|
468 /* This function should be called after FFT + IFFT. */
|
lbajardsilogic@79
|
469 /* Input/Output parameters: */
|
lbajardsilogic@79
|
470 /* - x: pointer on array to rescale (time or frequency). */
|
lbajardsilogic@79
|
471 /* Throws: Nothing */
|
lbajardsilogic@79
|
472 /*==========================================================================*/
|
lbajardsilogic@79
|
473
|
lbajardsilogic@79
|
474 void FFTReal::rescale (flt_t x []) const
|
lbajardsilogic@79
|
475 {
|
lbajardsilogic@79
|
476 const double dpi=3.14179;
|
lbajardsilogic@79
|
477 const flt_t mul = flt_t (1.0 / _length);
|
lbajardsilogic@79
|
478 long i = _length - 1;
|
lbajardsilogic@79
|
479
|
lbajardsilogic@79
|
480 do
|
lbajardsilogic@79
|
481 {
|
lbajardsilogic@79
|
482 x [i] *= mul;
|
lbajardsilogic@79
|
483 //x [i] *= mul*(0.5*(1-cos(2*dpi*(i)/_length))); // dan made this change to do rewindowing
|
lbajardsilogic@79
|
484 --i;
|
lbajardsilogic@79
|
485 }
|
lbajardsilogic@79
|
486 while (i >= 0);
|
lbajardsilogic@79
|
487 }
|
lbajardsilogic@79
|
488
|
lbajardsilogic@79
|
489
|
lbajardsilogic@79
|
490
|
lbajardsilogic@79
|
491 /*\\\ NESTED CLASS MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
|
lbajardsilogic@79
|
492
|
lbajardsilogic@79
|
493
|
lbajardsilogic@79
|
494
|
lbajardsilogic@79
|
495 /*==========================================================================*/
|
lbajardsilogic@79
|
496 /* Name: Constructor */
|
lbajardsilogic@79
|
497 /* Input parameters: */
|
lbajardsilogic@79
|
498 /* - nbr_bits: number of bits of the array on which we want to do a */
|
lbajardsilogic@79
|
499 /* FFT. Range: > 0 */
|
lbajardsilogic@79
|
500 /* Throws: std::bad_alloc */
|
lbajardsilogic@79
|
501 /*==========================================================================*/
|
lbajardsilogic@79
|
502
|
lbajardsilogic@79
|
503 FFTReal::BitReversedLUT::BitReversedLUT (const int nbr_bits)
|
lbajardsilogic@79
|
504 {
|
lbajardsilogic@79
|
505 long length;
|
lbajardsilogic@79
|
506 long cnt;
|
lbajardsilogic@79
|
507 long br_index;
|
lbajardsilogic@79
|
508 long bit;
|
lbajardsilogic@79
|
509
|
lbajardsilogic@79
|
510 length = 1L << nbr_bits;
|
lbajardsilogic@79
|
511 _ptr = new long [length];
|
lbajardsilogic@79
|
512
|
lbajardsilogic@79
|
513 br_index = 0;
|
lbajardsilogic@79
|
514 _ptr [0] = 0;
|
lbajardsilogic@79
|
515 for (cnt = 1; cnt < length; ++cnt)
|
lbajardsilogic@79
|
516 {
|
lbajardsilogic@79
|
517 /* ++br_index (bit reversed) */
|
lbajardsilogic@79
|
518 bit = length >> 1;
|
lbajardsilogic@79
|
519 while (((br_index ^= bit) & bit) == 0)
|
lbajardsilogic@79
|
520 {
|
lbajardsilogic@79
|
521 bit >>= 1;
|
lbajardsilogic@79
|
522 }
|
lbajardsilogic@79
|
523
|
lbajardsilogic@79
|
524 _ptr [cnt] = br_index;
|
lbajardsilogic@79
|
525 }
|
lbajardsilogic@79
|
526 }
|
lbajardsilogic@79
|
527
|
lbajardsilogic@79
|
528
|
lbajardsilogic@79
|
529
|
lbajardsilogic@79
|
530 /*==========================================================================*/
|
lbajardsilogic@79
|
531 /* Name: Destructor */
|
lbajardsilogic@79
|
532 /*==========================================================================*/
|
lbajardsilogic@79
|
533
|
lbajardsilogic@79
|
534 FFTReal::BitReversedLUT::~BitReversedLUT (void)
|
lbajardsilogic@79
|
535 {
|
lbajardsilogic@79
|
536 delete [] _ptr;
|
lbajardsilogic@79
|
537 _ptr = 0;
|
lbajardsilogic@79
|
538 }
|
lbajardsilogic@79
|
539
|
lbajardsilogic@79
|
540
|
lbajardsilogic@79
|
541
|
lbajardsilogic@79
|
542 /*==========================================================================*/
|
lbajardsilogic@79
|
543 /* Name: Constructor */
|
lbajardsilogic@79
|
544 /* Input parameters: */
|
lbajardsilogic@79
|
545 /* - nbr_bits: number of bits of the array on which we want to do a */
|
lbajardsilogic@79
|
546 /* FFT. Range: > 0 */
|
lbajardsilogic@79
|
547 /* Throws: std::bad_alloc, anything */
|
lbajardsilogic@79
|
548 /*==========================================================================*/
|
lbajardsilogic@79
|
549
|
lbajardsilogic@79
|
550 FFTReal::TrigoLUT::TrigoLUT (const int nbr_bits)
|
lbajardsilogic@79
|
551 {
|
lbajardsilogic@79
|
552 long total_len;
|
lbajardsilogic@79
|
553
|
lbajardsilogic@79
|
554 _ptr = 0;
|
lbajardsilogic@79
|
555 if (nbr_bits > 3)
|
lbajardsilogic@79
|
556 {
|
lbajardsilogic@79
|
557 total_len = (1L << (nbr_bits - 1)) - 4;
|
lbajardsilogic@79
|
558 _ptr = new flt_t [total_len];
|
lbajardsilogic@79
|
559
|
lbajardsilogic@79
|
560 const double PI = atan (1.0f) * 4;
|
lbajardsilogic@79
|
561 for (int level = 3; level < nbr_bits; ++level)
|
lbajardsilogic@79
|
562 {
|
lbajardsilogic@79
|
563 const long level_len = 1L << (level - 1);
|
lbajardsilogic@79
|
564 flt_t * const level_ptr = const_cast<flt_t *> (get_ptr (level));
|
lbajardsilogic@79
|
565 const double mul = PI / (level_len << 1);
|
lbajardsilogic@79
|
566
|
lbajardsilogic@79
|
567 for (long i = 0; i < level_len; ++ i)
|
lbajardsilogic@79
|
568 {
|
lbajardsilogic@79
|
569 level_ptr [i] = (flt_t) cos (i * mul);
|
lbajardsilogic@79
|
570 }
|
lbajardsilogic@79
|
571 }
|
lbajardsilogic@79
|
572 }
|
lbajardsilogic@79
|
573 }
|
lbajardsilogic@79
|
574
|
lbajardsilogic@79
|
575
|
lbajardsilogic@79
|
576
|
lbajardsilogic@79
|
577 /*==========================================================================*/
|
lbajardsilogic@79
|
578 /* Name: Destructor */
|
lbajardsilogic@79
|
579 /*==========================================================================*/
|
lbajardsilogic@79
|
580
|
lbajardsilogic@79
|
581 FFTReal::TrigoLUT::~TrigoLUT (void)
|
lbajardsilogic@79
|
582 {
|
lbajardsilogic@79
|
583 delete [] _ptr;
|
lbajardsilogic@79
|
584 _ptr = 0;
|
lbajardsilogic@79
|
585 }
|
lbajardsilogic@79
|
586
|
lbajardsilogic@79
|
587
|
lbajardsilogic@79
|
588
|
lbajardsilogic@79
|
589 #if defined (_MSC_VER)
|
lbajardsilogic@79
|
590 #pragma pack (pop)
|
lbajardsilogic@79
|
591 #endif // _MSC_VER
|
lbajardsilogic@79
|
592
|
lbajardsilogic@79
|
593
|
lbajardsilogic@79
|
594
|
lbajardsilogic@79
|
595 /*****************************************************************************
|
lbajardsilogic@79
|
596
|
lbajardsilogic@79
|
597 LEGAL
|
lbajardsilogic@79
|
598
|
lbajardsilogic@79
|
599 Source code may be freely used for any purpose, including commercial
|
lbajardsilogic@79
|
600 applications. Programs must display in their "About" dialog-box (or
|
lbajardsilogic@79
|
601 documentation) a text telling they use these routines by Laurent de Soras.
|
lbajardsilogic@79
|
602 Modified source code can be distributed, but modifications must be clearly
|
lbajardsilogic@79
|
603 indicated.
|
lbajardsilogic@79
|
604
|
lbajardsilogic@79
|
605 CONTACT
|
lbajardsilogic@79
|
606
|
lbajardsilogic@79
|
607 Laurent de Soras
|
lbajardsilogic@79
|
608 92 avenue Albert 1er
|
lbajardsilogic@79
|
609 92500 Rueil-Malmaison
|
lbajardsilogic@79
|
610 France
|
lbajardsilogic@79
|
611
|
lbajardsilogic@79
|
612 ldesoras@club-internet.fr
|
lbajardsilogic@79
|
613
|
lbajardsilogic@79
|
614 *****************************************************************************/
|
lbajardsilogic@79
|
615
|
lbajardsilogic@79
|
616
|
lbajardsilogic@79
|
617
|
lbajardsilogic@79
|
618 /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
|
lbajardsilogic@79
|
619
|