fix: route PR notes through bridge when active (VST3/SF2 playback via Play button)
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.
This commit is contained in:
@@ -41,6 +41,7 @@ Ký hiệu: **[MỚI]** tạo mới, **[THAY]** thay thế/đổi luồng hiện
|
|||||||
> (trước: check ngay → "no instrument loaded" khi VST3 init chưa xong).
|
> (trước: check ngay → "no instrument loaded" khi VST3 init chưa xong).
|
||||||
> C++ VST3 host thật đã có đủ (Vst3Instrument.cpp 592 dòng, HAVE_VST3SDK). Bundle rebuilt OK (1209801 B);
|
> C++ VST3 host thật đã có đủ (Vst3Instrument.cpp 592 dòng, HAVE_VST3SDK). Bundle rebuilt OK (1209801 B);
|
||||||
> `bridgeAudioNode.js` + `app.precompiled.js` version bump trong index.html. Chạy Windows theo TEST_NOTES.
|
> `bridgeAudioNode.js` + `app.precompiled.js` version bump trong index.html. Chạy Windows theo TEST_NOTES.
|
||||||
|
> **KẾT QUẢ TEST WINDOWS 2026-08-12:** cả 2 yêu cầu PASS — SF2 (024_BigSymphny) PR play peak 0.026468; VST3 ACDD: native GUI mở (class SonicForge_Native_VST3_Class), keybed 0.115554, dispatch 0.153984, PR play nút Play 0.073984. Chi tiết: TEST_NOTES.md §“Kết quả test THẬT Windows”.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -79,3 +79,10 @@ chạy từng mục trên máy Windows (hoặc OS native có đủ toolchain),
|
|||||||
- `transport_control` Rust giờ nhận `playhead: Option<u32>`; JS `NativeBridgeService.transport(kind, playhead)`.
|
- `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.
|
- `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.
|
- 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ở: class `SonicForge_Native_VST3_Class`, title `ACDD`, 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ưới `daw_engine/_internal/app/`), bump `?v=` chống cache.
|
||||||
|
|||||||
@@ -21693,7 +21693,7 @@ const App = () => {
|
|||||||
const startAt = startTime || ctx.currentTime; // undefined/null = phát ngay
|
const startAt = startTime || ctx.currentTime; // undefined/null = phát ngay
|
||||||
const delayMs = Math.max(0, (startAt - ctx.currentTime) * 1000);
|
const delayMs = Math.max(0, (startAt - ctx.currentTime) * 1000);
|
||||||
// Guard chống note-on trễ sau Stop: CHỈ khi là timeline (startTime thật).
|
// Guard chống note-on trễ sau Stop: CHỈ khi là timeline (startTime thật).
|
||||||
const guardPlay = startTime != null ? function () { return isPlayingRef.current; } : function () { return true; };
|
const guardPlay = startTime != null ? function () { return isPlayingRef.current || (subTabsRef.current && subTabsRef.current.some(s => s.isPlaying)); } : function () { return true; };
|
||||||
const trkId = track ? track.id : 0;
|
const trkId = track ? track.id : 0;
|
||||||
// Percussion (bank 128) → router allocateChannel ch 9; melodic → round-robin.
|
// Percussion (bank 128) → router allocateChannel ch 9; melodic → round-robin.
|
||||||
const isPerc = !!(synthEngine && synthEngine.soundfont_bank === 128);
|
const isPerc = !!(synthEngine && synthEngine.soundfont_bank === 128);
|
||||||
@@ -22171,7 +22171,7 @@ const App = () => {
|
|||||||
// future (silence when pressing play). Ghost notes are already relative to
|
// future (silence when pressing play). Ghost notes are already relative to
|
||||||
// the item window, so no absolute-session offset is applied anywhere here.
|
// the item window, so no absolute-session offset is applied anywhere here.
|
||||||
const routeCarla = shouldRouteCarla(synthEngine);
|
const routeCarla = shouldRouteCarla(synthEngine);
|
||||||
if (isStandaloneSf() && !routeCarla && isSfTrackEngine(synthEngine)) {
|
if (isStandaloneSf() && !routeCarla && isSfTrackEngine(synthEngine) && !(window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive())) {
|
||||||
scheduleNativeSfItem(track, { startTime: 0, notes: midiNotes }, offsetSeconds, context, destNode, bpm, { sources: activeSourcesRef.current, isActive: () => !!isPlayingRef.current });
|
scheduleNativeSfItem(track, { startTime: 0, notes: midiNotes }, offsetSeconds, context, destNode, bpm, { sources: activeSourcesRef.current, isActive: () => !!isPlayingRef.current });
|
||||||
return; // native render cả tab → audio buffer (không per-note WASM/Carla)
|
return; // native render cả tab → audio buffer (không per-note WASM/Carla)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user