22u: raw-asm re-decode of FUN_180529fe0 — multiband pre-combine inside method, per-band scale->kernel->2x bidir-double-IIR (52d650 fully decoded, per-bin double coefs), band-state arrays 0x540768[i]/0x5407a8[i]; 0x5407c8 acc has NO runtime reader (21b addr wrong); offline bidir-IIR smoothing hypothesis REFUTED (monotonic degradation)
This commit is contained in:
+25
-6
@@ -156,12 +156,29 @@ class CaseInput:
|
||||
return lvl.shape[0] == self.nf
|
||||
|
||||
|
||||
def masks_from_lvl(lvl, nb, A, S, Q=0.0, res=None, rp=0.0):
|
||||
def _bidir_iir(lo, c):
|
||||
"""FUN_18052d650 semantics approx: bidirectional single-pole IIR along bins,
|
||||
reset->forward->backward with persistent state, applied twice (22u).
|
||||
Normalised form acc = c*acc + (1-c)*x (unity DC gain); vectorised over
|
||||
leading axes via lfilter (endpoints differ slightly from C++ loop)."""
|
||||
if c <= 0:
|
||||
return lo
|
||||
from scipy.signal import lfilter
|
||||
b, a = [1.0 - c], [1.0, -c]
|
||||
y = np.asarray(lo, dtype=np.float64)
|
||||
for _ in range(2):
|
||||
y = lfilter(b, a, y, axis=-1)
|
||||
y = lfilter(b, a, y[..., ::-1], axis=-1)[..., ::-1]
|
||||
return y
|
||||
|
||||
|
||||
def masks_from_lvl(lvl, nb, A, S, Q=0.0, res=None, rp=0.0, iir_c=0.0):
|
||||
"""Per-frame lower-half mask exactly as bare chain + LAWAFFINE produces.
|
||||
|
||||
Law families (22t): scalar cut=A+S*log2(lvl); quad adds curvature Q*x^2;
|
||||
resrp multiplies per-band mask by res^rp (decomp warp-cascade factor,
|
||||
applied BEFORE cross-band min like the C++ warp section).
|
||||
iir_c>0: bidirectional bin-IIR smoothing per band (22u, FUN_18052d650).
|
||||
"""
|
||||
nf = lvl.shape[0]
|
||||
lv64 = lvl.astype(np.float64)
|
||||
@@ -172,6 +189,8 @@ def masks_from_lvl(lvl, nb, A, S, Q=0.0, res=None, rp=0.0):
|
||||
mm[low] = np.exp2(-lv64[low])
|
||||
if res is not None and rp:
|
||||
mm = mm * res[None].astype(np.float64) ** rp
|
||||
if iir_c > 0:
|
||||
mm = _bidir_iir(mm, iir_c)
|
||||
if nb > 1:
|
||||
lo = np.min(mm, axis=1) # min across bands
|
||||
else:
|
||||
@@ -182,10 +201,10 @@ def masks_from_lvl(lvl, nb, A, S, Q=0.0, res=None, rp=0.0):
|
||||
return full
|
||||
|
||||
|
||||
def replay(ci, lvl, nb, A, S, Q=0.0, res=None, rp=0.0):
|
||||
def replay(ci, lvl, nb, A, S, Q=0.0, res=None, rp=0.0, iir_c=0.0):
|
||||
"""Return trimmed 44.1k output for law params on prepared CaseInput ci."""
|
||||
assert ci.frames_ok(lvl), f'traj {lvl.shape[0]} != frames {ci.nf}'
|
||||
full = masks_from_lvl(lvl, nb, A, S, Q, res, rp)
|
||||
full = masks_from_lvl(lvl, nb, A, S, Q, res, rp, iir_c)
|
||||
segs = ci.xext[ci.offs[:, None] + np.arange(NFFT)[None, :]] * _WIN[None, :]
|
||||
yspec = np.fft.fft(segs, axis=1) * full
|
||||
td = np.real(np.fft.ifft(yspec, axis=1))
|
||||
@@ -232,15 +251,15 @@ def build_eval_index(trajs):
|
||||
return idx
|
||||
|
||||
|
||||
def sim_errors(trajs, idx, A, S, Q=0.0, rp=0.0):
|
||||
def sim_errors(trajs, idx, A, S, Q=0.0, rp=0.0, iir_c=0.0):
|
||||
errs = {}
|
||||
ycache = {}
|
||||
for e in idx:
|
||||
ck = (e['key'], e['nb'], round(Q, 6), round(rp, 6))
|
||||
ck = (e['key'], e['nb'], round(Q, 6), round(rp, 6), round(iir_c, 6))
|
||||
if ck not in ycache:
|
||||
ci = case_input(e['key'], e['inp'])
|
||||
ycache[ck] = replay(ci, trajs[e['key']], e['nb'], A, S,
|
||||
Q, trajs.get(e['key'] + '|res'), rp)
|
||||
Q, trajs.get(e['key'] + '|res'), rp, iir_c)
|
||||
y44 = ycache[ck]
|
||||
errs[e['name']] = corpus.db(corpus.ta(y44, e['f'])) - \
|
||||
corpus.db(corpus.ta(corpus.load_mono(e['ref']), e['f']))
|
||||
|
||||
Reference in New Issue
Block a user