diff --git a/dsp/framed_model.cpp b/dsp/framed_model.cpp index 8bf2eb7..9d9f166 100644 --- a/dsp/framed_model.cpp +++ b/dsp/framed_model.cpp @@ -200,7 +200,6 @@ static void process_band_structural( double res_k = std::max(static_cast(res[k]), 1e-12); raw_level[k] = static_cast(static_cast(am[k]) / res_k * scale_factor_x); } - // Apply k-mapping to raw_level as well (VLAW path uses raw_level, not lvl_in) if (kmap_on) { double k_sens; if (band.sens < 12) k_sens = 0.44 + (band.sens - 6.0) * (0.56 / 6.0); @@ -217,6 +216,26 @@ static void process_band_structural( double k_tot2 = k_sens * k_q; if (k_tot2 > 1e-9) for (size_t k = 0; k < nbin; k++) raw_level[k] = static_cast(raw_level[k] / k_tot2); } + static const int eq_on2 = getenv("RT_EQ") ? atoi(getenv("RT_EQ")) : 1; + if (eq_on2) { + double eq_gain = 0.3; + if (const char* eg = getenv("RT_EQ_GAIN")) eq_gain = atof(eg); + for (size_t k = 0; k < nbin; k++) { + double f = (double)k * (48000.0 * 0.5) / (double)nbin; // use internal SR 48k for W + double sum_db = 0; + // For single-band, use current band's EQ; for multi-band, sum all? Use current band only for lvl + double H = 0; + if (band.fc >= 1.0) { + double Qeff = 1.54 * std::pow(band.q, 1.33); + double A = f / band.fc - band.fc / f; + if (std::isfinite(A)) H = 1.0 / std::sqrt(1.0 + (Qeff*A)*(Qeff*A)); + } + sum_db = band.sens * H; + double w = std::pow(10.0, (sum_db * eq_gain / 12.0) / 20.0); + lvl_in[k] *= static_cast(w); + raw_level[k] *= static_cast(w); + } + } // RT_VLAW=1 (NOTES 24m): decoded two-stage detector law. // cutS(b) = alpha * ln(1 + lvl_raw / beta) + c + Delta(b) [stage-S] @@ -675,6 +694,16 @@ void FramedDetector::setParams(const std::vector& bands) { cascade_states_.assign(bands_.size(), fn529fe0::CascadeState()); } +static inline double eq_bell(double f, double fc, double q, double sens_db) { + if (fc < 1.0 || sens_db == 0) return 1.0; + double Qeff = 1.54 * std::pow(q, 1.33); + double A = f / fc - fc / f; + if (!std::isfinite(A)) return 1.0; + double H = 1.0 / std::sqrt(1.0 + (Qeff * A)*(Qeff * A)); + double gain = std::pow(10.0, sens_db / 40.0); + return 1.0 + (gain - 1.0) * H; +} + void FramedDetector::processFrame(const std::complex* spectrum, float* mask) { size_t half = nfft_ / 2; if (wsum_ == 0.0) { @@ -708,6 +737,7 @@ void FramedDetector::processFrame(const std::complex* spectrum, float* m am_[k] = static_cast(am); } } + // EQ before detector moved to lvl calc in process_band_structural (not am_ state) // Detector cascade 529c60: per-band pre-processor on complex twin-filtered // spectrum. Computes magnitudes, Haar-smooths, applies sin-peak floor.