FIX: (1) MIDI item route CHỈ qua Carla bridge khi VSTi loaded (bỏ FluidSynth GM sai âm) ở mọi đường playback + ghosts; (2) updateSfRouting sync route gains nhánh gainNode + ensureMasteringRouting force-sync mọi node — preview MIDI keyboard qua mastering không cần bật/tắt power; (3) stopNote/panic dừng fallback oscillator theo channel:pitch — hết âm kêu liên tục sau khi thả phím

This commit is contained in:
2026-08-10 09:07:42 +00:00
parent 75795653c5
commit f492104869
5 changed files with 229 additions and 90 deletions
+8
View File
@@ -1,3 +1,11 @@
### [2026-08-10] Task: Fix (KHÔNG bỏ qua) — MIDI keyboard preview không qua mastering + noteoff không xử lí + MIDI item không play qua Carla bridge
- **Tóm tắt thay đổi:**
(1) **MIDI item PHẢI play qua Carla bridge khi VSTi loaded** (`app.jsx`): trước đây các hàm playback gọi `SonicSF.playNote` (FluidSynth GM — âm SAI) SONG SONG với route Carla → âm nghe được là GM, không phải VSTi. Giờ: mọi đường playback (startTrackPlayback main, MIDI section subTrack, startLocalTrackPlayback, schedulePianoRollMidi + ghost notes) tính `routeToCarla = shouldRoutePlayback(synth_engine)` — nếu TRUE → CHỈ route Carla (bỏ hẳn FluidSynth); FALSE → FluidSynth như cũ.
(2) **MIDI keyboard preview không route qua mastering FX chain** (`app.jsx`): `updateSfRouting` nhánh gainNode (piano roll + midiAudible) THIẾU sync route gains → node giữ bypass cũ (tạo khi mastering OFF / audioBypass true) → preview đi dry cho tới khi bật/tắt power. Fix: sync `route.routeGain/dryGain` theo `effMidiBypass` NGAY tại thời điểm routing; `ensureMasteringRouting` giờ force-sync MỌI node (sfRouteGain/sfDryGain + routeGain/dryGain) theo trạng thái hiện tại.
(3) **Âm kêu liên tục dù đã thả phím (không xử lí noteoff)** (`soundfontPlayer.js`): khi FluidSynth WASM chưa sẵn sàng / font load fail → `_playNoteFallback` tạo oscillator — `stopNote` trước đây CHỈ noteoff FluidSynth, KHÔNG dừng oscillator → âm kêu tới khi auto-stop 2s. Fix: `_activeOscillatorsByKey` (key 'channel:pitch'); `stopNote` dừng oscillator đúng key ngay (osc.stop + gain 0); `panic`/`stopAll` dừng toàn bộ + clear map.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js` (rebuild babel), `app/static/js/services/soundfontPlayer.js`, `app/templates/index.html` (?v= 202608101600), `dist/daw_engine/_internal/app/static/**` + `templates/index.html`
- **Ghi chú/Test (nếu có):** pytest 86 passed, 7 skipped. Test jsdom noteoff: 6/6 pass (stopNote gọi osc.stop ngay t=1.0 + gain 0; đúng channel:pitch — không đụng note/osc channel khác; panic dừng tất cả). Bundle: routeToCarla ở cả 4 đường + ghosts. ⚠️ Rebuild PyInstaller exe trên Windows để nhận backend fix trước đó (plugins.py/projects.py — PYZ).
### [2026-08-10] Task: Preview soundfont + MIDI keyboard không đi qua mastering FX main out (phải bật/tắt power mới có tác dụng)
- **Tóm tắt thay đổi:** Routing âm thanh SF preview (keybed/draw/MIDI file) chỉ được đồng bộ khi masteringSettings ĐỔI (toggle power) — bắt đầu preview KHÔNG chạy lại `updateSfRouting` + đồng bộ route gains → âm preview không tự động qua mastering chain cho tới khi bật/tắt nút power. Fix: (1) thêm `ensureMasteringRouting()` trong App (toggleMasteringOnMaster theo trạng thái hiện tại — early-return nếu đúng; applyMasteringSettings; updateSfRouting) — gọi tại: keybed onMouseDown, playDrawPreview, playMidiPreview (Media Explorer), mở piano roll tab (setTimeout 60ms sau setActiveTab); (2) thêm `masterConnected`/`isBypassed` vào sig của `applyMasteringSettings` — toggle power luôn re-apply tham số module (hết blind-spot early-return); (3) expose `window.__ensureMasteringRouting`. Đã kiểm chứng bằng test jsdom (AudioContext mock theo dõi connect): khi mastering ON, path SF_ROUTE → masterBus.input → inputAnalyser → eqLowFilter (mastering chain) → destination là ĐÚNG — vấn đề nằm ở chỗ không re-sync routing tại thời điểm preview.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js` (rebuild babel), `app/templates/index.html` (?v= bump 202608101400), `dist/daw_engine/_internal/app/static/**` + `templates/index.html`