P2.5: decode twin-mask factory (FUN_18056e3e0 = constant fill 2π/(count·SR)) + band LUT apply (FUN_180563a60: level->gain t^γ/power-law); implement in levelpath.cpp, levelpath_check ALL OK
This commit is contained in:
+51
-24
@@ -34,6 +34,9 @@ static constexpr float DEPTH_SCALE = 4.0f; // DAT_1824c4334
|
||||
static constexpr float DB_CONV = 8.68588924407959f; // 20/ln(10) (DAT_1824c43e0)
|
||||
static constexpr float FLOOR_DB = -6.907755374908447f; // ln(0.001) (DAT_1824c4704)
|
||||
static constexpr float FLOOR_LIN = 0.001f; // exp(FLOOR_DB)
|
||||
static constexpr double TWO_PI = 6.283185307179586; // DAT_1824c4248 (2π, twin-mask factory)
|
||||
static constexpr float SCALE_1024 = 0.0009765625f; // 1/1024 (DAT_1824c3c50, band LUT apply)
|
||||
static constexpr float CONST_5 = 5.0f; // DAT_1824c4230 (AudioProcessingModule ctor)
|
||||
|
||||
// PRNG state offsets from param_1
|
||||
static constexpr int PRNG_STATE = 0x2404e0;
|
||||
@@ -96,35 +99,59 @@ void lut_curve_eval(void* ctx) {
|
||||
}
|
||||
|
||||
// FUN_18056e3e0: twin-mask factory
|
||||
// Creates per-band mask by applying twin resonance to the LUT curve
|
||||
// band_count = number of bands (max 6)
|
||||
// N = 1024 (FFT size for LUT evaluation)
|
||||
// Output stride: 0x2000 (8192 bytes = 1024 doubles)
|
||||
// DECODED (decomp_funs2.txt:7988 + f_56e3e0.dis): fills the 0x400-bin mask
|
||||
// with a SINGLE scalar s = 2π / (count·SR), where
|
||||
// count = [ctx+0x240080] (int), SR = [ctx+0x24] (float, internal SR).
|
||||
// NOT a per-bin twin resonance — a constant fill (the "twin" shape enters
|
||||
// elsewhere via the LUT curve FUN_180563440). Output mask stride 0x2000/band.
|
||||
void twin_mask_factory(void* ctx, int band_idx, int n_bins) {
|
||||
auto* base = static_cast<uint8_t*>(ctx);
|
||||
// Calls twin evaluation for each bin
|
||||
// TODO: transcribe the full loop from disassembly
|
||||
// The factory applies the band's resonance shape to the LUT curve
|
||||
int count = *reinterpret_cast<int*>(base + 0x240080);
|
||||
float sr = *reinterpret_cast<float*>(base + 0x24);
|
||||
double s = TWO_PI / (static_cast<double>(count) * static_cast<double>(sr));
|
||||
float* mask = reinterpret_cast<float*>(base + 0x4198 + band_idx * 0x2000);
|
||||
for (int i = 0; i < 0x400; i++) {
|
||||
mask[i] = static_cast<float>(s);
|
||||
}
|
||||
}
|
||||
|
||||
// FUN_180563a60: band combine
|
||||
// Combines 6 band masks into final per-bin gain
|
||||
// Stereo: max 2 channels, output stride per band = 0x2000
|
||||
// Pattern: gain = 1.0 - sum(band_masks)
|
||||
void band_combine(void* ctx, int n_channels, int n_bins) {
|
||||
// FUN_180563a60: band LUT apply (level -> gain). DECODED (decomp_funs2.txt:8975 + f_563a60.dis).
|
||||
// For each of 6 bands and 0x400 bins:
|
||||
// level_dB = 20·log10(mask[band][bin]) (logf · 8.6859)
|
||||
// level_axis[bin] = bin·(1/1024) (SCALE_1024)
|
||||
// t = clamp((dB − A)/(B − A), 0, 1) (BandConfig ctx+0x180: A,B,gamma,flag)
|
||||
// if gamma == 1.0: val = t
|
||||
// elif flag == 0 (linear): val = t^gamma (powf, NOT 1/gamma)
|
||||
// else (power-law): val = 0.5·(1 + sign(2t−1)·|2t−1|^gamma)
|
||||
// level_axis[bin+1] = val (pairs level, gain)
|
||||
// NOTE: this is the INVERSE curve of FUN_180563440 (which uses x^(1/γ)).
|
||||
void band_lut_apply(void* ctx) {
|
||||
auto* base = static_cast<uint8_t*>(ctx);
|
||||
int band_count = *reinterpret_cast<int*>(base + 0x540868);
|
||||
if (band_count > 6) band_count = 6;
|
||||
|
||||
// Output accumulator at r13+0x2198
|
||||
// Each band's mask is at r13+0x2198 + band_idx * 0x2000
|
||||
|
||||
for (int ch = 0; ch < n_channels; ch++) {
|
||||
// For each bin: sum all band contributions
|
||||
// Then invert: gain = 1.0 - sum
|
||||
double* acc = reinterpret_cast<double*>(base + 0x2198 + ch * 0x2000);
|
||||
for (int bin = 0; bin < n_bins; bin++) {
|
||||
acc[bin] = ONE - acc[bin];
|
||||
float* bandcfg = *reinterpret_cast<float**>(base + 0x180);
|
||||
float A = bandcfg[0];
|
||||
float B = bandcfg[1];
|
||||
float gamma = bandcfg[3];
|
||||
float flag = bandcfg[4];
|
||||
double* mask = reinterpret_cast<double*>(base + 0x4198);
|
||||
for (int band = 0; band < 6; band++) {
|
||||
double* m = mask + band * 0x400;
|
||||
float* level_gain = *reinterpret_cast<float**>(base + 0xe0 + band * 0x18);
|
||||
for (int bin = 0; bin < 0x400; bin++) {
|
||||
float db = logf(static_cast<float>(m[bin])) * DB_CONV;
|
||||
level_gain[bin * 2] = static_cast<float>(bin) * SCALE_1024;
|
||||
float t = (db - A) / (B - A);
|
||||
t = std::max(ZERO, std::min(ONE, t));
|
||||
float val = t;
|
||||
if (gamma != ONE) {
|
||||
if (flag == ZERO) {
|
||||
val = powf(t, gamma);
|
||||
} else {
|
||||
float u = TWO * t - ONE;
|
||||
float sgn = (u < ZERO) ? NEG1 : ONE;
|
||||
val = HALF * (ONE + sgn * powf(fabsf(u), gamma));
|
||||
}
|
||||
}
|
||||
level_gain[bin * 2 + 1] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user