#include "fft.h" #include static float window[FFT_SIZE]; constexpr float M_PI = 3.14159; // Call once before use void init_hamming_window() { for (int i = 0; i < FFT_SIZE; i++) { window[i] = 0.54f - 0.46f * cosf(2.0f * (float)M_PI * i / (FFT_SIZE - 1)); } } static unsigned int bit_reverse(unsigned int x, int log2n) { unsigned int n = 0; for (int i = 0; i < log2n; i++) { n <<= 1; n |= (x & 1); x >>= 1; } return n; } void compute_fft(float* time_data, float* freq_out) { static float real[FFT_SIZE]; static float imag[FFT_SIZE]; int log2n = 0; for (int t = FFT_SIZE; t > 1; t >>= 1) ++log2n; // Apply Hamming window for (int i = 0; i < FFT_SIZE; i++) { real[i] = time_data[i] * window[i]; imag[i] = 0.0f; } // Bit reversal for (int i = 0; i < FFT_SIZE; ++i) { int j = bit_reverse(i, log2n); if (j > i) { float tmp_re = real[i], tmp_im = imag[i]; real[i] = real[j]; imag[i] = imag[j]; real[j] = tmp_re; imag[j] = tmp_im; } } // Cooley-Tukey FFT for (int s = 1; s <= log2n; ++s) { int m = 1 << s; for (int k = 0; k < FFT_SIZE; k += m) { for (int j = 0; j < m / 2; ++j) { int t = k + j; int u = t + m / 2; float angle = -2.0f * (float)M_PI * j / m; float w_real = cosf(angle); float w_imag = sinf(angle); float re = w_real * real[u] - w_imag * imag[u]; float im = w_real * imag[u] + w_imag * real[u]; real[u] = real[t] - re; imag[u] = imag[t] - im; real[t] += re; imag[t] += im; } } } for (int i = 0; i < FFT_SIZE / 2; ++i) { float mag = sqrtf(real[i] * real[i] + imag[i] * imag[i]) / FFT_SIZE; float db = 20.0f * log10f(mag + 1e-6f); // Decibels float normalized = (db + 60.0f) / 60.0f; // [0,1] freq_out[i] = mag; } }