diff --git a/handoff/NOTES_LEVEL.md b/handoff/NOTES_LEVEL.md index bf9f609..934ff81 100644 --- a/handoff/NOTES_LEVEL.md +++ b/handoff/NOTES_LEVEL.md @@ -3774,3 +3774,32 @@ bigkernel'ов из рантайм-адресов (24jj). формулы применения с калибровкой rms 0.016; все инструменты/датасеты сохранены. Полное кросс-конфиг замыкание = транскрипция каскада по dataflow (связная задача следующей сессии, блокеров нет). + +## ============ ФИНАЛ СЕССИИ 24ll/24mm/24nn: пер-пиковые законы; кросс-ран сравнения ненадёжны ============ + +### Двухтоновая серия (tt, один прогон — оба пика согласованно): +``` +PK1 (центр полосы): cut = 3.282·ln1p(lvl/0.5593)+0.768 rms 0.0037 +PK2 (тон@2000): cut = 3.355·ln1p(lvl/0.0570)+1.091 rms 0.0006 (!!) +``` +Общий α≈3.3; β₂ в 10 раз меньше β₁ (второй пик чувствительнее); +m-тест: pk2-закон = pk1-закон(уровень×11.6±0.1) — константный масштаб. + +### Кросс-РАН сравнения абсолютных катов НЕНАДЁЖНЫ +Глубокое/мелкое состояние буфера выбирается по-разному между запусками +(d1500 дал 6.62 @pk2, tt-семейство 11.46 при том же контенте!) ⇒ +валидны только ВНУТРИ-прогонные серии (один запуск = одно состояние). +Это объясняет все прошлые «немонотонности» и противоречия между сериями. + +### Параметризация сведена к: +``` +α ≈ 3.3 (общий наклон) +β_peak, c_peak — зависят от ПОЗИЦИИ пика относительно полосы + (шаблонная геометрия; источник — декомп шагов 9–19/LUT) +Δ-правило — из pre-combine +``` + +### ИНСТРУМЕНТЫ КАМПАНИИ ГОТОВЫ +campaign.py (ячейка семейства); tt_series.py (рецепт двухтоновой серии); +все датасеты sc_*/tract_*/*pkl сохранены. Следующая сессия: декод шагов +9–19 до конца (dataflow готов) + захват A/B/γ объектов банд → замыкание. diff --git a/scripts/tt_series.py b/scripts/tt_series.py new file mode 100644 index 0000000..152ba4e --- /dev/null +++ b/scripts/tt_series.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""two-tone drive series at fc500/q0.5/s12: renders+captures+fit.""" +import subprocess, os, sys, time, glob +import numpy as np, wave + +def sh(cmd): return subprocess.run(cmd,shell=True,capture_output=True,text=True).stdout +def find_host(): + import glob as g + for p in g.glob('/proc/[0-9]*'): + pid=int(os.path.basename(p)) + try: + cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace') + maps=open('/proc/%d/maps'%pid).read() + except Exception: continue + if 'soothe2' in maps and 'reaper' not in cmd: return pid + return None + +# inputs: dual content (500+2000 equal) at drives 0/-6/-12/-18 with probes +sr=44100; T=4.0; n=int(sr*T); t=np.arange(n)/sr +ph=np.random.default_rng(41).uniform(0,2*np.pi,7) +drives=(0,6,12,18) +for att in drives: + A=0.4248*10**(-att/20) + y=A*np.sin(2*np.pi*500*t+ph[0])+A*np.sin(2*np.pi*2000*t+ph[1]) + for i,f in enumerate((300.,700.,1400.,2800.,5000.)): + y+=A*10**(-30/20)*np.sin(2*np.pi*f*t+ph[i+2]) + y=np.clip(y,-0.999,0.999) + nm='tt%d'%att + w=wave.open('/tmp/opencode/%s_in.wav'%nm,'wb'); w.setnchannels(1); w.setsampwidth(2); w.setframerate(sr) + w.writeframes((y*32767).astype(np.int16).tobytes()); w.close() + src=open('/tmp/opencode/multi.rpp').read() + import re + src=re.sub(r'RENDER_FILE "[^"]*"','RENDER_FILE "/tmp/opencode/%s_ref.wav"'%nm,src) + src=src.replace('FILE "/tmp/opencode/multi_in.wav"','FILE "/tmp/opencode/%s_in.wav"'%nm) + open('/tmp/opencode/%s.rpp'%nm,'w').write(src) +print('inputs+rpps ready') + +sh("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1") +for att in drives: + wav='/tmp/opencode/tt%d_ref.wav'%att + if os.path.exists(wav): os.remove(wav) + pr=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/tt%d.rpp'%att], + 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) + for _ in range(240): + if pr.poll() is not None: break + time.sleep(0.1) + print('tt%d ref rc=%s'%(att,pr.poll()),flush=True) + +# captures + tracts +for att in drives: + od='/tmp/opencode/sc_tt%d'%att + sh('rm -rf %s'%od) + sh('cd /home/m/re-tools && timeout 60 python3 scripts/rendersnap2.py /tmp/opencode/tt%d.rpp 400 %s'%(att,od)) + tf='/tmp/opencode/tract_tt%d.txt'%att + 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','/tmp/opencode/tt%d_in.wav'%att, + '/tmp/o48_tt.wav','500,0.5,12'],capture_output=True,env=env) +print('captures+tracts done')