f8a981b27f
Two guards: schedulePianoRollMidi skips native SF item scheduling while bridge is active; scheduleMidiNoteDispatch lets notes pass to the MIDI router when a piano-roll sub-tab is playing. Verified on Windows: SF2 peak 0.026, VST3 ACDD native GUI + peak 0.074 via Play button. Docs: TEST_NOTES.md, TASKS.md.
10 KiB
10 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::controlChangedùngsfizzSynth.cc(cc,val),pitchBenddùngsfizzSynth.pitchWheel(bend14)— nếu bản sfizz vcpkg chỉ cóhdCC/hdPitchWheelthì đổi;programChangeđang no-op (TODO) - Windows verify:
cargo check+ chạyshm_selfcheck.exe(sizeof struct = 11160 bytes)
B. Rust / Tauri (src-tauri/)
- B1-B4:
cargo checkpass 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>)— JSnativeBridgeService.js/unifiedMidiRouter.jsđã sync - B5: audio pump thread emit
bridge-audio~5ms — ✅ code: pump thread trong lib.rs (~263-330): đọc bridgeWriteIndex → emitbridge-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_guitạo child WebviewWindow + HWND quaraw_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ưatauri buildverify) - B7: capabilities — ✅ review: window VST tạo từ Rust (
WebviewWindowBuilder), commands app-level, event listen nằm trongcore: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) — 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
- 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 — 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. - 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)
- YÊU CẦU 2 (VST3 GUI): chọn VST3 qua nút Synth →
loadTrackInstrumentToBridgeload 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. - D7: UI Plugin Manager — badge
● Bridge ON/OFF(queryGET /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 - D10: header indicator Bridge/WASM + nút "Ép WASM" (toggle
SonicMidiRouter.setForceWasm); service thêmonStatusChange(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=Ntail bridge.log — thêm Query import; ast.parse OK curl /api/v1/bridge/statustrảconnectedđúng — cần chạy trên máy không SIGILLPOST /api/v1/bridge/loadresolve sf2/vst3 → bridge load → UI nhậnbridge-audio- SIGILL khi import
app.core.vst_enginetrê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_controlkhông ghi pathlen vào arg1 → bridge cũ đọc path rỗng. Sửa: C++main.cppload path dùng strnlen(arg2); helper Cshm_write_controlchỉ set arg1=pathlen khi type==2. transport_controlRust giờ nhậnplayhead: Option<u32>; JSNativeBridgeService.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.
Kết quả test THẬT Windows 2026-08-12 (build HEAD 36fb546, app.precompiled.js đã sửa 2 guard)
- ✅ YÊU CẦU 1 (SF2 → âm): Track 01 load
024_BigSymphny(SF2) → insert MIDI item + note C4 → PR play qua nút Play:[Play] PianoRoll schedule: notes=1 | track=1→ peak SHM 0.026468. NOTE_ON dispatch → 0.032. Keybed C4 → 0.0536. - ✅ YÊU CẦU 2 (VST3 native GUI + âm): Track 01 chọn VST3 ACDD (Ample Sound,
C:\Program Files\Common Files\VST3\Ample Sound\ACDD.vst3) →[Bridge] track 1 -> bridge VST3 ch 0 OK→ native GUI mở: classSonicForge_Native_VST3_Class, titleACDD, client 784x561, child JUCE window. Keybed C4 → peak 0.115554; dispatch NOTE_ON ch0 → 0.153984; PR play qua nút Play → 0.073984 ([Play] ... sfEngine=no | dest=ok). - ⚠️ Phím Space (shortcut transport) qua CDP synthetic/trusted event KHÔNG kích play trên app đang chạy (webview đang giữ bundle cũ cache từ lúc start; cần restart app để load bản v=1700 mới). Nút Play trên transport hoạt động chuẩn. Chưa xác định được lỗi thật của Space — không thuộc 2 yêu cầu bắt buộc.
- ⚠️ Nexus VST3 silent (license). Dùng ACDD demo để chứng minh âm.
- ⚠️ daw_engine.exe serve index.html từ memory lúc start (v=202608121600) dù file trên đĩa đã bump v=202608121700 → restart app mới nhận build mới.
- Ghi chú deploy: copy
app/static/js/app.precompiled.js+app/templates/index.html→dist/,src-tauri/resources/,src-tauri/target/release/(cùng dướidaw_engine/_internal/app/), bump?v=chống cache.