24hh2: gate set to BIT EXACT (user decision); g_s12 datapoint captured (fc1000 q1 s12: audio=scratch+(-0.11dB) confirms direct-mask at fc1000 too); parameterization campaign table drafted
This commit is contained in:
@@ -3638,3 +3638,33 @@ bigkernel'ов = ИМПОРТИРОВАННЫЕ функции (UCRT/хост-DL
|
|||||||
Как только имена получены (ожидаемо expf/powf/log10f класс), семантика
|
Как только имена получены (ожидаемо expf/powf/log10f класс), семантика
|
||||||
bigkernel'ов замыкается, и полный каскадный симулятор шагов 9–19+FIR
|
bigkernel'ов замыкается, и полный каскадный симулятор шагов 9–19+FIR
|
||||||
становится реализуемым без дальнейшей археологии.
|
становится реализуемым без дальнейшей археологии.
|
||||||
|
|
||||||
|
## ============ ДОПОЛНЕНИЕ 24hh2: гейт смены канона = BIT EXACT; точка g_s12; кампания параметризации ============
|
||||||
|
|
||||||
|
### Решение по гейту (пользователь)
|
||||||
|
Цель = BIT EXACT (не «лучше канона»): все параметры прослежены до декомпа,
|
||||||
|
корпус сходится в шумовой пол. Дефолт переключается только после этого.
|
||||||
|
|
||||||
|
### Новая точка фронтенда: fc1000 q1 SENS12 (g_s12)
|
||||||
|
```
|
||||||
|
наш lvl@85=20.139 res@85=0.11718
|
||||||
|
deepest scratch: cut_D=7.64 dB
|
||||||
|
REF goertzel: 7.53 dB ⇒ audio=scratch+const ✓ (−0.11)
|
||||||
|
```
|
||||||
|
Инверсия через dual-константы НЕКОРРЕКТНА (чужое семейство) — для анализа
|
||||||
|
кламп-гипотезы нужен фит закона внутри fc1000/q1 (серия драйвов по q1).
|
||||||
|
|
||||||
|
### Кампания параметризации (план):
|
||||||
|
Семейство = (контент, fc, q, sens); для каждого нужна серия драйвов:
|
||||||
|
```
|
||||||
|
✓ dual fc500 q0.5 s12 два-тона : α=3.2193 β=0.4927 c=0.54
|
||||||
|
✓ fc1000 q0.5 s12 один тон : α=1.6151 β=0.3645 c=0.48
|
||||||
|
✓ fc500 q0.5 s12 один тон : α=1.1530 β=0.4038 c=0.33
|
||||||
|
□ fc1000 q1 s12 + драйв-серия : ← следующий
|
||||||
|
□ q-серия на одном контенте : q∈{0.1..10} × фикс драйв
|
||||||
|
□ sens-серия аналогично
|
||||||
|
□ multi-band (comb) : правило суммирования нотчей
|
||||||
|
```
|
||||||
|
Каждая ячейка ≈10 мин (patchparam+рендер+rendersnap2+тракт).
|
||||||
|
После сетки: зависимость (α,β,c)(q,sens,fc,контент) → формулы или таблицы
|
||||||
|
с декомп-обоснованием из шагов 9–19.
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""g_s12 pipeline: clean render ref + deepest scratch capture + render48k tract.
|
||||||
|
Then compute implied-res vs our-res for the frontend clamp analysis."""
|
||||||
|
import subprocess, os, sys, time, glob
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def find_host():
|
||||||
|
import glob as g
|
||||||
|
for p in g.glob('/proc/[0-9]*'):
|
||||||
|
pid=int(os.path.basename(p))
|
||||||
|
try:
|
||||||
|
cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||||
|
maps=open(f'/proc/{pid}/maps').read()
|
||||||
|
except Exception: continue
|
||||||
|
if 'soothe2' in maps and 'reaper' not in cmd: return pid
|
||||||
|
return None
|
||||||
|
|
||||||
|
def sh(cmd):
|
||||||
|
return subprocess.run(cmd,shell=True,capture_output=True,text=True).stdout
|
||||||
|
|
||||||
|
sh("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
|
||||||
|
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1")
|
||||||
|
|
||||||
|
# 1. clean ref render
|
||||||
|
wav='/tmp/opencode/g_s12_ref.wav'
|
||||||
|
if os.path.exists(wav): os.remove(wav)
|
||||||
|
pr=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/g_s12.rpp'],
|
||||||
|
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
||||||
|
t0=time.time(); host=None
|
||||||
|
while time.time()-t0<30 and not host: host=find_host(); time.sleep(0.002)
|
||||||
|
print('host',host)
|
||||||
|
for _ in range(300):
|
||||||
|
if pr.poll() is not None: break
|
||||||
|
time.sleep(0.1)
|
||||||
|
for _ in range(50):
|
||||||
|
if pr.poll() is not None: break
|
||||||
|
time.sleep(0.1)
|
||||||
|
print('ref done rc=',pr.poll())
|
||||||
|
|
||||||
|
# 2. deepest scratch capture
|
||||||
|
sh("pkill -9 -x reaper; sleep 1; rm -rf /tmp/opencode/sc_g_s12")
|
||||||
|
r=sh('cd /home/m/re-tools && timeout 60 python3 scripts/rendersnap2.py /tmp/opencode/g_s12.rpp 400 /tmp/opencode/sc_g_s12')
|
||||||
|
print('capture tail:',r.strip().splitlines()[-1] if r.strip() else 'empty')
|
||||||
|
|
||||||
|
# 3. render48k tract (same input tone1k, band fc1000 q1 s12)
|
||||||
|
tf='/tmp/opencode/tract_g_s12.txt'
|
||||||
|
if os.path.exists(tf): os.remove(tf)
|
||||||
|
env=dict(os.environ); env['RT_DUMP_BIN']=tf
|
||||||
|
subprocess.run(['/home/m/re-tools/dsp/build/render48k','/home/m/soothe-bt/tone1k.wav',
|
||||||
|
'/tmp/o48_g.wav','1000,1.0,12'],capture_output=True,env=e if False else env)
|
||||||
|
print('tract done')
|
||||||
|
|
||||||
|
# 4. analysis
|
||||||
|
import wave
|
||||||
|
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):
|
||||||
|
x=x[-int(0.75*sr):]; t=np.arange(len(x))/sr; w=2*np.pi*f
|
||||||
|
return np.hypot(2*np.sum(x*np.cos(w*t))/len(x), 2*np.sum(x*np.sin(w*t))/len(x))
|
||||||
|
def db(a): return 20*np.log10(max(a,1e-12))
|
||||||
|
|
||||||
|
inp=loadwav('/home/m/soothe-bt/tone1k.wav')
|
||||||
|
ref=loadwav(wav)
|
||||||
|
rcut=-db(ta(ref,1000)/ta(inp,1000))
|
||||||
|
|
||||||
|
best=None
|
||||||
|
for fn in sorted(glob.glob('/tmp/opencode/sc_g_s12/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[85]<best[0]: best=(s[85],s)
|
||||||
|
cutD=-best[0]*8.685889638 if best else float('nan')
|
||||||
|
|
||||||
|
lv=res85=None
|
||||||
|
for ln in open(tf):
|
||||||
|
if ln.startswith('#'): continue
|
||||||
|
p=ln.split()
|
||||||
|
if int(p[0])==85: lv=float(p[3]); res85=float(p[2])
|
||||||
|
|
||||||
|
alpha,beta,c=3.2193,0.4927,0.5423 # dual constants
|
||||||
|
li=beta*np.expm1((cutD-c)/alpha)
|
||||||
|
print('\n=== fc1000 q1 SENS12 (недостающая точка) ===')
|
||||||
|
print('our lvl@85=%.3f res@85=%.5f' % (lv,res85))
|
||||||
|
print('scratch cut_D=%.2f dB' % cutD)
|
||||||
|
print('law-inverse impl lvl=%.3f -> implied res=%.5f' % (li, 0.7307*3.2309/max(li,1e-9)))
|
||||||
|
print('REF goertzel cut@1000=%.2f dB' % rcut)
|
||||||
|
print('\ncontext: sens18 impl res=0.15244 (плато); ours@s18=0.0284')
|
||||||
Reference in New Issue
Block a user