#include "spectral.hpp" #include #include #include SpectralProcessor::SpectralProcessor(size_t nfft, size_t hop) : nfft_(nfft), hop_(hop), frame_count_(0), output_pos_(0) { window_ = new double[nfft_]; computeWindow(); fft::init_plan(&plan_, static_cast(std::log2(nfft_))); buf_ = new std::complex[nfft_]; tmp_buf_ = new std::complex[nfft_]; overlap_.resize(nfft_, 0.0f); } SpectralProcessor::~SpectralProcessor() { delete[] window_; delete[] buf_; delete[] tmp_buf_; } void SpectralProcessor::computeWindow() { for (size_t i = 0; i < nfft_; i++) { window_[i] = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / (nfft_ - 1))); } } void SpectralProcessor::stftFrame(const float* in, std::complex* out) { for (size_t i = 0; i < nfft_; i++) { out[i] = std::complex(static_cast(in[i]) * window_[i], 0.0); } fft::execute(&plan_, out); } void SpectralProcessor::istftFrame(std::complex* in, float* out, float* overlap) { memcpy(tmp_buf_, in, nfft_ * sizeof(std::complex)); fft::execute_inverse(&plan_, tmp_buf_); for (size_t i = 0; i < nfft_; i++) { overlap[i] += static_cast(tmp_buf_[i].real() * window_[i]); } for (size_t i = 0; i < hop_; i++) { out[i] = overlap[i]; } for (size_t i = 0; i < nfft_ - hop_; i++) { overlap[i] = overlap[i + hop_]; } for (size_t i = nfft_ - hop_; i < nfft_; i++) { overlap[i] = 0.0f; } } void SpectralProcessor::updateDetector() { } void SpectralProcessor::processBlock(float* in, float* out, size_t num_samples, size_t num_channels) { memset(out, 0, num_samples * sizeof(float)); if (num_samples == 0 || num_samples < nfft_) { return; } size_t nframes = (num_samples - nfft_) / hop_ + 1; for (size_t f = 0; f < nframes; f++) { size_t offset = f * hop_; if (offset + nfft_ > num_samples) break; stftFrame(in + offset, buf_); updateDetector(); istftFrame(buf_, out + offset, overlap_.data()); } }