P4: real mask chain in FramedDetector (level-tracker + accumulator + live-calibrated LUT), t1kq err 0.5dB

Replace empirical PCHIP detector with live-calibrated mask chain from FUN_180529fe0:
  level = am*res*scale; track += w*(level-track) (per-bin attack/release weights
  extracted from RT snapshot, rt_weights.hpp); acc = (level-track)+level; mask =
  (1/(1+K*acc))^n (K=9.8026 n=0.25966 fitted to live mask band0). min-combine.

Results (N=2048 hop=512): t1kq single-band err +0.51 dB (-14.47 vs -14.98 dB ref);
comb 4-band per-tone -3.4..+5.8 dB (old PCHIP over-cut comb ~6 dB). Adds framed_test
harness for C++ FramedDetector eval on tone1kq/comb.
This commit is contained in:
2026-08-20 13:11:27 +03:00
parent 5c939583f5
commit fc48a9fee4
7 changed files with 180 additions and 63 deletions
+10 -9
View File
@@ -7,16 +7,17 @@ struct DetectorBand {
float fc; // band center freq (Hz)
float q; // resonance Q
float sens; // XML sens (dB); internal sens_stored = sens * 2.054
float level_scale = 1.0f; // calibration: level = am * res * level_scale
};
// 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)
// FramedDetector — C++ port of the real soothe mask chain (FUN_180529fe0).
// Per band, per bin:
// level_k = am_k * res_k (twin resonance x smoothed amplitude)
// track += w_k * (level - track) (per-bin level tracker, attack/release
// weights w from live capture rt_weights)
// acc_k = 2*level_k - track_k (accumulator, live peak ~10.08 at tone)
// mask_k = LUT(acc_k) (fitted mask curve from live capture)
// final mask = min over bands (max suppression), like soothe's band combine.
class FramedDetector {
public:
FramedDetector(size_t nfft, float sample_rate);
@@ -35,5 +36,5 @@ private:
std::vector<std::vector<float>> res_; // per band, per bin |2B/A|
std::vector<float> warp_; // per-bin warp tilt
std::vector<float> am_; // smoothed per-bin amplitude
std::vector<float> rp_; // per-band res power
std::vector<std::vector<float>> track_; // per band, per bin level tracker
};