roadmap: detector decrypted in soothe_mem.bin, SNR 19.8dB; integrate twiddle loader
- fft.cpp: build_twiddle via soothe::twiddle_load (Cody-Waite sin/cos); drop dup init_plan - fft_stage.cpp: cplx_mul/stage_complex/stage_double kernels -> phase fixed (corr +0.995) - detect.cpp: level-dependent regional floor (no bell-boost), mask 10^(-1.041*depth*floor/20) - burst500 metrics: ref -26.07 / ours -26.13 dBFS, corr 0.99475, SNR 19.80 dB, diff -0.065 dB - KEY: FUN_180535880/536f90 bodies are decrypted real SSE in soothe_mem.bin; dispatch table 0x182616008[0]=idx=4 -> 0x180009860 -> FUN_180040d40; region 0x18004xxxx = full detector algorithm, absent from prior fun_map/decomp (Ghidra ran on encrypted file)
This commit is contained in:
+17
-18
@@ -38,36 +38,35 @@ void Detector::processFrame(const std::complex<double>* spectrum, float* mask) {
|
||||
|
||||
// Compute magnitude per bin
|
||||
std::vector<float> mag(half + 1);
|
||||
double total_energy = 0.0;
|
||||
for (size_t i = 0; i <= half; i++) {
|
||||
mag[i] = static_cast<float>(std::sqrt(
|
||||
spectrum[i].real() * spectrum[i].real() +
|
||||
spectrum[i].imag() * spectrum[i].imag()));
|
||||
total_energy += static_cast<double>(mag[i]) * mag[i];
|
||||
}
|
||||
|
||||
// Overall signal level in dBFS (RMS of the spectrum)
|
||||
// Calibrated offset: spectrum overall_db → time-domain dBFS
|
||||
// For Hann window + N=2048: offset ≈ 28.8 dB
|
||||
float overall_rms = std::sqrt(total_energy / (half + 1));
|
||||
float overall_db = 20.0f * std::log10(std::max(overall_rms, 1e-10f)) - 28.847f;
|
||||
// Regional level: RMS over a moving window of bins, calibrated to dBFS
|
||||
// Empirically: peek level -8 dBFS → floor 6.1; below ~-32 dBFS → no cut
|
||||
const size_t reg = 16;
|
||||
std::vector<float> reg_db(half + 1);
|
||||
for (size_t i = 0; i <= half; i++) {
|
||||
size_t lo = (i >= reg) ? i - reg : 0;
|
||||
size_t hi = std::min(half, i + reg);
|
||||
float e = 0.0f;
|
||||
for (size_t k = lo; k <= hi; k++) e += mag[k] * mag[k];
|
||||
float rms = std::sqrt(e / (hi - lo + 1u));
|
||||
reg_db[i] = 20.0f * std::log10(std::max(rms, 1e-10f)) - 26.1f;
|
||||
}
|
||||
|
||||
// Floor reduction from overall level
|
||||
float floor_red = floor_func(overall_db);
|
||||
|
||||
// Bell curve parameters
|
||||
float qeff = 1.54f * std::pow(std::max(sharpness_, 0.5f), 1.33f);
|
||||
float sens_weight = 6.02f * std::min(1.0f, 12.0f / 12.0f); // sens=12 → full
|
||||
|
||||
for (size_t i = 0; i <= half; i++) {
|
||||
float freq = static_cast<float>(i) * bin_hz;
|
||||
// Level-dependent floor: louder bins cut deeper (matches soothe mask shape)
|
||||
float floor_red = std::max(0.0f, floor_func(reg_db[i]));
|
||||
|
||||
// Boost from bell curve at band1 frequency (500 Hz)
|
||||
float h = bell_curve(freq, 500.0f, qeff);
|
||||
float boost = sens_weight * h;
|
||||
|
||||
// Total reduction in dB
|
||||
float total_red = depth_ * (floor_red + boost);
|
||||
// Total reduction in dB (no additive band bell — tone boost is implicit
|
||||
// via higher regional level at the tone frequency)
|
||||
float total_red = 1.041f * depth_ * floor_red;
|
||||
|
||||
// Convert to linear mask: mask = 10^(-total_red/20)
|
||||
mask[i] = std::pow(10.0f, -total_red / 20.0f);
|
||||
|
||||
Reference in New Issue
Block a user