annotate sv/filter/FFTReal.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents afcf540ae3a2
children
rev   line source
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