#pragma once #include #include #include #include #include "fft.hpp" #include "framed_model.hpp" constexpr size_t DEFAULT_NFFT = 2048; constexpr size_t DEFAULT_HOP = 512; class SpectralProcessor { public: SpectralProcessor(size_t nfft = DEFAULT_NFFT, size_t hop = DEFAULT_HOP, float sample_rate = 44100.0f); ~SpectralProcessor(); void setDetectorParams(const std::vector& bands); void processBlock(float* in, float* out, size_t num_samples, size_t num_channels = 1); private: size_t nfft_; size_t hop_; std::vector window_; FFTPlan plan_; std::vector> buf_; std::vector> tmp_buf_; std::vector> fir_buf_; std::vector> fir_freq_; std::vector fir_window_; std::vector overlap_; std::vector mask_; FramedDetector detector_; size_t frame_count_; size_t output_pos_; void computeWindow(); void stftFrame(const float* in, std::complex* out); void istftFrame(std::complex* in, float* out, float* overlap); // FIR construction from detector mask (52b550-52b8bb pipeline): // mask → log → sign-invert → EXP → twiddle ops → window → normalize // Produces frequency-domain FIR kernel for complex multiply application. void buildFirFromMask(const float* mask, std::complex* fir, size_t nbin); // WIN_freq: live-captured freq-path window (0x540658), 0.5→1.0 std::vector win_freq_; bool win_freq_loaded_ = false; void loadWinFreq(); };