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