#pragma once #include #include #include struct DetectorBand { float fc; // band center freq (Hz) float q; // resonance Q float sens; // XML sens (dB); internal sens_stored = sens * 2.054 }; // FramedDetector — C++ port of framed_render.py (Phase 5 pilot, mean=0.175 dB). // Multi-band: each active band contributes gain_k = (1-C_k)*res_k^rp, // final mask = min over bands (max suppression). // res_k[f] = |2B(z)/A(z)| (twin resonance, sens-scaled GAIN) // am = 2|X_k|/wsum (smoothed per-bin amplitude) // xv_k = log10(am / res_k) // C_k = G_FIT*LUT(xv_k) + W_FIT*warp(f)^A_FIT // gain_k = max(1-C_k, eps) * res_k^(rp0*Q_k^drp) class FramedDetector { public: FramedDetector(size_t nfft, float sample_rate); ~FramedDetector(); void setParams(const std::vector& bands); void processFrame(const std::complex* spectrum, float* mask); private: size_t nfft_; float sample_rate_; double wsum_; std::vector bands_; std::vector> res_; // per band, per bin |2B/A| std::vector warp_; // per-bin warp tilt std::vector am_; // smoothed per-bin amplitude std::vector rp_; // per-band res power };