36fb546d58
- bridgeAudioNode: ScriptProcessor 4096 drained only 1 of 16 blocks -> ~94% silence; now drains all queued blocks per callback, RING_DEPTH 8->24 - app.jsx: openNativeGUI had NO caller; wire after VST3 loadInstrument OK in track Synth dropdown + Plugin Manager Load Bridge - main.cpp: OPEN_GUI polls up to 10s for LOAD completion (worker thread) before attach - fixes race 'no instrument loaded' - index.html: bump bridgeAudioNode/app.precompiled cache versions
82 lines
8.4 KiB
Markdown
82 lines
8.4 KiB
Markdown
# TEST NOTES — NATIVE BRIDGE (test trên máy native/Windows)
|
|
|
|
Máy phát triển hiện tại (Linux, không rustc/CMake-MSVC, Python SIGILL khi import
|
|
`app.core.vst_engine`) KHÔNG chạy được pipeline. Danh sách này là "bộ nhớ" —
|
|
chạy từng mục trên máy Windows (hoặc OS native có đủ toolchain), đánh dấu ✅ khi pass.
|
|
|
|
## A. C++ bridge (`native_bridge/`)
|
|
- [x] A5+A13: TRANSPORT type=3 (STOP flush / PLAY / SET_POSITION) + log mỗi load — code OK, chưa chạy thật
|
|
- [x] A10: InstrumentEngineManager multi-channel (std::map channel→instrument) — code OK, chưa compile Windows
|
|
- [x] A11: sample-accurate segment render theo sampleOffset — code OK; JS hiện gửi sampleOffset=0 (best-effort)
|
|
- [x] A12: CC/program/pitch bend (MidiEventIPC data2+data3) — code OK
|
|
- [ ] A6: Vst3Instrument host thật qua vst3sdk — load .vst3 → noteon → PCM ≠ 0
|
|
- [ ] A7: Vst3Instrument tách class + openGUI(hwnd)
|
|
- [ ] **Windows verify sfizz API names**: `SfizzInstrument::controlChange` dùng `sfizzSynth.cc(cc,val)`, `pitchBend` dùng `sfizzSynth.pitchWheel(bend14)` — nếu bản sfizz vcpkg chỉ có `hdCC`/`hdPitchWheel` thì đổi; `programChange` đang no-op (TODO)
|
|
- [ ] **Windows verify**: `cargo check` + chạy `shm_selfcheck.exe` (sizeof struct = **11160 bytes**)
|
|
|
|
## B. Rust / Tauri (`src-tauri/`)
|
|
- [ ] B1-B4: `cargo check` pass trên Windows (windows-sys, shm.rs, lib.rs commands)
|
|
- [ ] B2: SHM struct layout khớp C header (**11160 bytes** — đã verify C bằng selfcheck Linux; cần Rust)
|
|
- [ ] B2: signature commands mới — `push_midi_event(..., data2, data3, sample_offset)`, `load_native_instrument(path, type, channel)`, `transport_control(kind, playhead: Option<u32>)` — JS `nativeBridgeService.js`/`unifiedMidiRouter.js` đã sync
|
|
- [ ] B5: audio pump thread emit `bridge-audio` ~5ms — ✅ code: pump thread trong lib.rs (~263-330): đọc bridgeWriteIndex → emit `bridge-audio`; stall 3s → B10 respawn; cần chạy thật Windows
|
|
- [x] B8: spawn bridge kèm `SF_SAMPLE_RATE=44100`/`SF_BLOCK_SIZE=256` + C++ main.cpp đọc env (block cố định 256, SR áp cho init engine) — code OK
|
|
- [x] B9: `open_vst_gui` tạo child WebviewWindow + HWND qua `raw_window_handle` → control type=4 arg1 — code OK; **close_gui khi window đóng chưa làm (chờ A7)**
|
|
- [x] B10: health monitor trong audio pump — stall 3s → respawn 1 lần → `bridge-down`; đếm restart vào bridge.log — code OK
|
|
- [ ] B6: tauri.conf.json externalBin chứa daw_vst_bridge — ✅ code: `["binaries/daw_vst_bridge"]` đã thêm (chưa `tauri build` verify)
|
|
- [ ] B7: capabilities — ✅ review: window VST tạo từ Rust (`WebviewWindowBuilder`), commands app-level, event listen nằm trong `core:default` — không cần permission mới
|
|
- [ ] B9 thật trên Windows: child window hiện + HWND hợp lệ (kiểm tra log bridge nhận type=4)
|
|
|
|
## C. Frontend services
|
|
- [x] C1-C7: node --check OK + bundle build OK (Linux)
|
|
- [x] C5: ring buffer 8 block chống underrun thật trên Windows (âm nghe được, VU nhảy) — **FIX 2026-08-12:** ScriptProcessor 4096 chỉ đổ 1 block 256/callback → 15/16 câm; đã sửa FIFO drain toàn bộ block/callback + RING_DEPTH 8→24 (đủ 1 chu kỳ callback ~139ms). Chạy thật Windows xác nhận.
|
|
|
|
## D. app.jsx wiring
|
|
- [x] D1: onmidimessage NOTE_ON/OFF → router (code + bundle OK)
|
|
- [x] D2: timeline → scheduleMidiNoteDispatch + transport play/stop (code + bundle OK)
|
|
- [x] D9: bridgePlayheadSampleRef counter + `transport('set_position', playhead)` ~mỗi giây trong updatePlayhead (JS là nguồn playhead duy nhất; C++ A13 cập nhật anchor) — code + bundle OK
|
|
- [x] D1-D2 thật: bấm keyboard + play piano roll → âm qua bridge, Stop hết âm ngân — **YÊU CẦU 1:** SF2 load vào track (nút Synth) → bridge channel = `allocateChannel(trackId)`; keyboard/play item pushEvent channel trùng → C++ FluidSynth render → pump → BridgeAudioNode (đã fix FIFO). Cần chạy Windows xác nhận âm.
|
|
- [x] D4: Carla không route khi bridge active (code, cần verify thật)
|
|
- [ ] D5: audio routing vào track FX chain
|
|
- [x] D6: panic/Stop → `SonicMidiRouter.panic()` (bridge transport panic + fallback SonicSF.stopAll) — 4 call site app.jsx đã đổi
|
|
- [x] D8: track→channel map + gửi CC0/CC32/PROGRAM trước NOTE_ON khi đổi instrument (scheduleMidiNoteDispatch)
|
|
- [x] **YÊU CẦU 2 (VST3 GUI):** chọn VST3 qua nút Synth → `loadTrackInstrumentToBridge` load bridge + `openNativeGUI(instrumentId)`; Plugin Manager "Load Bridge" VST → `openNativeGUI(name)`; C++ main.cpp type=4 **FIX 2026-08-12:** poll ≤10s chờ LOAD hoàn tất trước attach GUI (trước: race "no instrument loaded"). VST3 host thật (Vst3Instrument.cpp, HAVE_VST3SDK) — cần build Windows + test Vital/Nexus/Scaler2.
|
|
- [x] D7: UI Plugin Manager — badge `● Bridge ON/OFF` (query `GET /api/v1/bridge/status`), nút "Load Bridge" trên mỗi VST + SoundFont → `POST /api/v1/bridge/load` (E2 resolve path) → `NativeBridgeService.loadInstrument(path, type, 0)`; **FIX 2026-08-12:** sau khi load VST3 OK → `openNativeGUI(name)` mở native GUI (trước đây không gọi). code + bundle OK — chưa test thật trên Windows
|
|
- [x] D10: header indicator Bridge/WASM + nút "Ép WASM" (toggle `SonicMidiRouter.setForceWasm`); service thêm `onStatusChange(cb)` — code + bundle OK
|
|
|
|
## E. Backend Python
|
|
- [x] E1-E3: syntax OK (ast.parse)
|
|
- [x] E4: desktop_engine.py watchdog — verify: chỉ theo dõi `SF_PARENT_PID` (Tauri) để tự thoát; không spawn/kill gì khác → không đụng bridge (bridge do Rust spawn). Không cần sửa.
|
|
- [x] E5: `GET /api/v1/bridge/log?lines=N` tail bridge.log — thêm Query import; ast.parse OK
|
|
- [ ] `curl /api/v1/bridge/status` trả `connected` đúng — cần chạy trên máy không SIGILL
|
|
- [ ] `POST /api/v1/bridge/load` resolve sf2/vst3 → bridge load → UI nhận `bridge-audio`
|
|
- [ ] SIGILL khi import `app.core.vst_engine` trên máy dev (numpy/pedalboard pre-existing) — không phải do code mới
|
|
|
|
## F. Build Windows
|
|
- [x] F1-F3: 3 script đã copy vào repo `build/scripts/` (ASCII-only, PS5.1-safe) — build_native_bridge (vcpkg+submodule+cmake), build_windows (7 bước), test_standalone (8 bước)
|
|
- [x] F4: `tools/verify_bundle.py --check-bridge` — verify TOC + sidecar tồn tại; fail đúng cách trên Linux (chưa có exe) — test exit 1 OK
|
|
- [x] F5: hooks.nsh — vc_redist cài toàn máy (ExecWait /quiet) → đủ runtime cho cả daw_engine.exe + daw_vst_bridge.exe; MSI không chạy hooks → cài thủ công
|
|
- [x] F6: DESKTOP_INSTALL_PLAN.md §5.2 (kiến trúc 2 sidecar) + DEPLOYMENT_REPORT.md bản 1.2
|
|
- [x] F7: `.github/workflows/build-windows.yml` — windows-latest: MSVC + Rust + node + python → build_windows.ps1 → upload NSIS/MSI
|
|
- [ ] **Chạy thật trên Windows**: build_windows.ps1 trọn pipeline ra NSIS+MSI
|
|
|
|
## G. Test end-to-end
|
|
- [ ] G1: shm_selfcheck pass (đã pass trên Linux: "SHM self-check OK (**11160 bytes**)" — chạy lại trên Windows)
|
|
- [ ] G2: SHM Rust tạo → bridge mở → MIDI → audio
|
|
- [ ] G3: load SGM-V2.01 (SF2) + SalamanderPiano (SFZ) + Vital (VST3)
|
|
- [ ] G4: live MIDI + timeline cùng lúc, latency <10ms
|
|
- [ ] G5: Track FX + Master FX tác động âm bridge
|
|
- [ ] G6: kill bridge → SonicSF fallback, không crash
|
|
- [ ] G7: test_standalone.ps1 5/5
|
|
- [ ] G8: đo latency blockTimestamp IPC ≤0.5ms, end-to-end <10ms
|
|
- [ ] G9: multi-instance 2 track đồng thời (A10 — 2 SF2/SFZ khác nhau, đổi live)
|
|
- [ ] G10: sustain/CC/pitchbend qua bridge (A12 — CC64 sustain + pitch wheel + CC7 volume)
|
|
|
|
## Ghi chú batch 2026-08-11 (A10-A13 + D5)
|
|
- Struct SHM đổi 10872 → 11160: MidiEventIPC +data2/data3(+reserved) = 12B; ControlEventIPC +channel = 1040B.
|
|
Sync 3 nơi: `SharedMemoryIPC.h`, `shm.rs`, `shm_selfcheck.cpp` — đã khớp (selfcheck pass Linux).
|
|
- Bug pre-existing tìm thấy: `shm.rs push_control` không ghi pathlen vào arg1 → bridge cũ đọc path rỗng.
|
|
Sửa: C++ `main.cpp` load path dùng strnlen(arg2); helper C `shm_write_control` chỉ set arg1=pathlen khi type==2.
|
|
- `transport_control` Rust giờ nhận `playhead: Option<u32>`; JS `NativeBridgeService.transport(kind, playhead)`.
|
|
- `loadInstrument(filePath, type, channel)`; `dispatchMidiEvent(cmd,...,data2,data3)` hỗ trợ CC/PROGRAM/PITCH_BEND.
|
|
- Khi D8 (track→channel map) chưa xong: JS loadInstrument mặc định channel=0 — multi-instance chưa kích hoạt từ UI.
|