You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.5KB

  1. #pragma once
  2. #include <complex>
  3. namespace rack {
  4. /** Simple FFT implementation
  5. If you need something fast, use pffft, KissFFT, etc instead.
  6. The size N must be a power of 2
  7. */
  8. struct SimpleFFT {
  9. int N;
  10. /** Twiddle factors e^(2pi k/N), interleaved complex numbers */
  11. std::complex<float> *tw;
  12. SimpleFFT(int N, bool inverse) : N(N) {
  13. tw = new std::complex<float>[N];
  14. for (int i = 0; i < N; i++) {
  15. float phase = 2*M_PI * (float)i / N;
  16. if (inverse)
  17. phase *= -1.0;
  18. tw[i] = std::exp(std::complex<float>(0.0, phase));
  19. }
  20. }
  21. ~SimpleFFT() {
  22. delete[] tw;
  23. }
  24. /** Reference naive implementation
  25. x and y are arrays of interleaved complex numbers
  26. y must be size N/s
  27. s is the stride factor for the x array which divides the size N
  28. */
  29. void dft(const std::complex<float> *x, std::complex<float> *y, int s=1) {
  30. for (int k = 0; k < N/s; k++) {
  31. std::complex<float> yk = 0.0;
  32. for (int n = 0; n < N; n += s) {
  33. int m = (n*k) % N;
  34. yk += x[n] * tw[m];
  35. }
  36. y[k] = yk;
  37. }
  38. }
  39. void fft(const std::complex<float> *x, std::complex<float> *y, int s=1) {
  40. if (N/s <= 2) {
  41. // Naive DFT is faster than further FFT recursions at this point
  42. dft(x, y, s);
  43. return;
  44. }
  45. std::complex<float> *e = new std::complex<float>[N/(2*s)]; // Even inputs
  46. std::complex<float> *o = new std::complex<float>[N/(2*s)]; // Odd inputs
  47. fft(x, e, 2*s);
  48. fft(x + s, o, 2*s);
  49. for (int k = 0; k < N/(2*s); k++) {
  50. int m = (k*s) % N;
  51. y[k] = e[k] + tw[m] * o[k];
  52. y[k + N/(2*s)] = e[k] - tw[m] * o[k];
  53. }
  54. delete[] e;
  55. delete[] o;
  56. }
  57. };
  58. } // namespace rack