Audacity 3.2.0
FFT.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 FFT.cpp
4
5 Dominic Mazzoni
6
7 September 2000
8
9*******************************************************************//*******************************************************************/
31/*
32 Salvo Ventura - November 2006
33 Added more window functions:
34 * 4: Blackman
35 * 5: Blackman-Harris
36 * 6: Welch
37 * 7: Gaussian(a=2.5)
38 * 8: Gaussian(a=3.5)
39 * 9: Gaussian(a=4.5)
40*/
41
42#include "FFT.h"
43
44#include "Internat.h"
45#include "MemoryX.h"
46
47#include <wx/wxcrtvararg.h>
48#include <stdlib.h>
49#include <math.h>
50
51#include "RealFFTf.h"
52
55static const size_t MaxFastBits = 16;
56
57/* Declare Static functions */
58static void InitFFT();
59
60static bool IsPowerOfTwo(size_t x)
61{
62 if (x < 2)
63 return false;
64
65 if (x & (x - 1)) /* Thanks to 'byang' for this cute trick! */
66 return false;
67
68 return true;
69}
70
71static size_t NumberOfBitsNeeded(size_t PowerOfTwo)
72{
73 if (PowerOfTwo < 2) {
74 wxFprintf(stderr, "Error: FFT called with size %ld\n", PowerOfTwo);
75 exit(1);
76 }
77
78 size_t i = 0;
79 while (PowerOfTwo > 1)
80 PowerOfTwo >>= 1, ++i;
81
82 return i;
83}
84
85int ReverseBits(size_t index, size_t NumBits)
86{
87 size_t i, rev;
88
89 for (i = rev = 0; i < NumBits; i++) {
90 rev = (rev << 1) | (index & 1);
91 index >>= 1;
92 }
93
94 return rev;
95}
96
97void InitFFT()
98{
100
101 size_t len = 2;
102 for (size_t b = 1; b <= MaxFastBits; b++) {
103 auto &array = gFFTBitTable[b - 1];
104 array.reinit(len);
105 for (size_t i = 0; i < len; i++)
106 array[i] = ReverseBits(i, b);
107
108 len <<= 1;
109 }
110}
111
113{
114 gFFTBitTable.reset();
115}
116
117static inline size_t FastReverseBits(size_t i, size_t NumBits)
118{
119 if (NumBits <= MaxFastBits)
120 return gFFTBitTable[NumBits - 1][i];
121 else
122 return ReverseBits(i, NumBits);
123}
124
125/*
126 * Complex Fast Fourier Transform
127 */
128
129void FFT(size_t NumSamples,
130 bool InverseTransform,
131 const float *RealIn, const float *ImagIn,
132 float *RealOut, float *ImagOut)
133{
134 double angle_numerator = 2.0 * M_PI;
135 double tr, ti; /* temp real, temp imaginary */
136
137 if (!IsPowerOfTwo(NumSamples)) {
138 wxFprintf(stderr, "%ld is not a power of two\n", NumSamples);
139 exit(1);
140 }
141
142 if (!gFFTBitTable)
143 InitFFT();
144
145 if (!InverseTransform)
146 angle_numerator = -angle_numerator;
147
148 /* Number of bits needed to store indices */
149 auto NumBits = NumberOfBitsNeeded(NumSamples);
150
151 /*
152 ** Do simultaneous data copy and bit-reversal ordering into outputs...
153 */
154
155 for (size_t i = 0; i < NumSamples; i++) {
156 auto j = FastReverseBits(i, NumBits);
157 RealOut[j] = RealIn[i];
158 ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i];
159 }
160
161 /*
162 ** Do the FFT itself...
163 */
164
165 size_t BlockEnd = 1;
166 for (size_t BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) {
167
168 double delta_angle = angle_numerator / (double) BlockSize;
169
170 double sm2 = sin(-2 * delta_angle);
171 double sm1 = sin(-delta_angle);
172 double cm2 = cos(-2 * delta_angle);
173 double cm1 = cos(-delta_angle);
174 double w = 2 * cm1;
175 double ar0, ar1, ar2, ai0, ai1, ai2;
176
177 for (size_t i = 0; i < NumSamples; i += BlockSize) {
178 ar2 = cm2;
179 ar1 = cm1;
180
181 ai2 = sm2;
182 ai1 = sm1;
183
184 for (size_t j = i, n = 0; n < BlockEnd; j++, n++) {
185 ar0 = w * ar1 - ar2;
186 ar2 = ar1;
187 ar1 = ar0;
188
189 ai0 = w * ai1 - ai2;
190 ai2 = ai1;
191 ai1 = ai0;
192
193 size_t k = j + BlockEnd;
194 tr = ar0 * RealOut[k] - ai0 * ImagOut[k];
195 ti = ar0 * ImagOut[k] + ai0 * RealOut[k];
196
197 RealOut[k] = RealOut[j] - tr;
198 ImagOut[k] = ImagOut[j] - ti;
199
200 RealOut[j] += tr;
201 ImagOut[j] += ti;
202 }
203 }
204
205 BlockEnd = BlockSize;
206 }
207
208 /*
209 ** Need to normalize if inverse transform...
210 */
211
212 if (InverseTransform) {
213 float denom = (float) NumSamples;
214
215 for (size_t i = 0; i < NumSamples; i++) {
216 RealOut[i] /= denom;
217 ImagOut[i] /= denom;
218 }
219 }
220}
221
222/*
223 * Real Fast Fourier Transform
224 *
225 * This is merely a wrapper of RealFFTf() from RealFFTf.h.
226 */
227
228void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
229{
230 auto hFFT = GetFFT(NumSamples);
231 Floats pFFT{ NumSamples };
232 // Copy the data into the processing buffer
233 for(size_t i = 0; i < NumSamples; i++)
234 pFFT[i] = RealIn[i];
235
236 // Perform the FFT
237 RealFFTf(pFFT.get(), hFFT.get());
238
239 // Copy the data into the real and imaginary outputs
240 for (size_t i = 1; i<(NumSamples / 2); i++) {
241 RealOut[i]=pFFT[hFFT->BitReversed[i] ];
242 ImagOut[i]=pFFT[hFFT->BitReversed[i]+1];
243 }
244 // Handle the (real-only) DC and Fs/2 bins
245 RealOut[0] = pFFT[0];
246 RealOut[NumSamples / 2] = pFFT[1];
247 ImagOut[0] = ImagOut[NumSamples / 2] = 0;
248 // Fill in the upper half using symmetry properties
249 for(size_t i = NumSamples / 2 + 1; i < NumSamples; i++) {
250 RealOut[i] = RealOut[NumSamples-i];
251 ImagOut[i] = -ImagOut[NumSamples-i];
252 }
253}
254
255/*
256 * InverseRealFFT
257 *
258 * This function computes the inverse of RealFFT, above.
259 * The RealIn and ImagIn is assumed to be conjugate-symmetric
260 * and as a result the output is purely real.
261 * Only the first half of RealIn and ImagIn are used due to this
262 * symmetry assumption.
263 *
264 * This is merely a wrapper of InverseRealFFTf() from RealFFTf.h.
265 */
266void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn,
267 float *RealOut)
268{
269 auto hFFT = GetFFT(NumSamples);
270 Floats pFFT{ NumSamples };
271 // Copy the data into the processing buffer
272 for (size_t i = 0; i < (NumSamples / 2); i++)
273 pFFT[2*i ] = RealIn[i];
274 if(ImagIn == NULL) {
275 for (size_t i = 0; i < (NumSamples / 2); i++)
276 pFFT[2*i+1] = 0;
277 } else {
278 for (size_t i = 0; i < (NumSamples / 2); i++)
279 pFFT[2*i+1] = ImagIn[i];
280 }
281 // Put the fs/2 component in the imaginary part of the DC bin
282 pFFT[1] = RealIn[NumSamples / 2];
283
284 // Perform the FFT
285 InverseRealFFTf(pFFT.get(), hFFT.get());
286
287 // Copy the data to the (purely real) output buffer
288 ReorderToTime(hFFT.get(), pFFT.get(), RealOut);
289}
290
291/*
292 * PowerSpectrum
293 *
294 * This function uses RealFFTf() from RealFFTf.h to perform the real
295 * FFT computation, and then squares the real and imaginary part of
296 * each coefficient, extracting the power and throwing away the phase.
297 *
298 * For speed, it does not call RealFFT, but duplicates some
299 * of its code.
300 */
301
302void PowerSpectrum(size_t NumSamples, const float *In, float *Out)
303{
304 auto hFFT = GetFFT(NumSamples);
305 Floats pFFT{ NumSamples };
306 // Copy the data into the processing buffer
307 for (size_t i = 0; i<NumSamples; i++)
308 pFFT[i] = In[i];
309
310 // Perform the FFT
311 RealFFTf(pFFT.get(), hFFT.get());
312
313 // Copy the data into the real and imaginary outputs
314 for (size_t i = 1; i<NumSamples / 2; i++) {
315 Out[i]= (pFFT[hFFT->BitReversed[i] ]*pFFT[hFFT->BitReversed[i] ])
316 + (pFFT[hFFT->BitReversed[i]+1]*pFFT[hFFT->BitReversed[i]+1]);
317 }
318 // Handle the (real-only) DC and Fs/2 bins
319 Out[0] = pFFT[0]*pFFT[0];
320 Out[NumSamples / 2] = pFFT[1]*pFFT[1];
321}
322
323/*
324 * Windowing Functions
325 */
326
328{
329 return eWinFuncCount;
330}
331
332const TranslatableString WindowFuncName(int whichFunction)
333{
334 switch (whichFunction) {
335 default:
337 return XO("Rectangular");
338 case eWinFuncBartlett:
339 /* i18n-hint a proper name */
340 return XO("Bartlett");
341 case eWinFuncHamming:
342 /* i18n-hint a proper name */
343 return XO("Hamming");
344 case eWinFuncHann:
345 /* i18n-hint a proper name */
346 return XO("Hann");
347 case eWinFuncBlackman:
348 /* i18n-hint a proper name */
349 return XO("Blackman");
351 /* i18n-hint two proper names */
352 return XO("Blackman-Harris");
353 case eWinFuncWelch:
354 /* i18n-hint a proper name */
355 return XO("Welch");
357 /* i18n-hint a mathematical function named for C. F. Gauss */
358 return XO("Gaussian(a=2.5)");
360 /* i18n-hint a mathematical function named for C. F. Gauss */
361 return XO("Gaussian(a=3.5)");
363 /* i18n-hint a mathematical function named for C. F. Gauss */
364 return XO("Gaussian(a=4.5)");
365 }
366}
367
368void NewWindowFunc(int whichFunction, size_t NumSamplesIn, bool extraSample, float *in)
369{
370 int NumSamples = (int)NumSamplesIn;
371 if (extraSample) {
372 wxASSERT(NumSamples > 0);
373 --NumSamples;
374 }
375 wxASSERT(NumSamples > 0);
376
377 switch (whichFunction) {
378 default:
379 wxFprintf(stderr, "FFT::WindowFunc - Invalid window function: %d\n", whichFunction);
380 break;
382 // Multiply all by 1.0f -- do nothing
383 break;
384
385 case eWinFuncBartlett:
386 {
387 // Bartlett (triangular) window
388 const int nPairs = (NumSamples - 1) / 2; // whether even or odd NumSamples, this is correct
389 const float denom = NumSamples / 2.0f;
390 in[0] = 0.0f;
391 for (int ii = 1;
392 ii <= nPairs; // Yes, <=
393 ++ii) {
394 const float value = ii / denom;
395 in[ii] *= value;
396 in[NumSamples - ii] *= value;
397 }
398 // When NumSamples is even, in[half] should be multiplied by 1.0, so unchanged
399 // When odd, the value of 1.0 is not reached
400 }
401 break;
402 case eWinFuncHamming:
403 {
404 // Hamming
405 const double multiplier = 2 * M_PI / NumSamples;
406 static const double coeff0 = 0.54, coeff1 = -0.46;
407 for (int ii = 0; ii < NumSamples; ++ii)
408 in[ii] *= coeff0 + coeff1 * cos(ii * multiplier);
409 }
410 break;
411 case eWinFuncHann:
412 {
413 // Hann
414 const double multiplier = 2 * M_PI / NumSamples;
415 static const double coeff0 = 0.5, coeff1 = -0.5;
416 for (int ii = 0; ii < NumSamples; ++ii)
417 in[ii] *= coeff0 + coeff1 * cos(ii * multiplier);
418 }
419 break;
420 case eWinFuncBlackman:
421 {
422 // Blackman
423 const double multiplier = 2 * M_PI / NumSamples;
424 const double multiplier2 = 2 * multiplier;
425 static const double coeff0 = 0.42, coeff1 = -0.5, coeff2 = 0.08;
426 for (int ii = 0; ii < NumSamples; ++ii)
427 in[ii] *= coeff0 + coeff1 * cos(ii * multiplier) + coeff2 * cos(ii * multiplier2);
428 }
429 break;
431 {
432 // Blackman-Harris
433 const double multiplier = 2 * M_PI / NumSamples;
434 const double multiplier2 = 2 * multiplier;
435 const double multiplier3 = 3 * multiplier;
436 static const double coeff0 = 0.35875, coeff1 = -0.48829, coeff2 = 0.14128, coeff3 = -0.01168;
437 for (int ii = 0; ii < NumSamples; ++ii)
438 in[ii] *= coeff0 + coeff1 * cos(ii * multiplier) + coeff2 * cos(ii * multiplier2) + coeff3 * cos(ii * multiplier3);
439 }
440 break;
441 case eWinFuncWelch:
442 {
443 // Welch
444 const float N = NumSamples;
445 for (int ii = 0; ii < NumSamples; ++ii) {
446 const float iOverN = ii / N;
447 in[ii] *= 4 * iOverN * (1 - iOverN);
448 }
449 }
450 break;
452 {
453 // Gaussian (a=2.5)
454 // Precalculate some values, and simplify the fmla to try and reduce overhead
455 static const double A = -2 * 2.5*2.5;
456 const float N = NumSamples;
457 for (int ii = 0; ii < NumSamples; ++ii) {
458 const float iOverN = ii / N;
459 // full
460 // in[ii] *= exp(-0.5*(A*((ii-NumSamples/2)/NumSamples/2))*(A*((ii-NumSamples/2)/NumSamples/2)));
461 // reduced
462 in[ii] *= exp(A * (0.25 + (iOverN * iOverN) - iOverN));
463 }
464 }
465 break;
467 {
468 // Gaussian (a=3.5)
469 static const double A = -2 * 3.5*3.5;
470 const float N = NumSamples;
471 for (int ii = 0; ii < NumSamples; ++ii) {
472 const float iOverN = ii / N;
473 in[ii] *= exp(A * (0.25 + (iOverN * iOverN) - iOverN));
474 }
475 }
476 break;
478 {
479 // Gaussian (a=4.5)
480 static const double A = -2 * 4.5*4.5;
481 const float N = NumSamples;
482 for (int ii = 0; ii < NumSamples; ++ii) {
483 const float iOverN = ii / N;
484 in[ii] *= exp(A * (0.25 + (iOverN * iOverN) - iOverN));
485 }
486 }
487 break;
488 }
489
490 if (extraSample && whichFunction != eWinFuncRectangular) {
491 double value = 0.0;
492 switch (whichFunction) {
493 case eWinFuncHamming:
494 value = 0.08;
495 break;
497 value = exp(-2 * 2.5 * 2.5 * 0.25);
498 break;
500 value = exp(-2 * 3.5 * 3.5 * 0.25);
501 break;
503 value = exp(-2 * 4.5 * 4.5 * 0.25);
504 break;
505 default:
506 break;
507 }
508 in[NumSamples] *= value;
509 }
510}
511
512// See cautions in FFT.h !
513void WindowFunc(int whichFunction, size_t NumSamples, float *in)
514{
515 bool extraSample = false;
516 switch (whichFunction)
517 {
518 case eWinFuncHamming:
519 case eWinFuncHann:
520 case eWinFuncBlackman:
522 extraSample = true;
523 break;
524 default:
525 break;
526 case eWinFuncBartlett:
527 // PRL: Do nothing here either
528 // But I want to comment that the old function did this case
529 // wrong in the second half of the array, in case NumSamples was odd
530 // but I think that never happened, so I am not bothering to preserve that
531 break;
532 }
533 NewWindowFunc(whichFunction, NumSamples, extraSample, in);
534}
535
536void DerivativeOfWindowFunc(int whichFunction, size_t NumSamples, bool extraSample, float *in)
537{
538 if (eWinFuncRectangular == whichFunction)
539 {
540 // Rectangular
541 // There are deltas at the ends
542 wxASSERT(NumSamples > 0);
543 --NumSamples;
544 // in[0] *= 1.0f;
545 for (int ii = 1; ii < (int)NumSamples; ++ii)
546 in[ii] = 0.0f;
547 in[NumSamples] *= -1.0f;
548 return;
549 }
550
551 if (extraSample) {
552 wxASSERT(NumSamples > 0);
553 --NumSamples;
554 }
555
556 wxASSERT(NumSamples > 0);
557
558 double A;
559 switch (whichFunction) {
560 case eWinFuncBartlett:
561 {
562 // Bartlett (triangular) window
563 // There are discontinuities in the derivative at the ends, and maybe at the midpoint
564 const int nPairs = (NumSamples - 1) / 2; // whether even or odd NumSamples, this is correct
565 const float value = 2.0f / NumSamples;
566 in[0] *=
567 // Average the two limiting values of discontinuous derivative
568 value / 2.0f;
569 for (int ii = 1;
570 ii <= nPairs; // Yes, <=
571 ++ii) {
572 in[ii] *= value;
573 in[NumSamples - ii] *= -value;
574 }
575 if (NumSamples % 2 == 0)
576 // Average the two limiting values of discontinuous derivative
577 in[NumSamples / 2] = 0.0f;
578 if (extraSample)
579 in[NumSamples] *=
580 // Average the two limiting values of discontinuous derivative
581 -value / 2.0f;
582 else
583 // Halve the multiplier previously applied
584 // Average the two limiting values of discontinuous derivative
585 in[NumSamples - 1] *= 0.5f;
586 }
587 break;
588 case eWinFuncHamming:
589 {
590 // Hamming
591 // There are deltas at the ends
592 const double multiplier = 2 * M_PI / NumSamples;
593 static const double coeff0 = 0.54, coeff1 = -0.46 * multiplier;
594 // TODO This code should be more explicit about the precision it intends.
595 // For now we get C4305 warnings, truncation from 'const double' to 'float'
596 in[0] *= coeff0;
597 if (!extraSample)
598 --NumSamples;
599 for (int ii = 0; ii < (int)NumSamples; ++ii)
600 in[ii] *= - coeff1 * sin(ii * multiplier);
601 if (extraSample)
602 in[NumSamples] *= - coeff0;
603 else
604 // slightly different
605 in[NumSamples] *= - coeff0 - coeff1 * sin(NumSamples * multiplier);
606 }
607 break;
608 case eWinFuncHann:
609 {
610 // Hann
611 const double multiplier = 2 * M_PI / NumSamples;
612 const double coeff1 = -0.5 * multiplier;
613 for (int ii = 0; ii < (int)NumSamples; ++ii)
614 in[ii] *= - coeff1 * sin(ii * multiplier);
615 if (extraSample)
616 in[NumSamples] = 0.0f;
617 }
618 break;
619 case eWinFuncBlackman:
620 {
621 // Blackman
622 const double multiplier = 2 * M_PI / NumSamples;
623 const double multiplier2 = 2 * multiplier;
624 const double coeff1 = -0.5 * multiplier, coeff2 = 0.08 * multiplier2;
625 for (int ii = 0; ii < (int)NumSamples; ++ii)
626 in[ii] *= - coeff1 * sin(ii * multiplier) - coeff2 * sin(ii * multiplier2);
627 if (extraSample)
628 in[NumSamples] = 0.0f;
629 }
630 break;
632 {
633 // Blackman-Harris
634 const double multiplier = 2 * M_PI / NumSamples;
635 const double multiplier2 = 2 * multiplier;
636 const double multiplier3 = 3 * multiplier;
637 const double coeff1 = -0.48829 * multiplier,
638 coeff2 = 0.14128 * multiplier2, coeff3 = -0.01168 * multiplier3;
639 for (int ii = 0; ii < (int)NumSamples; ++ii)
640 in[ii] *= - coeff1 * sin(ii * multiplier) - coeff2 * sin(ii * multiplier2) - coeff3 * sin(ii * multiplier3);
641 if (extraSample)
642 in[NumSamples] = 0.0f;
643 }
644 break;
645 case eWinFuncWelch:
646 {
647 // Welch
648 const float N = NumSamples;
649 const float NN = NumSamples * NumSamples;
650 for (int ii = 0; ii < (int)NumSamples; ++ii) {
651 in[ii] *= 4 * (N - ii - ii) / NN;
652 }
653 if (extraSample)
654 in[NumSamples] = 0.0f;
655 // Average the two limiting values of discontinuous derivative
656 in[0] /= 2.0f;
657 in[NumSamples - 1] /= 2.0f;
658 }
659 break;
661 // Gaussian (a=2.5)
662 A = -2 * 2.5*2.5;
663 goto Gaussian;
665 // Gaussian (a=3.5)
666 A = -2 * 3.5*3.5;
667 goto Gaussian;
669 // Gaussian (a=4.5)
670 A = -2 * 4.5*4.5;
671 goto Gaussian;
672 Gaussian:
673 {
674 // Gaussian (a=2.5)
675 // There are deltas at the ends
676 const float invN = 1.0f / NumSamples;
677 const float invNN = invN * invN;
678 // Simplify formula from the loop for ii == 0, add term for the delta
679 in[0] *= exp(A * 0.25) * (1 - invN);
680 if (!extraSample)
681 --NumSamples;
682 for (int ii = 1; ii < (int)NumSamples; ++ii) {
683 const float iOverN = ii * invN;
684 in[ii] *= exp(A * (0.25 + (iOverN * iOverN) - iOverN)) * (2 * ii * invNN - invN);
685 }
686 if (extraSample)
687 in[NumSamples] *= exp(A * 0.25) * (invN - 1);
688 else {
689 // Slightly different
690 const float iOverN = NumSamples * invN;
691 in[NumSamples] *= exp(A * (0.25 + (iOverN * iOverN) - iOverN)) * (2 * NumSamples * invNN - invN - 1);
692 }
693 }
694 break;
695 default:
696 wxFprintf(stderr, "FFT::DerivativeOfWindowFunc - Invalid window function: %d\n", whichFunction);
697 }
698}
#define M_PI
Definition: Distortion.cpp:30
void NewWindowFunc(int whichFunction, size_t NumSamplesIn, bool extraSample, float *in)
Definition: FFT.cpp:368
static bool IsPowerOfTwo(size_t x)
Definition: FFT.cpp:60
static const size_t MaxFastBits
Definition: FFT.cpp:55
void DerivativeOfWindowFunc(int whichFunction, size_t NumSamples, bool extraSample, float *in)
Definition: FFT.cpp:536
void DeinitFFT()
Definition: FFT.cpp:112
int ReverseBits(size_t index, size_t NumBits)
Definition: FFT.cpp:85
static size_t NumberOfBitsNeeded(size_t PowerOfTwo)
Definition: FFT.cpp:71
void WindowFunc(int whichFunction, size_t NumSamples, float *in)
Definition: FFT.cpp:513
int NumWindowFuncs()
Definition: FFT.cpp:327
void PowerSpectrum(size_t NumSamples, const float *In, float *Out)
Definition: FFT.cpp:302
static ArraysOf< int > gFFTBitTable
Definition: FFT.cpp:54
const TranslatableString WindowFuncName(int whichFunction)
Definition: FFT.cpp:332
void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn, float *RealOut)
Definition: FFT.cpp:266
void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
Definition: FFT.cpp:228
static void InitFFT()
Definition: FFT.cpp:97
void FFT(size_t NumSamples, bool InverseTransform, const float *RealIn, const float *ImagIn, float *RealOut, float *ImagOut)
Definition: FFT.cpp:129
static size_t FastReverseBits(size_t i, size_t NumBits)
Definition: FFT.cpp:117
@ eWinFuncRectangular
Definition: FFT.h:111
@ eWinFuncBlackmanHarris
Definition: FFT.h:116
@ eWinFuncGaussian25
Definition: FFT.h:118
@ eWinFuncCount
Definition: FFT.h:121
@ eWinFuncGaussian45
Definition: FFT.h:120
@ eWinFuncHamming
Definition: FFT.h:113
@ eWinFuncBartlett
Definition: FFT.h:112
@ eWinFuncBlackman
Definition: FFT.h:115
@ eWinFuncHann
Definition: FFT.h:114
@ eWinFuncWelch
Definition: FFT.h:117
@ eWinFuncGaussian35
Definition: FFT.h:119
XO("Cut/Copy/Paste")
void RealFFTf(fft_type *buffer, const FFTParam *h)
Definition: RealFFTf.cpp:161
void InverseRealFFTf(fft_type *buffer, const FFTParam *h)
Definition: RealFFTf.cpp:263
void ReorderToTime(const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut)
Definition: RealFFTf.cpp:360
HFFT GetFFT(size_t fftlen)
Definition: RealFFTf.cpp:104
#define A(N)
Definition: ToChars.cpp:62
Holds a msgid for the translation catalog; may also bind format arguments.