Files
SonicForgeStudio/PLAN_SHM_REALTIME.md
T

110 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PLAN: VST FX SHM realtime
Mục tiêu: VST3 FX (master FX chain + track chain) xử lý THẬT realtime qua
fx_vst_bridge — không còn pass-through khi nghe live.
Kiến trúc (cloud-FX loop, latency ~2 block):
WebAudio (masterBus.output)
→ AudioWorklet (sf-fx-realtime.js) — input block
→ WebSocket (engine /ws/fx-realtime/{id})
→ Python SHM input ring (SonicForge_FXRT_*)
→ fx_vst_bridge.exe --realtime-fx (RealtimeFxChain::process, SEH-guarded)
→ SHM output ring
→ Python → WebSocket → AudioWorklet output → graph
SHM layout FxRealtimeIPC (C++ struct = Python ctypes mirror, all u32/float 4B):
header u32: magic(0x46585254) state sampleRate blockSize running heartbeat
inWrite inRead inSlots outWrite outRead outSlots (48 bytes)
inL[4][256] inR[4][256] outL[8][256] outR[8][256]
Files:
1. native_bridge/include/FxRealtimeIPC.h — struct + constants (mới)
2. native_bridge/src/RealtimeFxLoop.cpp — loop (mới)
3. native_bridge/src/main_fx.cpp — thêm --realtime-fx
4. native_bridge/CMakeLists.txt — thêm 2 file vào fx_vst_bridge
5. app/core/fx_realtime.py — session SHM + spawn (mới)
6. app/api/v1/plugins.py — /fx-realtime/start, /stop, WS
7. app/static/js/sf-fx-realtime.js — AudioWorklet (mới)
8. app/static/js/app.jsx — fxRealtimeManager wiring
9. engine.spec — hiddenimport websockets
v1 scope: MASTER chain realtime (chỗ VST3 bị skip trong rebuildMasteringGraph).
Track chain realtime: ponytail — per-track session sau (export offline đã có).
## Trạng thái: ✅ v1 DONE (2026-08-20)
- Bridge build OK (native_bridge/build/Release/fx_vst_bridge.exe) + deploy sidecar
(src-tauri/binaries/fx_vst_bridge-x86_64-pc-windows-msvc.exe +
src-tauri/target/release/fx_vst_bridge.exe).
- Engine build OK (websockets bundled) + deploy target/release + resources.
- Frontend build OK (app.precompiled.js + sf-fx-realtime.js static serve).
- E2E đã test trên engine deploy (port 8000):
- POST /fx-realtime/start (purecomp.vst3, 44100) → session_id + ws_url ✓
- WS binary loop: chain rỗng = passthrough bit-exact (peak 0.5/rms 0.35) ✓
- WS + purecomp: peak 0.5→0.462, rms 0.35→0.246 (compressor attenuate) ✓
- WS disconnect → session tự stop, fx_vst_bridge.exe thoát ✓
- POST /fx-realtime/stop → stopped:true ✓
- WS token sai → reject (handshake 403) ✓
- FIX phát hiện khi test: WS drain output chỉ trong vòng receive_bytes → output
thừa kẹt SHM ring khi client ngừng gửi → tách _pump_output() task riêng.
## Trạng thái: ✅ TRACK REALTIME DONE (2026-08-20)
- Track chain realtime: mọi luồng âm thanh track qua bridge
(fx_vst_bridge --realtime-fx + SHM SonicForge_FXRT_*) trước main out.
- Module-level `fxRtTracks` map 'trackId:audio|sf' + fxRtTrackChain/Paths/
Start/Splice/Stop/Reconcile/StopAll trong app.jsx; gọi từ rebuildTrackFxGraph,
startTrackPlayback, stopAllPlayback, FX Rack panel.
- `fxRtTrackPaths`: audio nếu clips.length>0 || buffer || sections.length>0;
sf nếu midiItems.length>0 || type==='MIDI' || instrumentId.
- E2E ổn định (pw_e2e2.py ×3): splice 3 audio + 3 sf, track audio out
peak≈0.47 rms≈0.33, sf câm hợp lệ (MIDI taiko không route sfEntry), master
Ozone peak≈0.85-0.99. Master câm khi track mastering_bypass=true — hợp lệ.
- FIX bug bypass toggle: reconcile đọc state CŨ (React setState async) khi
`onChange` gọi `__rebuildTrackFxGraph(track.id)` đồng bộ → bypass không stop
session. Fix: `rebuildTrackFxGraph = (trackId, patch)` merge
`track = { ...track, ...patch }` TRƯỚC khi rebuild/reconcile; 4 call site
(bypass, fxActive, setVstChain, setChain) truyền patch giá trị MỚI.
Verify: toggle bypass-on → reconcile want=[] → stop ngay; bypass-off →
want=["sf"] → start mới + spliced.
- Debug log tạm đã gỡ (giữ `[FX RT track] spliced` + console.warn lỗi);
rebuild bundle 1370231 bytes, served LEN khớp local.
Ponytail còn lại:
- Sub-tab (piano roll) play chưa start fxRt — chỉ main/section play.
- Chain đổi giữa lúc play chưa restart session (start/stop theo play boundary).
- Browser-side queue drop-oldest (8 block) — thay adaptive stretch nếu cần.
- Chưa test UI thật trong WebView (graph insertion AudioWorkletNode) — plumbing
đã verify qua WS; mở app + bật master VST chain + play để xác nhận âm thanh.
## Trạng thái: ✅ MASTER REALTIME UI VERIFIED (2026-08-20, engine sống)
- Verify UI-level: login → inject `window.currentMasteringSettings.vstFxChain`
(path đúng `C:\Program Files\Common Files\VST3\Sonible\purecomp.vst3`) →
insert clip → Play. Monkey-patch `SonicAPI.fxRealtimeStart` ghi payload→sid.
Kết quả (pw_master3.py): call #1 = master (purecomp, engine trả session_id +
ws_url) → WS `SonicForge_FXRT_d19c01fc33da` nhận audio 738 frame, out
peak 0.4622 / rms 0.1442 vs input sine 0.5/0.35 = attenuate ✓.
Track sessions (call #2/#3) chạy song song; stop → WS close, `--realtime-fx`
bridge thoát, chỉ còn 2 `--fx-gui` của user (không đụng). Engine @8000 OK.
- WS-level (rt_test2.py) trước đó: master realtime attenuate peak 0.4621 rms
0.2462 với path đúng `Sonible\purecomp.vst3` (path sai `SoniBook` = passthrough
thầm lặng).
- Nguyên nhân "VST FX PLUGIN trong master chain peak -inf" (trả lời user):
1) Engine bị kill lúc test → `SonicAPI.fxRealtimeStart` fail → `fxRtStart`
catch + toast cảnh báo, KHÔNG session → masterBus.output nối thẳng
analyser → âm nghe được nhưng KHÔNG qua VST → meter plugin -inf.
2) Chain rỗng / vstBypass=true → `fxRtChain()` = [] → không session (âm qua
thẳng, không lỗi) → meter -inf.
3) Meter trong GUI embed (`--fx-gui`) là của instance GUI RIÊNG (config JSON
chỉ path+name; VstGuiEmbed chỉ /frame /ping /input — KHÔNG có audio
endpoint) → GUI embed KHÔNG nhận audio realtime SHM session → meter -inf
VÔ ĐIỀU KIỆN kể cả khi realtime đang chạy. Audio thật đi qua instance
`--realtime-fx` riêng (không hiển thị meter). → ponytail thật: user không
thấy meter plugin thật; nơi thấy tín hiệu = master VU meter của app
(post-chain) hoặc WS session.
- Lưu ý: `masterFxList` (Plugin Picker mastering) load trong useEffect([]) của
MasteringModal mount sẵn từ đầu → trước khi SonicAPI sẵn sàng → picker rỗng
trong headless; track modal mount trễ hơn nên đầy. Workaround: chờ SonicAPI
rồi mới mở modal, hoặc inject chain trực tiếp. (Không phải lỗi engine.)