Files
SonicForgeStudio/TEST_NOTES.md
T
locpham c3368d0a91 feat: native host bridge integration — C++ bridge, Rust SHM, JS routing, build scripts, docs
- native_bridge/: InstrumentEngineManager multi-channel, sample-accurate, CC/program/pitchbend, transport, Vst3Instrument stub (HAVE_VST3SDK)
- src-tauri: shm.rs, bridge spawn + audio pump + health monitor, open_vst_gui, externalBin, commands
- app: UnifiedMidiRouter, NativeBridgeService, bridgeAudioNode, audioRoutingEngine, Plugin Manager UI, Bridge/WASM indicator, set_position sync
- build: 3 ps1 (force-added, build/ ignored), verify_bundle --check-bridge, CI workflow
- docs: TASKS.md, TEST_NOTES.md (Windows verify checklist), install/report updates
2026-08-11 23:37:29 +07:00

7.4 KiB

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/)

  • A5+A13: TRANSPORT type=3 (STOP flush / PLAY / SET_POSITION) + log mỗi load — code OK, chưa chạy thật
  • A10: InstrumentEngineManager multi-channel (std::map channel→instrument) — code OK, chưa compile Windows
  • A11: sample-accurate segment render theo sampleOffset — code OK; JS hiện gửi sampleOffset=0 (best-effort)
  • 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
  • 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
  • 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)
  • 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

  • C1-C7: node --check OK + bundle build OK (Linux)
  • C5: ring buffer 8 block chống underrun thật trên Windows (âm nghe được, VU nhảy)

D. app.jsx wiring

  • D1: onmidimessage NOTE_ON/OFF → router (code + bundle OK)
  • D2: timeline → scheduleMidiNoteDispatch + transport play/stop (code + bundle OK)
  • 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
  • D1-D2 thật: bấm keyboard + play piano roll → âm qua bridge, Stop hết âm ngân
  • D4: Carla không route khi bridge active (code, cần verify thật)
  • D5: audio routing vào track FX chain
  • D6: panic/Stop → SonicMidiRouter.panic() (bridge transport panic + fallback SonicSF.stopAll) — 4 call site app.jsx đã đổi
  • D8: track→channel map + gửi CC0/CC32/PROGRAM trước NOTE_ON khi đổi instrument (scheduleMidiNoteDispatch)
  • 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); code + bundle OK — chưa test thật trên Windows
  • D10: header indicator Bridge/WASM + nút "Ép WASM" (toggle SonicMidiRouter.setForceWasm); service thêm onStatusChange(cb) — code + bundle OK

E. Backend Python

  • E1-E3: syntax OK (ast.parse)
  • 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.
  • 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

  • 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)
  • 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
  • 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
  • F6: DESKTOP_INSTALL_PLAN.md §5.2 (kiến trúc 2 sidecar) + DEPLOYMENT_REPORT.md bản 1.2
  • 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.