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:
2026-08-17 20:02:32 +03:00
parent 847725f5fc
commit b1b4f2bdf7
4 changed files with 77 additions and 52 deletions
+12 -11
View File
@@ -1,18 +1,27 @@
#include "fft.hpp"
#include "fft_stage.hpp"
#include "twiddle_loader.hpp"
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
namespace fft {
// twiddle loader drops angles modulo — matches soothe: angles arrive as
// float pairs, loader computes cos/sin per float
void build_twiddle(FFTPlan* plan, double* scratch) {
uint32_t N = plan->N;
uint32_t half = N / 2;
std::vector<float> angles(half);
for (uint32_t k = 0; k < half; k++) {
double angle = -2.0 * M_PI * k / N;
scratch[k * 2 + 0] = std::cos(angle);
scratch[k * 2 + 1] = std::sin(angle);
angles[k] = static_cast<float>(-2.0 * M_PI * k / N);
}
std::vector<double> cosv(half), sinv(half);
soothe::twiddle_load(angles.data(), cosv.data(), sinv.data(), half);
for (uint32_t k = 0; k < half; k++) {
scratch[k * 2 + 0] = cosv[k];
scratch[k * 2 + 1] = sinv[k];
}
}
@@ -86,12 +95,4 @@ void execute(const FFTPlan* plan, std::complex<double>* buf) {
execute_forward(plan, buf);
}
void init_plan(FFTPlan* plan, uint32_t log2N) {
plan->log2N = log2N;
plan->N = 1U << log2N;
plan->stage_count = log2N;
plan->bit_reverse = 1;
plan->xor_mask = 0;
}
}