#pragma once #include namespace rack { /** Simple FFT implementation If you need something fast, use pffft, KissFFT, etc instead. The size N must be a power of 2 */ struct SimpleFFT { int N; /** Twiddle factors e^(2pi k/N), interleaved complex numbers */ std::complex *tw; SimpleFFT(int N, bool inverse) : N(N) { tw = new std::complex[N]; for (int i = 0; i < N; i++) { float phase = 2*M_PI * (float)i / N; if (inverse) phase *= -1.0; tw[i] = std::exp(std::complex(0.0, phase)); } } ~SimpleFFT() { delete[] tw; } /** Reference naive implementation x and y are arrays of interleaved complex numbers y must be size N/s s is the stride factor for the x array which divides the size N */ void dft(const std::complex *x, std::complex *y, int s=1) { for (int k = 0; k < N/s; k++) { std::complex yk = 0.0; for (int n = 0; n < N; n += s) { int m = (n*k) % N; yk += x[n] * tw[m]; } y[k] = yk; } } void fft(const std::complex *x, std::complex *y, int s=1) { if (N/s <= 2) { // Naive DFT is faster than further FFT recursions at this point dft(x, y, s); return; } std::complex *e = new std::complex[N/(2*s)]; // Even inputs std::complex *o = new std::complex[N/(2*s)]; // Odd inputs fft(x, e, 2*s); fft(x + s, o, 2*s); for (int k = 0; k < N/(2*s); k++) { int m = (k*s) % N; y[k] = e[k] + tw[m] * o[k]; y[k + N/(2*s)] = e[k] - tw[m] * o[k]; } delete[] e; delete[] o; } }; } // namespace rack