RSeries astromech firmware
CTFFT.h
Go to the documentation of this file.
1 /*
2  * Derivative work based on FFmpeg.
3  *
4  * CTFFT is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * CTFFT is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with CTFFT; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #ifndef CTFFT_MINIMAL
20  #if defined(ARDUINO) && !defined(ESP32)
21  #define CTFFT_MINIMAL 1
22  #ifndef CTFFT_MAXBITS
23  #define CTFFT_MAXBITS 8
24  #endif
25  #ifndef PROGMEM
26  #define PROGMEM
27  #else
28  #define READ_COS(x) pgm_read_float(&(x))
29  #endif
30  #endif
31  #ifndef CTFFT_MINIMAL
32  #define CTFFT_MINIMAL 0
33  #endif
34 #endif
35 
36 #ifndef READ_COS
37  #define READ_COS(x) x
38 #endif
39 
40 #ifndef HAVE_TYPE_TRAITS
41  #ifndef CTFFT_MINIMAL
42  #define HAVE_TYPE_TRAITS 1
43  #endif
44 #endif
45 
46 #if HAVE_TYPE_TRAITS
47  #include <type_traits>
48 #endif
49 
50 #if defined(__GNUC__) && defined(ESP32)
51  #if !__GNUC_PREREQ(8,4)
52  #define GCC_OPTIMIZER_BUG
53  #endif
54 #endif
55 
56 #include <math.h>
57 
58 #ifndef CTFFT_COMPILETIME
59  #if defined(__GNUC__) && __cplusplus >= 201300
60  #define CTFFT_COMPILETIME
61  #endif
62 #endif
63 
64 #ifndef CTFFT_MAXBITS
65 // Setting CTFFT_MAXBITS to higher than 19 will increase compilation time.
66 // You may also need to increase the constexpr loop limit -fconstexpr-loop-limit=<value>
67 // MAXBITS==19 : 5 seconds
68 // MAXBITS==20 : 16 seconds
69 // MAXBITS==21 : 56 seconds
70 // MAXBITS==22 : 5 minutes
71 // ....
72 #define CTFFT_MAXBITS 19
73 #endif
74 
75 namespace CTFFT
76 {
77 constexpr long double pi = 3.1415926535897932384626433832795028841972L;
78 constexpr long double sqrt1_2 = 1.4142135623730950488016887242096980785697L/2;
79 
80 constexpr unsigned log2(unsigned x)
81 {
82  return (x == 1) ? 0 : log2(x >> 1) + 1;
83 }
84 
85 #ifdef CTFFT_COMPILETIME
86  #define CTFFT_COSTABLE_CONSTRUCTOR constexpr Data():sample
87  #define CTFFT_COSTABLE_CONSTEXPR constexpr
88 #else
89  #define CTFFT_COSTABLE_CONSTRUCTOR Data
90  #define CTFFT_COSTABLE_CONSTEXPR
91 #endif
92 
93 template<typename T, unsigned nbits>
94 struct CosTable
95 {
96 #if HAVE_TYPE_TRAITS
97  static_assert(std::is_floating_point<T>(), "Only floating point supported");
98 #endif
99  static_assert(nbits >= 4 && nbits <= CTFFT_MAXBITS, "Number of bits not supported");
100 #if !CTFFT_MINIMAL
101  template<unsigned NUMBITS>
102  struct Data
103  {
104  static constexpr unsigned size = 1<<NUMBITS;
106 
108  {
109  constexpr long double freq = 2*pi/size;
110  for (unsigned i = 0; i <= size / 4; i++)
111  sample[i] = cos(i*freq);
112  for (unsigned i = 1; i < size / 4; i++)
113  sample[size / 2 - i] = sample[i];
114  }
115  };
116 #endif
117 
118  static const T* get(unsigned i)
119  {
120  #if CTFFT_MINIMAL
121  #if CTFFT_MAXBITS >= 4
122  static const T costable4[16] PROGMEM = {
123  1, 0.92388, 0.707107, 0.382683, -2.50828e-20, 0.382683, 0.707107, 0.92388
124  };
125  #endif
126  #if CTFFT_MAXBITS >= 5
127  static const T costable5[32] PROGMEM = {
128  1, 0.980785, 0.92388, 0.83147, 0.707107, 0.55557, 0.382683, 0.19509, -2.50828e-20,
129  0.19509, 0.382683, 0.55557, 0.707107, 0.83147, 0.92388, 0.980785
130  };
131  #endif
132  #if CTFFT_MAXBITS >= 6
133  static const T costable6[64] PROGMEM = {
134  1, 0.995185, 0.980785, 0.95694, 0.92388, 0.881921, 0.83147, 0.77301, 0.707107,
135  0.634393, 0.55557, 0.471397, 0.382683, 0.290285, 0.19509, 0.0980171, -2.50828e-20,
136  0.0980171, 0.19509, 0.290285, 0.382683, 0.471397, 0.55557, 0.634393, 0.707107,
137  0.77301, 0.83147, 0.881921, 0.92388, 0.95694, 0.980785, 0.995185
138  };
139  #endif
140  #if CTFFT_MAXBITS >= 7
141  static const T costable7[128] PROGMEM = {
142  1, 0.998795, 0.995185, 0.989177, 0.980785, 0.970031, 0.95694, 0.941544, 0.92388,
143  0.903989, 0.881921, 0.857729, 0.83147, 0.803208, 0.77301, 0.740951, 0.707107,
144  0.671559, 0.634393, 0.595699, 0.55557, 0.514103, 0.471397, 0.427555, 0.382683,
145  0.33689, 0.290285, 0.24298, 0.19509, 0.14673, 0.0980171, 0.0490677, -2.50828e-20,
146  0.0490677, 0.0980171, 0.14673, 0.19509, 0.24298, 0.290285, 0.33689, 0.382683,
147  0.427555, 0.471397, 0.514103, 0.55557, 0.595699, 0.634393, 0.671559, 0.707107,
148  0.740951, 0.77301, 0.803208, 0.83147, 0.857729, 0.881921, 0.903989, 0.92388,
149  0.941544, 0.95694, 0.970031, 0.980785, 0.989177, 0.995185, 0.998795
150  };
151  #endif
152  #if CTFFT_MAXBITS >= 8
153  static const T costable8[256] PROGMEM = {
154  1, 0.999699, 0.998795, 0.99729, 0.995185, 0.99248, 0.989177, 0.985278, 0.980785,
155  0.975702, 0.970031, 0.963776, 0.95694, 0.949528, 0.941544, 0.932993, 0.92388,
156  0.91421, 0.903989, 0.893224, 0.881921, 0.870087, 0.857729, 0.844854, 0.83147,
157  0.817585, 0.803208, 0.788346, 0.77301, 0.757209, 0.740951, 0.724247, 0.707107,
158  0.689541, 0.671559, 0.653173, 0.634393, 0.615232, 0.595699, 0.575808, 0.55557,
159  0.534998, 0.514103, 0.492898, 0.471397, 0.449611, 0.427555, 0.405241, 0.382683,
160  0.359895, 0.33689, 0.313682, 0.290285, 0.266713, 0.24298, 0.219101, 0.19509,
161  0.170962, 0.14673, 0.122411, 0.0980171, 0.0735646, 0.0490677, 0.0245412,
162  -2.50828e-20, 0.0245412, 0.0490677, 0.0735646, 0.0980171, 0.122411, 0.14673,
163  0.170962, 0.19509, 0.219101, 0.24298, 0.266713, 0.290285, 0.313682, 0.33689,
164  0.359895, 0.382683, 0.405241, 0.427555, 0.449611, 0.471397, 0.492898, 0.514103,
165  0.534998, 0.55557, 0.575808, 0.595699, 0.615232, 0.634393, 0.653173, 0.671559,
166  0.689541, 0.707107, 0.724247, 0.740951, 0.757209, 0.77301, 0.788346, 0.803208,
167  0.817585, 0.83147, 0.844854, 0.857729, 0.870087, 0.881921, 0.893224, 0.903989,
168  0.91421, 0.92388, 0.932993, 0.941544, 0.949528, 0.95694, 0.963776, 0.970031,
169  0.975702, 0.980785, 0.985278, 0.989177, 0.99248, 0.995185, 0.99729, 0.998795, 0.999699
170  };
171  #endif
172  switch (i)
173  {
174  #if CTFFT_MAXBITS >= 4
175  case 4:
176  return costable4;
177  #endif
178  #if CTFFT_MAXBITS >= 5
179  case 5:
180  return costable5;
181  #endif
182  #if CTFFT_MAXBITS >= 6
183  case 6:
184  return costable6;
185  #endif
186  #if CTFFT_MAXBITS >= 7
187  case 7:
188  return costable7;
189  #endif
190  #if CTFFT_MAXBITS >= 8
191  case 8:
192  return costable8;
193  #endif
194  default:
195  return NULL;
196  }
197  #else
198  static const T* tables[nbits-3];
199  if (i-4 >= sizeof(tables)/sizeof(tables[0]))
200  return NULL;
201  #define DECLARE_COSTABLE(nb) \
202  if (nbits >= nb && !tables[nb-4]) \
203  { \
204  static const CTFFT_COSTABLE_CONSTEXPR Data<nb> table_ = Data<nb>(); \
205  tables[nb-4] = table_.sample; \
206  }
208  #if CTFFT_MAXBITS >= 5
210  #endif
211  #if CTFFT_MAXBITS >= 7
213  #endif
214  #if CTFFT_MAXBITS >= 7
216  #endif
217  #if CTFFT_MAXBITS >= 8
219  #endif
220  #if CTFFT_MAXBITS >= 9
222  #endif
223  #if CTFFT_MAXBITS >= 10
224  DECLARE_COSTABLE(10)
225  #endif
226  #if CTFFT_MAXBITS >= 11
227  DECLARE_COSTABLE(11)
228  #endif
229  #if CTFFT_MAXBITS >= 12
230  DECLARE_COSTABLE(12)
231  #endif
232  #if CTFFT_MAXBITS >= 13
233  DECLARE_COSTABLE(13)
234  #endif
235  #if CTFFT_MAXBITS >= 14
236  DECLARE_COSTABLE(14)
237  #endif
238  #if CTFFT_MAXBITS >= 15
239  DECLARE_COSTABLE(15)
240  #endif
241  #if CTFFT_MAXBITS >= 16
242  DECLARE_COSTABLE(16)
243  #endif
244  #if CTFFT_MAXBITS >= 17
245  DECLARE_COSTABLE(17)
246  #endif
247  #if CTFFT_MAXBITS >= 18
248  DECLARE_COSTABLE(18)
249  #endif
250  #if CTFFT_MAXBITS >= 19
251  DECLARE_COSTABLE(19)
252  #endif
253  #if CTFFT_MAXBITS >= 20
254  DECLARE_COSTABLE(20)
255  #endif
256  #if CTFFT_MAXBITS >= 21
257  DECLARE_COSTABLE(21)
258  #endif
259  #if CTFFT_MAXBITS >= 22
260  DECLARE_COSTABLE(22)
261  #endif
262  #if CTFFT_MAXBITS >= 23
263  DECLARE_COSTABLE(23)
264  #endif
265  #if CTFFT_MAXBITS >= 24
266  DECLARE_COSTABLE(24)
267  #endif
268  #undef DECLARE_COSTABLE
269  return tables[i-4];
270  #endif
271  }
272 };
273 
274 #undef CTFFT_COSTABLE_CONSTRUCTOR
275 #undef CTFFT_COSTABLE_CONSTEXPR
276 
277 template<typename T>
278 struct Complex
279 {
280  T real;
281  T img;
282 };
283 
284 template<typename T, unsigned SIZE, typename CT>
286 {
287 public:
288  FourierTransform(bool inverseTransform = false) :
289  inverse(inverseTransform)
290  {
291  unsigned n = 1 << nbits;
292  for (unsigned i = 0; i < n; i++)
293  rev[-split_radix_permutation(i, n, inverse) & (n - 1)] = i;
294  }
295 
296  void permute(Complex<T>* data)
297  {
298  unsigned np = 1 << nbits;
299  for (unsigned i = 0; i < np; i++)
300  tmp[rev[i]] = data[i];
301  for (unsigned i = 0; i < np; i++)
302  data[i] = tmp[i];
303  }
304 
305  void calculate(Complex<T>* data)
306  {
307  dispatch(nbits)(data, nbits);
308  }
309 
310 private:
311  typedef void (*FFT)(Complex<T>* data, unsigned nbits);
312  static constexpr int nbits = log2(SIZE);
313  int inverse;
314  int mdct_size;
315  int mdct_bits;
316  unsigned rev[SIZE];
317  Complex<T> tmp[SIZE];
318  const T* tcos = CT::get(nbits);
319  const T* tsin = tcos + (SIZE >> 2);
320 
321  static int split_radix_permutation(int i, int n, int inverse)
322  {
323  int m;
324  if (n <= 2)
325  return i & 1;
326  m = n >> 1;
327  if (!(i&m))
328  return split_radix_permutation(i, m, inverse) * 2;
329  m >>= 1;
330  if (inverse == !(i&m))
331  return split_radix_permutation(i, m, inverse) * 4 + 1;
332  return split_radix_permutation(i, m, inverse) * 4 - 1;
333  }
334 
335  #define BF(x, y, a, b) do { \
336  x = a - b; \
337  y = a + b; \
338  } while (0)
339 
340  #define CMUL(dre, dim, are, aim, bre, bim) do { \
341  (dre) = (are) * (bre) - (aim) * (bim); \
342  (dim) = (are) * (bim) + (aim) * (bre); \
343  } while (0)
344 
345  #define BUTTERFLIES(a0,a1,a2,a3) {\
346  BF(t3, t5, t5, t1);\
347  BF(a2.real, a0.real, a0.real, t5);\
348  BF(a3.img, a1.img, a1.img, t3);\
349  BF(t4, t6, t2, t6);\
350  BF(a3.real, a1.real, a1.real, t4);\
351  BF(a2.img, a0.img, a0.img, t6);\
352  }
353 
354  // force loading all the inputs before storing any.
355  // this is slightly slower for small data, but avoids store->load aliasing
356  // for addresses separated by large powers of 2.
357  #define BUTTERFLIES_BIG(a0,a1,a2,a3) {\
358  T r0=a0.real, i0=a0.img, r1=a1.real, i1=a1.img;\
359  BF(t3, t5, t5, t1);\
360  BF(a2.real, a0.real, r0, t5);\
361  BF(a3.img, a1.img, i1, t3);\
362  BF(t4, t6, t2, t6);\
363  BF(a3.real, a1.real, r1, t4);\
364  BF(a2.img, a0.img, i0, t6);\
365  }
366 
367  #define TRANSFORM(a0,a1,a2,a3,wre,wim) {\
368  CMUL(t1, t2, a2.real, a2.img, wre, -wim);\
369  CMUL(t5, t6, a3.real, a3.img, wre, wim);\
370  BUTTERFLIES(a0,a1,a2,a3)\
371  }
372 
373  #define TRANSFORM_ZERO(a0,a1,a2,a3) {\
374  t1 = a2.real;\
375  t2 = a2.img;\
376  t5 = a3.real;\
377  t6 = a3.img;\
378  BUTTERFLIES(a0,a1,a2,a3)\
379  }
380 
381  static void fft4(Complex<T>* z, unsigned n)
382  {
383  // argument not used
384  (void)n;
385 
386  T t1, t2, t3, t4, t5, t6, t7, t8;
387 
388  BF(t3, t1, z[0].real, z[1].real);
389  BF(t8, t6, z[3].real, z[2].real);
390  BF(z[2].real, z[0].real, t1, t6);
391  BF(t4, t2, z[0].img, z[1].img);
392  BF(t7, t5, z[2].img, z[3].img);
393  BF(z[3].img, z[1].img, t4, t8);
394  BF(z[3].real, z[1].real, t3, t7);
395  BF(z[2].img, z[0].img, t2, t5);
396  }
397 
398  static void fft8(Complex<T>* z, unsigned n)
399  {
400  // argument not used
401  (void)n;
402 
403  T t1, t2, t3, t4, t5, t6;
404 
405  fft4(z, 2);
406 
407  BF(t1, z[5].real, z[4].real, -z[5].real);
408  BF(t2, z[5].img, z[4].img, -z[5].img);
409  BF(t5, z[7].real, z[6].real, -z[7].real);
410  BF(t6, z[7].img, z[6].img, -z[7].img);
411 
412  BUTTERFLIES(z[0],z[2],z[4],z[6]);
413  TRANSFORM(z[1],z[3],z[5],z[7],sqrt1_2,sqrt1_2);
414  }
415 
416  static void fft16(Complex<T>* z, unsigned n)
417  {
418  // argument not used
419  (void)n;
420 
421  T t1, t2, t3, t4, t5, t6;
422  const T* cos16 = CT::get(4);
423  T cos_16_1 = READ_COS(cos16[1]);
424  T cos_16_3 = READ_COS(cos16[3]);
425 
426  fft8(z, 3);
427  fft4(z+8, 2);
428  fft4(z+12, 2);
429 
430  TRANSFORM_ZERO(z[0],z[4],z[8],z[12]);
431  TRANSFORM(z[2],z[6],z[10],z[14],sqrt1_2,sqrt1_2);
432  TRANSFORM(z[1],z[5],z[9],z[13],cos_16_1,cos_16_3);
433  TRANSFORM(z[3],z[7],z[11],z[15],cos_16_3,cos_16_1);
434  }
435 #ifdef GCC_OPTIMIZER_BUG
436  #pragma GCC optimize ("O0")
437 #endif
438  static void pass(Complex<T> *z, const T* wre, unsigned int n)
439  {
440  T t1, t2, t3, t4, t5, t6;
441  int o1 = 2*n;
442  int o2 = 4*n;
443  int o3 = 6*n;
444  const T* wim = wre+o1;
445 
446  n--;
447  TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);
448  TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],READ_COS(wre[1]),READ_COS(wim[-1]));
449  do
450  {
451  z += 2;
452  wre += 2;
453  wim -= 2;
454  TRANSFORM(z[0],z[o1],z[o2],z[o3],READ_COS(wre[0]),READ_COS(wim[0]));
455  TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],READ_COS(wre[1]),READ_COS(wim[-1]));
456  }
457  while(--n);
458  }
459 #ifdef GCC_OPTIMIZER_BUG
460  #pragma GCC optimize ("Os")
461 #endif
462 
463 #ifndef CTFFT_MINIMAL
464  #undef BUTTERFLIES
465  #define BUTTERFLIES BUTTERFLIES_BIG
466 
467  static void passBig(Complex<T> *z, const T* wre, unsigned int n)
468  {
469  T t1, t2, t3, t4, t5, t6;
470  int o1 = 2*n;
471  int o2 = 4*n;
472  int o3 = 6*n;
473  const T* wim = wre+o1;
474 
475  n--;
476  TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);
477  TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);
478  do
479  {
480  z += 2;
481  wre += 2;
482  wim -= 2;
483  TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]);
484  TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);
485  }
486  while(--n);
487  }
488 #endif
489 
490  static void fft(Complex<T>* z, unsigned n)
491  {
492  unsigned n4 = (1<<(n-2));
493  dispatch(n-1)(z, n-1);
494  dispatch(n-2)(z+n4*2, n-2);
495  dispatch(n-2)(z+n4*3, n-2);
496  #ifndef CTFFT_MINIMAL
497  if (n >= 10)
498  passBig(z, CT::get(n), n4/2);
499  else
500  #endif
501  pass(z, CT::get(n), n4/2);
502  }
503 
504  static FFT dispatch(unsigned n)
505  {
506  static FFT opt[] = {
507  fft4,
508  fft8,
509  fft16
510  };
511  return (n-2 < sizeof(opt)/sizeof(opt[0])) ? opt[n-2] : fft;
512  }
513 
514  #undef BF
515  #undef CMUL
516  #undef BUTTERFLIES
517  #undef BUTTERFLIES_BIG
518  #undef TRANSFORM
519  #undef TRANSFORM_ZERO
520 };
521 
522 template<typename T, unsigned SIZE>
524 {
525 public:
527  {
532  };
533 
535  inverse(transform == kC2R || transform == kC2R),
536  negative(transform == kC2R || transform == kR2C),
537  sign_convention((transform == kInverseR2C || transform == kC2R) ? 1 : -1),
538  fft(inverse)
539  {
540  }
541 
542  void calculate(T* data)
543  {
544  Complex<T> ev, od, odsum;
545  const int n = 1 << nbits;
546  const float k1 = 0.5;
547  const float k2 = 0.5 - inverse;
548  const T* tcos = this->tcos;
549  const T* tsin = this->tsin;
550 
551  if (!inverse)
552  {
553  fft.permute((Complex<T>*)data);
554  fft.calculate((Complex<T>*)data);
555  }
556 
557  /* i=0 is a special case because of packing, the DC term is real, so we
558  are going to throw the N/2 term (also real) in with it. */
559  ev.real = data[0];
560  data[0] = ev.real + data[1];
561  data[1] = ev.real - data[1];
562 
563  int i;
564  #define RDFT_UNMANGLE(sign0, sign1) \
565  for (i = 1; i < (n>>2); i++) \
566  { \
567  int i1 = 2*i; \
568  int i2 = n-i1; \
569  /* Separate even and odd FFTs */ \
570  ev.real = k1*(data[i1 ]+data[i2 ]); \
571  od.img = k2*(data[i2 ]-data[i1 ]); \
572  ev.img = k1*(data[i1+1]-data[i2+1]); \
573  od.real = k2*(data[i1+1]+data[i2+1]); \
574  /* Apply twiddle factors to the odd FFT and add to the even FFT */ \
575  odsum.real = od.real* READ_COS(tcos[i]) sign0 od.img * READ_COS(tsin[i]);\
576  odsum.img = od.img * READ_COS(tcos[i]) sign1 od.real* READ_COS(tsin[i]);\
577  data[i1 ] = ev.real + odsum.real; \
578  data[i1+1] = ev.img + odsum.img; \
579  data[i2 ] = ev.real - odsum.real; \
580  data[i2+1] = odsum.img - ev.img; \
581  }
582 
583  if (negative)
584  {
585  RDFT_UNMANGLE(+,-)
586  }
587  else
588  {
589  RDFT_UNMANGLE(-,+)
590  }
591  #undef RDFT_UNMANGLE
592 
593  data[2*i+1] = sign_convention * data[2*i+1];
594  if (inverse)
595  {
596  data[0] *= k1;
597  data[1] *= k1;
598  fft.permute((Complex<T>*)data);
599  fft.calculate((Complex<T>*)data);
600  }
601  }
602 
603  static constexpr unsigned nbits = log2(SIZE);
605  bool inverse;
606  bool negative;
609  const T* tcos = costable::get(nbits);
610  const T* tsin = tcos + (SIZE >> 2);
611 };
612 
613 }
CTFFT::CosTable::Data::size
static constexpr unsigned size
Definition: CTFFT.h:104
CTFFT::FourierTransform
Definition: CTFFT.h:285
CTFFT::RealDiscrete::inverse
bool inverse
Definition: CTFFT.h:605
TRANSFORM_ZERO
#define TRANSFORM_ZERO(a0, a1, a2, a3)
Definition: CTFFT.h:373
CTFFT::CosTable::Data
Definition: CTFFT.h:102
CTFFT::FourierTransform::permute
void permute(Complex< T > *data)
Definition: CTFFT.h:296
CTFFT::RealDiscrete::kR2C
@ kR2C
Definition: CTFFT.h:528
CTFFT::CosTable::Data::sample
T sample[size]
Definition: CTFFT.h:105
CTFFT::Complex::real
T real
Definition: CTFFT.h:280
CTFFT::CosTable::Data::CTFFT_COSTABLE_CONSTRUCTOR
CTFFT_COSTABLE_CONSTRUCTOR()
Definition: CTFFT.h:107
READ_COS
#define READ_COS(x)
Definition: CTFFT.h:37
CTFFT::Complex::img
T img
Definition: CTFFT.h:281
CTFFT::RealDiscrete::kInverseC2R
@ kInverseC2R
Definition: CTFFT.h:531
RDFT_UNMANGLE
#define RDFT_UNMANGLE(sign0, sign1)
CTFFT::RealDiscrete::tsin
const T * tsin
Definition: CTFFT.h:610
CTFFT::RealDiscrete::RealDiscrete
RealDiscrete(TransformType transform=kR2C)
Definition: CTFFT.h:534
CTFFT::RealDiscrete::sign_convention
int sign_convention
Definition: CTFFT.h:607
CTFFT::CosTable::get
static const T * get(unsigned i)
Definition: CTFFT.h:118
CTFFT::Complex
Definition: CTFFT.h:278
CTFFT::FourierTransform::calculate
void calculate(Complex< T > *data)
Definition: CTFFT.h:305
BUTTERFLIES
#define BUTTERFLIES(a0, a1, a2, a3)
Definition: CTFFT.h:345
CTFFT::pi
constexpr long double pi
Definition: CTFFT.h:77
CTFFT::RealDiscrete< float, kFFTSize >::TransformType
TransformType
Definition: CTFFT.h:526
CTFFT::RealDiscrete::kC2R
@ kC2R
Definition: CTFFT.h:529
CTFFT::log2
constexpr unsigned log2(unsigned x)
Definition: CTFFT.h:80
CTFFT::FourierTransform::FourierTransform
FourierTransform(bool inverseTransform=false)
Definition: CTFFT.h:288
CTFFT::sqrt1_2
constexpr long double sqrt1_2
Definition: CTFFT.h:78
DECLARE_COSTABLE
#define DECLARE_COSTABLE(nb)
BF
#define BF(x, y, a, b)
Definition: CTFFT.h:335
CTFFT_MAXBITS
#define CTFFT_MAXBITS
Definition: CTFFT.h:72
CTFFT::RealDiscrete::nbits
static constexpr unsigned nbits
Definition: CTFFT.h:603
CTFFT
Definition: CTFFT.h:75
CTFFT::CosTable
Definition: CTFFT.h:94
CTFFT::RealDiscrete
Definition: CTFFT.h:523
CTFFT::RealDiscrete::kInverseR2C
@ kInverseR2C
Definition: CTFFT.h:530
CTFFT::RealDiscrete::negative
bool negative
Definition: CTFFT.h:606
CTFFT::RealDiscrete::tcos
const T * tcos
Definition: CTFFT.h:609
CTFFT::RealDiscrete::calculate
void calculate(T *data)
Definition: CTFFT.h:542
CTFFT::RealDiscrete::fft
FourierTransform< T, 1<<(nbits-1), costable > fft
Definition: CTFFT.h:608
PROGMEM
const int pow14[4] PROGMEM
Definition: mp3_decoder.h:259
TRANSFORM
#define TRANSFORM(a0, a1, a2, a3, wre, wim)
Definition: CTFFT.h:367