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 тракта — это и есть критерий 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