22w: faithful mask-shaping chain v1 behind RT_FAITHFUL (fnfaith.cpp) — exact 180533340 freq-warped bidir-IIR coefficients (fc_bin=85@48k/4096, constants from dump); corpus TOTAL 5.315 but comb 2.57 best-ever; decisive: mask shape cannot balance dual tones -> level contrast is created by the DETECTOR (time-domain twin bank hypothesis priority #1)
This commit is contained in:
@@ -25,6 +25,7 @@ add_library(soothe2_dsp SHARED
|
||||
exp2.cpp
|
||||
leveltrack.cpp
|
||||
framed_model.cpp
|
||||
fnfaith.cpp
|
||||
fn529fe0.cpp
|
||||
rt_weights.cpp
|
||||
rt_mask_tables.cpp
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
#include "fnfaith.hpp"
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace fnfaith {
|
||||
|
||||
Params params_from_env() {
|
||||
Params p{};
|
||||
p.scale = getenv("RT_FAITH_SCALE") ? atof(getenv("RT_FAITH_SCALE")) : 1.0;
|
||||
p.kappa = getenv("RT_FAITH_KAPPA") ? atof(getenv("RT_FAITH_KAPPA")) : 0.0094;
|
||||
p.p = getenv("RT_FAITH_P") ? atof(getenv("RT_FAITH_P")) : 0.822;
|
||||
p.tau1 = getenv("RT_FAITH_TAU1") ? atof(getenv("RT_FAITH_TAU1")) : 19.03;
|
||||
p.mult1 = getenv("RT_FAITH_MULT1") ? atof(getenv("RT_FAITH_MULT1")) : 360.0;
|
||||
p.tau3 = getenv("RT_FAITH_TAU3") ? atof(getenv("RT_FAITH_TAU3")) : 10.68;
|
||||
p.mult3 = getenv("RT_FAITH_MULT3") ? atof(getenv("RT_FAITH_MULT3")) : 2400.0;
|
||||
p.tau4 = getenv("RT_FAITH_TAU4") ? atof(getenv("RT_FAITH_TAU4")) : 10.68;
|
||||
p.mult4 = getenv("RT_FAITH_MULT4") ? atof(getenv("RT_FAITH_MULT4")) : 2400.0;
|
||||
p.C_hz = getenv("RT_FAITH_C") ? atof(getenv("RT_FAITH_C")) : 1000.0;
|
||||
return p;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct FaithCoefs {
|
||||
std::vector<double> up, down;
|
||||
};
|
||||
|
||||
// FUN_180533340 transcription (constants from dump: DAT_24c3d8c=0.5, DAT_24c46b8=-2pi)
|
||||
FaithCoefs gen_coefs(size_t nbin, double sr, double tau, double mult, double p,
|
||||
double C_hz, double kappa) {
|
||||
FaithCoefs c;
|
||||
c.up.assign(nbin, 0.0);
|
||||
c.down.assign(nbin, 1.0);
|
||||
const double srh = sr * 0.5;
|
||||
const double fcnorm = (C_hz / srh) * (double)nbin;
|
||||
for (size_t i = 1; i < nbin; i++) {
|
||||
const double r = fcnorm / (double)i;
|
||||
const double g = ((double)i <= fcnorm) ? r : std::pow(r, p);
|
||||
const double cd = 1.0 / (g * tau / mult + 1.0);
|
||||
double up = std::exp(cd * g * tau * kappa * (-6.283185307179586));
|
||||
if (up > 1.0) up = 1.0;
|
||||
if (up < 0.0) up = 0.0;
|
||||
c.up[i] = up;
|
||||
c.down[i] = 1.0 - up;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// FUN_18052d650: acc=0; forward all bins; backward n-2..1, acc persists into bwd.
|
||||
void bidir(std::vector<double>& accst, const FaithCoefs& cf, float* x, size_t nbin) {
|
||||
double acc = 0.0;
|
||||
accst[0] = 0.0;
|
||||
for (size_t i = 0; i < nbin; i++) {
|
||||
acc = cf.up[i] * acc + cf.down[i] * (double)x[i];
|
||||
x[i] = (float)acc;
|
||||
}
|
||||
for (size_t i = (size_t)((long long)nbin - 2); i >= 1; i--) {
|
||||
acc = cf.up[i] * acc + cf.down[i] * (double)x[i];
|
||||
x[i] = (float)acc;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void band_mask_faithful(const float* am, const float* res, size_t nbin,
|
||||
float sample_rate, float scale_factor, const Params& pr,
|
||||
float* mask_out) {
|
||||
static std::vector<FaithCoefs> cache;
|
||||
static size_t cached_nbin = 0;
|
||||
static double cached_sr = 0.0;
|
||||
static Params cached_pr{};
|
||||
if (cache.empty() || cached_nbin != nbin || cached_sr != sample_rate ||
|
||||
cached_pr.kappa != pr.kappa || cached_pr.p != pr.p ||
|
||||
cached_pr.tau1 != pr.tau1 || cached_pr.mult1 != pr.mult1 ||
|
||||
cached_pr.tau3 != pr.tau3 || cached_pr.mult3 != pr.mult3 ||
|
||||
cached_pr.tau4 != pr.tau4 || cached_pr.mult4 != pr.mult4 ||
|
||||
cached_pr.C_hz != pr.C_hz) {
|
||||
cache.clear();
|
||||
cache.push_back(gen_coefs(nbin, sample_rate, pr.tau1, pr.mult1, pr.p, pr.C_hz, pr.kappa));
|
||||
cache.push_back(gen_coefs(nbin, sample_rate, pr.tau3, pr.mult3, pr.p, pr.C_hz, pr.kappa));
|
||||
cache.push_back(gen_coefs(nbin, sample_rate, pr.tau4, pr.mult4, pr.p, pr.C_hz, pr.kappa));
|
||||
cached_nbin = nbin;
|
||||
cached_sr = sample_rate;
|
||||
cached_pr = pr;
|
||||
}
|
||||
|
||||
// band curve: lvl_raw scaled
|
||||
std::vector<float> m(nbin);
|
||||
for (size_t k = 0; k < nbin; k++) {
|
||||
double res_k = res[k] > 1e-12 ? (double)res[k] : 1e-12;
|
||||
double lvl = (double)am[k] / res_k * (double)scale_factor;
|
||||
m[k] = (float)(std::exp2(-(lvl * pr.scale)) );
|
||||
}
|
||||
|
||||
std::vector<double> accst(1, 0.0);
|
||||
bidir(accst, cache[0], m.data(), nbin); // #1
|
||||
bidir(accst, cache[0], m.data(), nbin); // #2
|
||||
bidir(accst, cache[1], m.data(), nbin); // #3
|
||||
bidir(accst, cache[2], m.data(), nbin); // #4a
|
||||
bidir(accst, cache[2], m.data(), nbin); // #4b
|
||||
|
||||
for (size_t k = 0; k < nbin; k++) mask_out[k] = m[k];
|
||||
}
|
||||
|
||||
} // namespace fnfaith
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
// FAITHFUL mask-shaping chain (22w) — transcription of FUN_180529fe0 per
|
||||
// handoff/BLOCKMAP_529fe0.md (raw asm). Replaces process_band_structural
|
||||
// when RT_FAITHFUL=1.
|
||||
//
|
||||
// band = lvl * s (s = RT_FAITH_SCALE, decomp: /0x1a0*0x870*0x88c)
|
||||
// mask = exp2(-band) (bigkernel exp2 family)
|
||||
// bidir(mask, A); bidir(mask, A) // states reset each pass (52d650 + inline)
|
||||
// bidir(mask, B) // pass #3
|
||||
// bidir(mask, C); bidir(mask, C) // pass #4 x2
|
||||
// mirror upper half; dry/wet identity.
|
||||
//
|
||||
// Bidirectional one-pole per FUN_18052d650: acc = up[i]*acc + down[i]*x[i],
|
||||
// forward over all bins, backward n-2..1 with persistent acc, reset per call.
|
||||
// Coefficients per FUN_180533340 (freq-warped): fc_bin = C/(sr/2)*nbin;
|
||||
// g = fc/i below crossover, powf(fc/i, p) above; c = 1/(g*tau/mult+1);
|
||||
// up[i] = exp(-2*pi*kappa*c*g*tau), down[i] = 1-up[i].
|
||||
//
|
||||
// Decoded defaults (FUN_180530b60 log-interp @ live 0x540878/87c = 0.5):
|
||||
// setA/B tau=19.03 mult=360 ; set3/set4 tau=10.68 mult=2400 ; p=0.822 ;
|
||||
// C=1000 Hz ; kappa = 1/T8 ~ 0.0094 (T8 unknown -> env).
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace fnfaith {
|
||||
|
||||
struct Params {
|
||||
double scale; // RT_FAITH_SCALE
|
||||
double kappa; // RT_FAITH_KAPPA
|
||||
double p; // RT_FAITH_P
|
||||
double tau1, mult1; // state A (#1,#2)
|
||||
double tau3, mult3; // state B (#3)
|
||||
double tau4, mult4; // state C (#4 x2)
|
||||
double C_hz; // crossover (1000)
|
||||
};
|
||||
|
||||
Params params_from_env();
|
||||
|
||||
// Compute lower-half mask [0, nbin) for one band from lvl_raw = am/res*scale_factor.
|
||||
void band_mask_faithful(const float* am, const float* res, size_t nbin,
|
||||
float sample_rate, float scale_factor, const Params& pr,
|
||||
float* mask_out /* nbin */);
|
||||
|
||||
} // namespace fnfaith
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "rt_mask_tables.hpp"
|
||||
#include "rt_weights.hpp"
|
||||
#include "fn529fe0.hpp"
|
||||
#include "fnfaith.hpp"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
@@ -414,10 +415,22 @@ void FramedDetector::processFrame(const std::complex<double>* spectrum, float* m
|
||||
for (size_t k = 0; k <= half; k++) mask[k] = 1.0f;
|
||||
|
||||
if (is_internal_grid(nfft_, sample_rate_)) {
|
||||
// RT_FAITHFUL=1 (NOTES 22w): BLOCKMAP_529fe0 transcription path
|
||||
static const int faithful = getenv("RT_FAITHFUL") ? atoi(getenv("RT_FAITHFUL")) : 0;
|
||||
static const fnfaith::Params fparams = faithful ? fnfaith::params_from_env()
|
||||
: fnfaith::Params{};
|
||||
// same scale_factor as process_band_structural (line ~79)
|
||||
constexpr float sf = 15.0f * 440.95f / 2048.0f;
|
||||
for (size_t b = 0; b < bands_.size(); b++) {
|
||||
std::vector<float> band_mask(nfft_, 1.0f);
|
||||
if (faithful) {
|
||||
fnfaith::band_mask_faithful(am_.data(), res_[b].data(), half + 1,
|
||||
sample_rate_, sf, fparams,
|
||||
band_mask.data());
|
||||
} else {
|
||||
process_band_structural(am_.data(), res_[b].data(), bands_[b],
|
||||
band_mask.data(), nfft_, sample_rate_);
|
||||
}
|
||||
for (size_t k = 0; k <= half; k++) {
|
||||
mask[k] = std::min(band_mask[k], mask[k]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user