98 lines
4.5 KiB
C++
98 lines
4.5 KiB
C++
#pragma once
|
||
#include <cstddef>
|
||
#include <vector>
|
||
|
||
// Structural transcription of the soothe2 mask-apply mono path
|
||
// FUN_180529fe0 (0x5408b8==0), BITEXACT_PLAN step 1. Uses the live-captured
|
||
// tables (dsp/rt_mask_tables.*, dsp/rt_weights.*) and the exact step sequence
|
||
// from NOTES_LEVEL:820-840 / :237-253.
|
||
//
|
||
// Unlike the empirical bridge (dsp/framed_model.cpp), this reproduces the real
|
||
// reduction/exp2-domain chain:
|
||
// scale -> IIR1 -> copy -> IIR2 -> mirror -> blend(0.8 pedestal)
|
||
// -> exp2(-level)*blend -> combine/acc -> warp(kBand768*kWarp)
|
||
// -> IIR3 x2 -> dry/wet -> (FFT-conv is step 4, separate module)
|
||
//
|
||
// The IIR/weight tables are indexed 0..N/2 of the INTERNAL grid (N=4096/SR=48000);
|
||
// per-bin level is supplied by the caller (level-path), same xv domain as bridge
|
||
// (level = am/res) but fed through the structural chain instead of the LUT bridge.
|
||
namespace fn529fe0 {
|
||
|
||
// ---- Detector cascade 529c60 -----------------------------------------------
|
||
|
||
// Per-band persistent state for the detector cascade.
|
||
// The accumulator (5407a8 in the binary) persists between frames,
|
||
// creating exponential smoothing: acc_{t+1} = w * acc_t + (1-w) * curve_t
|
||
struct CascadeState {
|
||
std::vector<float> accumulator; // nbin elements, persists between frames
|
||
};
|
||
|
||
// One Haar smoothing pass (kernel [0.25, 0.5, 0.25]).
|
||
// Decoded from 529c60 Haar loop (BLOCKMAP 24mm14, lines 35-74).
|
||
// Net effect: b[i] = 0.25*b[i-1] + 0.5*b[i] + 0.25*b[i+1] (wavelet smooth).
|
||
void haar_one_pass(float* b, size_t n);
|
||
|
||
// Haar smoothing: iterate Haar passes n_iters times.
|
||
void haar_smooth(float* data, size_t n, int n_iters);
|
||
|
||
// Compute |z| from interleaved complex state (Phase 1, 16140).
|
||
// in: interleaved [re0,im0,re1,im1,...], out: [mag0,mag1,...]
|
||
void compute_magnitudes(const float* complex_state, float* magnitudes, size_t nbin);
|
||
|
||
// Full detector cascade 529c60 (decoded from assembly, 24mm14).
|
||
//
|
||
// Pipeline:
|
||
// 1. compute_magnitudes: complex → |z| (skipped if is_magnitude=true)
|
||
// 2. haar_smooth: |z| → smoothed curve
|
||
// 3. peak = max(curve)
|
||
// 4. sin_peak = sin(param*30 - 90) * 0.115129 * peak
|
||
// 5. curve[i] = max(curve[i], sin_peak)
|
||
// 6. w = -log10(pow(50, ratio*0.001) * ratio*0.001)
|
||
// 7. acc[i] = acc[i] * w + curve[i] * (1-w)
|
||
// 8. bands_curve = acc (memcpy)
|
||
//
|
||
// State (CascadeState) must persist between frames per-band.
|
||
// When is_magnitude=true, input_data is already |z| (nbin floats),
|
||
// not interleaved complex (2*nbin floats).
|
||
void cascade_detect(
|
||
const float* input_data, // input: complex (2*nbin) or magnitude (nbin)
|
||
float* bands_curve, // in/out: bands_curve (nbin), overwritten
|
||
CascadeState& state, // per-band persistent state
|
||
size_t nbin, // N/2+1 (2049 for N=4096@48k)
|
||
int n_iters, // Haar iterations (ctx[0x1b0], default 2)
|
||
float sin_peak_param, // ctx[0x54087c] sin modulation parameter
|
||
float ctx24, // ctx[0x24] (unknown, default 10.0)
|
||
int ctx1a0, // ctx[0x1a0] (init=1)
|
||
int ctx1ac, // ctx[0x1ac] (init=4)
|
||
bool is_magnitude = false // true = input_data is already |z|, skip Phase 1
|
||
);
|
||
|
||
// Main chain 9–19 (BLOCKMAP:620) — DIVIDE/FMA/EXP/FIR proxy (1c)
|
||
void chain_9_19(float* bands, float* tmp6f8, float* accVec,
|
||
const float* warp, const float* att, const float* rel,
|
||
size_t nbin);
|
||
|
||
// ---- Legacy structural chain functions --------------------------------------
|
||
|
||
// All per-bin buffers are length nbin = nfft/2+1 (internal grid).
|
||
// IIR stage: y[i] = A[i]*acc + B[i]*x[i]; acc=y (first-order leaky, like leveltrack).
|
||
void iir1(float* x, const double* A, const double* B, size_t nbin, double acc0);
|
||
|
||
// Blend step 6: f6f8[k] = freqaxis[k]*(1-mix) + mix*0.8; out = exp2(-x)*f6f8.
|
||
void blend_exp2(float* mask, const float* x, const float* freqaxis,
|
||
float mix, size_t nbin);
|
||
|
||
// Combine step 7 (reduction/exp2 domain): accumulates per-band.
|
||
// acc = band - f6f8; += wAtt[mirror]*upper; += wRel[mirror]*lower; += band
|
||
// In-place on acc; band and f6f8 are inputs (len nbin, mirrored to full nfft).
|
||
void combine_acc(double* acc, const float* band, const float* f6f8,
|
||
const float* wAtt, const float* wRel, size_t nfft);
|
||
|
||
// Warp step 8: mask *= kBand768 * kWarp (two multiplies).
|
||
void warp_mask(float* mask, const float* kBand768, const float* kWarp, size_t nbin);
|
||
|
||
// Dry/wet step 10 (fVar30=1, 0x540888=1 -> identity for default).
|
||
void dry_wet(float* mask, float fVar30, float wet, size_t nbin);
|
||
|
||
} // namespace fn529fe0
|