24mm9: FIR-chain decoded = min-phase cepstral sandwich; opB/opC are RFFT twins (plan@548), df0 = complex-mul dst=track; validated 0.0065 dB median over 60 clean frames; gamma = 1+s_F(q), q~0.8 source open
This commit is contained in:
@@ -109,8 +109,106 @@ def validate_scr(sim_scr, cap_scr, tol_db=0.05):
|
||||
return float(np.sqrt(np.mean(err ** 2))), int(m.sum())
|
||||
|
||||
|
||||
def win_periodic_hann(N):
|
||||
return 0.5 * (1.0 - np.cos(2.0 * np.pi * np.arange(N) / N))
|
||||
|
||||
|
||||
# ------------------------------------------------ FIR-цепь (24mm9) --------
|
||||
NFRAME = 4096 # n=[ctx+0x540534]
|
||||
NBINS_FIR = NFRAME // 2 + 1
|
||||
Q_EXP = 0.80 # скаляр аргумента EXP; источник в 1803831c0 (ОТКРЫТО)
|
||||
|
||||
|
||||
def winfreq_fall():
|
||||
"""WINfreq@[ctx+0x540658]: периодический Hann(4096), падающая половина."""
|
||||
return win_periodic_hann(NFRAME)[NFRAME // 2:]
|
||||
|
||||
|
||||
def fir_kernel(scr, q=Q_EXP):
|
||||
"""Полная FIR-цепь (BLOCKMAP 24mm9): min-phase кепстральный сэндвич.
|
||||
|
||||
scr(2049) → pack(re=scr,im=0) → FIR[n]=0 (Найквост)
|
||||
→ inv-RFFT → fold(y[1..2047]*=2.0 @1824c41e0; y[2049..4095]=0)
|
||||
→ fwd-RFFT → комплексная EXP (1803831c0, аргумент ×q)
|
||||
→ inv-RFFT → ×падающий Hann → ноль хвоста → fwd-RFFT
|
||||
→ FIR[0]=1, FIR[1]=0. Возвращает |F| (2049).
|
||||
"""
|
||||
h = np.asarray(scr, dtype=np.complex128).copy()
|
||||
h[-1] = 0.0
|
||||
y = np.fft.irfft(h, n=NFRAME)
|
||||
y[1:NFRAME // 2] *= 2.0
|
||||
y[NFRAME // 2 + 1:] = 0.0
|
||||
w = np.fft.irfft(np.exp(q * np.fft.rfft(y, n=NFRAME)), n=NFRAME)
|
||||
w[:NFRAME // 2] *= winfreq_fall()
|
||||
w[NFRAME // 2:] = 0.0
|
||||
F = np.abs(np.fft.rfft(w, n=NFRAME))
|
||||
F[0] = 1.0
|
||||
return F
|
||||
|
||||
|
||||
def mask_from_frame(S, q=Q_EXP):
|
||||
"""mask_sim из слотов кадра: cur ≈ trk · |F(scr)| (df0 complex-mul)."""
|
||||
scr = S[0x540628][:NBINS_FIR].astype(np.float64)
|
||||
trk = S[0x540688][:NBINS_FIR].astype(np.float64)
|
||||
return trk * fir_kernel(scr, q)
|
||||
|
||||
|
||||
def validate_mask_stage(ds, q=Q_EXP, cap=60):
|
||||
"""Валидация масочной ветви на чистых γ-кадрах (24mm9-протокол).
|
||||
|
||||
Отбор: |γ_fit−1.760561|<5e-4 и fit-rms<1e-5 (жёстче pick_clean_frame).
|
||||
Критерий: rms по ВСЕМ 2049 бинам < 0.05 дБ (структурная фаза).
|
||||
"""
|
||||
import glob
|
||||
rmss, gpred = [], []
|
||||
for f in sorted(glob.glob(os.path.join(ds, 'ph*.npz'))):
|
||||
try:
|
||||
d = np.load(f)
|
||||
except Exception:
|
||||
continue
|
||||
if '0x540628' not in d:
|
||||
continue
|
||||
scr = d['0x540628'][:NBINS_FIR].astype(np.float64)
|
||||
trk = d['0x540688'][:NBINS_FIR].astype(np.float64)
|
||||
cur = d['0x540678'][:NBINS_FIR].astype(np.float64)
|
||||
ok = (trk > 1e-30) & (cur > 1e-30) & np.isfinite(scr)
|
||||
if ok.sum() < 50:
|
||||
continue
|
||||
lt, lc = np.log(trk[ok]), np.log(cur[ok])
|
||||
sel = np.abs(lt) > 0.05
|
||||
if sel.sum() < 8:
|
||||
continue
|
||||
g = float(np.sum(lt[sel] * lc[sel]) / np.sum(lt[sel] ** 2))
|
||||
frms = float(np.sqrt(np.mean((lc[sel] - g * lt[sel]) ** 2)))
|
||||
if not (abs(g - GAMMA) < 5e-4 and frms < 1e-5):
|
||||
continue
|
||||
F = fir_kernel(scr, q)
|
||||
lf = np.log(F[sel])
|
||||
lt_s = np.log(trk[sel])
|
||||
sF = float(np.sum(lf * lt_s) / np.sum(lt_s ** 2))
|
||||
gpred.append(1.0 + sF)
|
||||
m = trk * F
|
||||
mm = (cur > 1e-12) & (m > 1e-12)
|
||||
e = (np.log(m[mm]) - np.log(cur[mm])) * 20 / np.log(10)
|
||||
rmss.append(float(np.sqrt(np.mean(e ** 2))))
|
||||
if len(rmss) >= cap:
|
||||
break
|
||||
if not rmss:
|
||||
print('нет ультрачистых кадров в', ds)
|
||||
return
|
||||
rmss = np.array(rmss)
|
||||
print('кадров=%d | rms медиана=%.4f дБ p90=%.4f max=%.4f | '
|
||||
'gamma_pred(1+s_F)=%.6f' %
|
||||
(len(rmss), np.median(rmss), np.percentile(rmss, 90), rmss.max(),
|
||||
float(np.median(gpred))))
|
||||
|
||||
|
||||
def main():
|
||||
import sys
|
||||
if len(sys.argv) > 1 and sys.argv[1] == '--mask':
|
||||
validate_mask_stage(sys.argv[2] if len(sys.argv) > 2
|
||||
else '/tmp/opencode/sc_multi4b')
|
||||
return
|
||||
ds = sys.argv[1] if len(sys.argv) > 1 else '/tmp/opencode/sc_multi6'
|
||||
tract = sys.argv[2] if len(sys.argv) > 2 else '/tmp/opencode/tract_multi6.txt'
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ import numpy as np
|
||||
|
||||
SLOTS = [0x540668, 0x540548, 0x540550, 0x540598, 0x540628, 0x5406f8,
|
||||
0x540678, 0x540688, 0x5406c8, 0x5406e8, 0x540768,
|
||||
0x540788, 0x5407f8]
|
||||
0x540788, 0x5407f8,
|
||||
# 24mm9: ACC-таблица указателей (шаг 10 combine) и WINfreq
|
||||
# (окно FIR-цепи; падающий Hann — контроль формы)
|
||||
0x5407c8, 0x540658]
|
||||
NARR = 8194
|
||||
SCAL_OFF = 0x540860
|
||||
SCAL_N = 24 # floats -> 0x540860..0x5408c0
|
||||
|
||||
Reference in New Issue
Block a user