FIX: preview soundfont (MIDI keyboard) không tự động qua mastering FX main out

- Thêm ensureMasteringRouting() đồng bộ graph mastering + routing SF + route gains NGAY trước khi preview (keybed onMouseDown, playDrawPreview, playMidiPreview, mở piano roll tab) — hết phải bật/tắt nút power mới có tác dụng
- applyMasteringSettings sig thêm masterConnected/isBypassed — toggle power luôn re-apply tham số module
This commit is contained in:
2026-08-10 06:04:12 +00:00
parent c08233a163
commit 025e0f03a2
4 changed files with 68 additions and 11 deletions
+36 -1
View File
@@ -336,7 +336,7 @@ function applyMasteringSettings(s) {
// Re-applying identical values in rapid bursts is "fast parameter automation"
// and makes Chromium flag the biquad EQ filters as unstable ("state is bad").
// Only touch the graph when a value actually changed.
const sig = [s.eqActive, s.eqLowGain, s.eqMid1Gain, s.eqMid2Gain, s.eqHighGain, s.imagerActive, s.w1, s.w2, s.w3, s.w4, s.maximizerActive, s.maxGain, s.maxSoftClip, s.maxUpward, s.ceiling, s.compActive, s.compThreshold, s.compRatio, s.compMakeup, s.limActive, s.limThreshold, s.excActive, s.excDrive, s.rebalActive, s.rebalMid, s.rebalSide].join('|');
const sig = [s.masterConnected, s.isBypassed, s.eqActive, s.eqLowGain, s.eqMid1Gain, s.eqMid2Gain, s.eqHighGain, s.imagerActive, s.w1, s.w2, s.w3, s.w4, s.maximizerActive, s.maxGain, s.maxSoftClip, s.maxUpward, s.ceiling, s.compActive, s.compThreshold, s.compRatio, s.compMakeup, s.limActive, s.limThreshold, s.excActive, s.excDrive, s.rebalActive, s.rebalMid, s.rebalSide].join('|');
if (sig === _lastMasteringSig) return;
_lastMasteringSig = sig;
@@ -8704,6 +8704,9 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
function playDrawPreview(p, durMs) {
stopPreviewNote();
// Đng b mastering + routing SF trưc khi preview draw (âm qua
// mastering FX ca main out khi chain bt)
try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (er) {}
if (window.SonicSF && window.SonicSF.playNote) {
var pvCtx = getAudioContext();
var pvTrk = activeTracks.find(function(t) { return t.id === st.trackId; });
@@ -9090,6 +9093,10 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
e.stopPropagation();
keybedMouseDownRef.current = true;
try {
// Đng b mastering + routing SF NGAY trưc khi preview âm
// keybed PHI qua mastering FX ca main out khi chain đang bt
// (trưc đây phi bt/tt power mi có tác dng).
try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (er) {}
if (window.triggerMidiVuActivity) {
window.triggerMidiVuActivity((st.parent_tab_id && st.parent_tab_id.startsWith('session_') ? '_sess_' : '') + st.trackId, 100);
}
@@ -13807,6 +13814,9 @@ const MediaExplorerPanel = ({ height, clipboardRef, active }) => {
tempoRef.current = newTempo;
try { localStorage.setItem('studio_media_explorer_tempo', String(newTempo)); } catch (e) {}
const ctx = getAudioContext();
// Đng b mastering + routing SF trưc khi preview MIDI file (âm qua
// mastering FX ca main out khi chain bt)
try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (e3) {}
const bpmVal = tempoRef.current || 120;
const secondsPerBeat = 60.0 / bpmVal;
const startWallTime = ctx.currentTime + 0.05;
@@ -18170,6 +18180,9 @@ const App = () => {
};
setSubTabs(prev => [...prev, newTab]);
setActiveTab(tabId);
// Đng b routing SF + mastering ngay khi m piano roll preview keybed
// phi đi qua mastering FX ca main out (không cn bt/tt power).
setTimeout(() => { try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (e) {} }, 60);
// KHÔNG loadSoundFont đây (k c nn): sfload SF mi bt đng b làm
// WASM heap 256MB đy FluidSynth stall CÂM TOÀN CC (mi âm thanh
// chết sau khi m tab). playNote T load + retry đúng lúc note cn.
@@ -20843,6 +20856,28 @@ const App = () => {
}
};
const updateSfRoutingRef = useRef(null);
// Đng b mastering + routing NGAY TRƯC KHI PREVIEW (keybed/draw/MIDI file)
// Bug: preview instrument soundfont vi MIDI keyboard KHÔNG t đng đi qua
// mastering FX ca main out phi bt/tt nút power mi có tác dng. Nguyên
// nhân: routing SF (setOutputDestination + sfRouteGain/sfDryGain) và graph
// mastering ch đưc đng b khi masteringSettings ĐI (toggle power), không
// chy khi bt đu preview. Hàm này ép đng b 3 lp (graph theo trng thái
// hin ti early-return nếu đã đúng; tham s module; route SF + route
// gains) gi ti mi đim preview âm preview LUÔN qua mastering khi bt.
const ensureMasteringRouting = () => {
try {
const _s = window.currentMasteringSettings;
if (!_s || !masterBus || !audioCtx) return;
toggleMasteringOnMaster(!!_s.masterConnected, !!_s.isBypassed);
applyMasteringSettings(_s);
updateSfRouting();
} catch (e) {
console.warn('ensureMasteringRouting error:', e);
}
};
const ensureMasteringRoutingRef = useRef(null);
ensureMasteringRoutingRef.current = ensureMasteringRouting;
window.__ensureMasteringRouting = ensureMasteringRouting;
// MIDI preview cache (bounce nhanh offline)
// Khi preview: capture tiếng đàn (SF output pre track-FX) vào cache theo
// track. Khi export: nếu cache đ đ dài render OFFLINE NHANH bng cache