24ll3: per-bin am/res paradigm REFUTED for off-center peaks — unified res^p fit hits lower bound (wants NO res dependence), yet cuts grow monotonically with res at equal am; two-argument structure or full cascade required; multi6 dataset is the validation target
This commit is contained in:
@@ -3832,3 +3832,23 @@ multi6 = идеальный валидатор каскадного симуля
|
|||||||
шесть пиков с разными (am,res) комбинациями, самосогласованные B=exp(scratch).
|
шесть пиков с разными (am,res) комбинациями, самосогласованные B=exp(scratch).
|
||||||
После оп-за-оп транскрипции симулятор ОБЯЗАН воспроизвести эти пять глубин
|
После оп-за-оп транскрипции симулятор ОБЯЗАН воспроизвести эти пять глубин
|
||||||
из am/res тракта — это и есть критерий bit-exact детектора.
|
из am/res тракта — это и есть критерий bit-exact детектора.
|
||||||
|
|
||||||
|
## ============ ДОПОЛНЕНИЕ 24ll3: пер-биновая парадигма am/res ОТВЕРГНУТА для внецентровых пиков ============
|
||||||
|
|
||||||
|
### Единый фит cut=α·ln1p((am·s/res^p)/β)+c по 28 точкам (multi6+tt):
|
||||||
|
параметр p упёрся в НИЖНЮЮ границу 0.05 (хотел БЕЗ зависимости от res),
|
||||||
|
rms 2.28 дБ. Разрешение отрицательных p не спасает.
|
||||||
|
⇒ **уровень внецентрового пика НЕ выражается через am/res в любой степени**.
|
||||||
|
Первые четыре тона multi6 имеют ОДИНАКОВЫЙ am≈0.21, но каты 2.33→7.18
|
||||||
|
растут монотонно с res ⇒ детекторный уровень зависит от res ПОЛОЖИТЕЛЬНО,
|
||||||
|
отдельно от am — двухаргументная структура или каскадная связь.
|
||||||
|
|
||||||
|
### Что это значит
|
||||||
|
Наш lvl_raw=am/res·scale как вход закона правилен ТОЛЬКО у центра полосы.
|
||||||
|
Для остальных позиций нужна либо (а) полная каскадная симуляция шагов 9–19,
|
||||||
|
либо (б) эмпирическая поверхность cut(am,res,pos) по датасетам кампании.
|
||||||
|
Оба пути определены; (а) = bit-exact маршрут.
|
||||||
|
|
||||||
|
### Датасет multi6 — главный актив следующего раунда
|
||||||
|
6 нотчей один прогон, самосогласованные B/am/res тройки + полный спектр
|
||||||
|
am(f)/res(f) в tract_multi6.txt — идеальная мишень для валидации симулятора.
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""unify.py — global unified-law fit: cut = alpha*ln1p(am*s/res^p / beta)+c
|
||||||
|
across multi6 (6 peaks) + tt-series (8 points, both peaks)."""
|
||||||
|
import numpy as np, glob, wave
|
||||||
|
from scipy.optimize import least_squares
|
||||||
|
|
||||||
|
def deepest(dirname,b):
|
||||||
|
best=None
|
||||||
|
for fn in sorted(glob.glob(dirname+'/ph*.npz')):
|
||||||
|
d=np.load(fn)
|
||||||
|
if '0x540628' not in d.files: continue
|
||||||
|
s=d['0x540628'].astype(np.float64)
|
||||||
|
if best is None or s[b]<best[0]: best=(s[b],s)
|
||||||
|
return best[1] if best else None
|
||||||
|
|
||||||
|
def loadwav(p):
|
||||||
|
w=wave.open(p,'rb'); n=w.getnframes(); ch=w.getnchannels(); sw=w.getsampwidth()
|
||||||
|
d=w.readframes(n); w.close()
|
||||||
|
if sw==2: return np.frombuffer(d,dtype=np.int16).astype(np.float64).reshape(-1,ch).mean(1)/32768
|
||||||
|
raw=np.frombuffer(d,dtype=np.uint8).reshape(-1,ch,3)
|
||||||
|
s=raw[:,:,0].astype(np.int64)|(raw[:,:,1].astype(np.int64)<<8)|(raw[:,:,2].astype(np.int64)<<16)
|
||||||
|
return np.where(s>=0x800000,s-0x1000000,s).astype(np.float64).reshape(-1,ch).mean(1)/8388608
|
||||||
|
|
||||||
|
def ta(x,f,sr=44100,L=None):
|
||||||
|
x=x[-L:]; t=np.arange(len(x))/sr; c=np.cos(2*np.pi*f*t); sn=np.sin(2*np.pi*f*t)
|
||||||
|
return np.hypot(2*(x*c).sum(),2*(x*sn).sum())/len(x)
|
||||||
|
|
||||||
|
pts=[]
|
||||||
|
# multi6 six peaks
|
||||||
|
S=deepest('/tmp/opencode/sc_multi6',85)
|
||||||
|
cut=np.maximum(-S*8.685889638,0)
|
||||||
|
am=np.zeros(len(S)); rs=np.zeros(len(S))
|
||||||
|
for ln in open('/tmp/opencode/tract_multi6.txt'):
|
||||||
|
if ln.startswith('#'): continue
|
||||||
|
p=ln.split(); kk=int(p[0])
|
||||||
|
if kk<len(S): am[kk]=float(p[1]); rs[kk]=float(p[2])
|
||||||
|
for kk in range(1,len(S)):
|
||||||
|
if cut[kk]>1.0 and am[kk]>0.01:
|
||||||
|
pts.append(('m6',am[kk],rs[kk],cut[kk]))
|
||||||
|
# tt-series 4 drives x 2 peaks (ref-domain cuts via Goertzel)
|
||||||
|
inp0=loadwav('/tmp/opencode/tt0_in.wav')
|
||||||
|
rc={0:(10.34,11.84),6:(8.12,9.57),12:(6.12,7.45),18:(4.40,5.55)}
|
||||||
|
for att,(c1v,c2v) in rc.items():
|
||||||
|
tf='/tmp/opencode/tract_tt%d.txt'%att
|
||||||
|
d43=d171=None; r43=r171=None
|
||||||
|
for ln in open(tf):
|
||||||
|
if ln.startswith('#'): continue
|
||||||
|
p=ln.split(); kk=int(p[0])
|
||||||
|
if kk==43: r43=float(p[2]); d43=am0=None; d43=float(p[1])
|
||||||
|
if kk==171: r171=float(p[2]); d171=float(p[1])
|
||||||
|
pts.append(('tt%d-pk1'%att,d43,r43,c1v))
|
||||||
|
pts.append(('tt%d-pk2'%att,d171,r171,c2v))
|
||||||
|
print('points:',len(pts))
|
||||||
|
|
||||||
|
def resid(p):
|
||||||
|
al,be,cc,pp,ss=p
|
||||||
|
out=[]
|
||||||
|
for nm,a,r,c in pts:
|
||||||
|
X=a*ss/max(r**pp,1e-12)
|
||||||
|
out.append(al*np.log1p(X/be)+cc-c)
|
||||||
|
return np.array(out)
|
||||||
|
|
||||||
|
p0=[3.28,0.56,0.77,1.25,1.0]
|
||||||
|
lb=[0.5,0.01,-5,0.05,0.05]
|
||||||
|
ub=[8,5,5,4,50]
|
||||||
|
r=least_squares(resid,p0,bounds=(lb,ub),max_nfev=8000)
|
||||||
|
mm=-resid(r.x)+np.array([c for _,_,_,c in pts])
|
||||||
|
tgt=np.array([c for _,_,_,c in pts])
|
||||||
|
rms=np.sqrt(((mm-tgt)**2).mean())
|
||||||
|
print('UNIFIED: alpha=%.3f beta=%.4f c=%+.3f p=%.3f s=%.3f ; rms=%.4f max=%.3f' % (
|
||||||
|
*r.x,rms,np.abs(mm-tgt).max()))
|
||||||
|
for (nm,a,rr,c),pv in zip(pts,mm):
|
||||||
|
print(' %-10s am=%.4f res=%.4f cut=%6.2f pred=%6.2f err=%+.2f' % (nm,a,rr,c,pv,c-pv))
|
||||||
Reference in New Issue
Block a user