FIX: (1) masteringConnected default true + ensureMasteringRouting/refreshCarlaStatus ở mọi đường play — MIDI item/preview qua mastering ngay khi chạy app; (2) _instrumentEpoch chống cache stale + retry bank 0 — hết chọn Synth String nghe Piano; (3) /carla-status + auto-open Carla + route exclusive chỉ khi Carla sống (fallback FluidSynth tránh câm); (4) keybed giữ note theo thời gian bấm (auto-off 5s phòng hờ, mouseup dừng ngay)
This commit is contained in:
+54
-8
@@ -101,6 +101,38 @@ const scheduleCarlaNote = (synthEngine, channel, pitch, velocity, startWallTime,
|
||||
} catch (e) { /* routing thất bại im lặng — soundfont vẫn chơi qua FluidSynth */ }
|
||||
};
|
||||
|
||||
// ── Carla bridge alive tracking + auto-open ────────────────────────────────
|
||||
// window.__carlaRunning: undefined = chưa biết | true = đang chạy | false = đã chết.
|
||||
// Quyết định route MIDI item EXCLUSIVE qua Carla hay fallback FluidSynth —
|
||||
// tránh "câm toàn phần" khi Carla bị đóng (route chỉ-Carla mà Carla chết = im lặng).
|
||||
const refreshCarlaStatus = () => {
|
||||
try {
|
||||
if (!window.SonicAPI || !window.SonicAPI.carlaStatus) return;
|
||||
window.SonicAPI.carlaStatus().then(st => {
|
||||
window.__carlaRunning = !!(st && st.running);
|
||||
}).catch(() => { window.__carlaRunning = false; });
|
||||
} catch (e) {}
|
||||
};
|
||||
// Carla chưa chạy → TỰ ĐỘNG mở với VSTi của track (fire-and-forget) để MIDI
|
||||
// item play qua Carla bridge đúng yêu cầu.
|
||||
const ensureCarlaForPlayback = (synthEngine) => {
|
||||
try {
|
||||
if (!window.SonicCarlaMidi || !window.SonicCarlaMidi.shouldRoutePlayback(synthEngine)) return;
|
||||
if (!window.SonicAPI || !window.SonicAPI.carlaStatus) return;
|
||||
window.SonicAPI.carlaStatus().then(st => {
|
||||
if (st && st.running) { window.__carlaRunning = true; return; }
|
||||
window.__carlaRunning = false;
|
||||
const pid = synthEngine && synthEngine.plugin_id;
|
||||
if (pid) {
|
||||
window.SonicAPI.openInCarla(pid).then(r => {
|
||||
if (r && r.success) { window.__carlaRunning = true; }
|
||||
else { window.__carlaRunning = false; }
|
||||
}).catch(() => { window.__carlaRunning = false; });
|
||||
}
|
||||
}).catch(() => { window.__carlaRunning = false; });
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
|
||||
// Handle ?sfs=<encoded> from double-clicking a .sfs file (opens domain -> loads project)
|
||||
(function handleSfsDeepLink() {
|
||||
@@ -9101,7 +9133,10 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
window.triggerMidiVuActivity((st.parent_tab_id && st.parent_tab_id.startsWith('session_') ? '_sess_' : '') + st.trackId, 100);
|
||||
}
|
||||
if (window.SonicSF) {
|
||||
window.SonicSF.playNote(pitch, 100, 500, undefined, kbCtx.program, null, kbCtx.ch, kbCtx.synthEngine);
|
||||
// ⚠️ FIX: giữ note theo thời gian bấm phím — durationMs lớn (5s)
|
||||
// chỉ là auto-off phòng hờ; mouseup/mouseleave gọi stopNote dừng
|
||||
// NGAY (trước đây 500ms → note tự tắt giữa chừng khi giữ phím).
|
||||
window.SonicSF.playNote(pitch, 100, 5000, undefined, kbCtx.program, null, kbCtx.ch, kbCtx.synthEngine);
|
||||
}
|
||||
// MIDI → Carla (track VSTi + ARM + Carla local): preview realtime
|
||||
if (window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoute(kbCtx.synthEngine, st.isArmed)) {
|
||||
@@ -9120,7 +9155,8 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
window.triggerMidiVuActivity((st.parent_tab_id && st.parent_tab_id.startsWith('session_') ? '_sess_' : '') + st.trackId, 100);
|
||||
}
|
||||
if (window.SonicSF) {
|
||||
window.SonicSF.playNote(pitch, 100, 200, undefined, kbCtx.program, null, kbCtx.ch, kbCtx.synthEngine);
|
||||
// giữ note khi kéo qua phím (mouse enter) — dừng bằng mouseup/leave
|
||||
window.SonicSF.playNote(pitch, 100, 5000, undefined, kbCtx.program, null, kbCtx.ch, kbCtx.synthEngine);
|
||||
}
|
||||
if (window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoute(kbCtx.synthEngine, st.isArmed)) {
|
||||
window.SonicCarlaMidi.noteOn(kbCtx.ch, pitch, 100);
|
||||
@@ -16392,7 +16428,7 @@ const App = () => {
|
||||
const [fxRackTarget, setFxRackTarget] = useState(null);
|
||||
window.__openFxRack = (trackId, trackName) => setFxRackTarget({ trackId, trackName });
|
||||
const [masteringSettings, setMasteringSettings] = useState({
|
||||
masterConnected: false,
|
||||
masterConnected: true, // ⚠️ FIX: bật ON mặc định — MIDI item/preview PHẢI được xử lí qua mastering FX ngay khi chạy app (không cần bật/tắt power)
|
||||
activeModule: 'eq',
|
||||
eqActive: true,
|
||||
imagerActive: true,
|
||||
@@ -21078,6 +21114,10 @@ const App = () => {
|
||||
|
||||
const startTrackPlayback = offsetTime => {
|
||||
const context = getAudioContext();
|
||||
// ⚠️ FIX: đồng bộ mastering + Carla status NGAY khi play — MIDI item phải
|
||||
// qua mastering FX (khi bật) và qua Carla bridge (khi VSTi loaded).
|
||||
try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (e) {}
|
||||
refreshCarlaStatus();
|
||||
const allPlayTracks = activeTracksRef.current && activeTracksRef.current.length ? activeTracksRef.current : activeTracks;
|
||||
// Capture items signature at schedule time — updatePlayhead so sánh với
|
||||
// signature này để phát hiện items đổi vị trí giữa lúc play (re-schedule).
|
||||
@@ -21134,6 +21174,7 @@ const App = () => {
|
||||
if ((track.type === 'MIDI' || midiItems.length > 0) && window.SonicSF) {
|
||||
// Preview cache: capture the soundfont (pre track-FX) for fast offline export
|
||||
ensureMidiCapture(track, activeTrackNodesRef.current[track.id]);
|
||||
if (window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(track.synth_engine)) ensureCarlaForPlayback(track.synth_engine);
|
||||
var trkCh = assignTrackMidiChannel(track, allPlayTracks);
|
||||
// Ensure instrument is loaded in FluidSynth
|
||||
if (track.synth_engine && track.synth_engine.type === 'soundfont' && track.synth_engine.soundfont_id) {
|
||||
@@ -21156,7 +21197,7 @@ const App = () => {
|
||||
// Track VSTi + Carla local → MIDI item PHẢI play qua Carla bridge
|
||||
// (chỉ route Carla — KHÔNG play qua FluidSynth GM nữa, tránh âm
|
||||
// sai instrument chồng lên). Không có Carla → FluidSynth như cũ.
|
||||
const routeToCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(track.synth_engine));
|
||||
const routeToCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(track.synth_engine)) && window.__carlaRunning !== false;
|
||||
if (offsetTime < noteStartSec) {
|
||||
const delay = noteStartSec - offsetTime;
|
||||
const startTime = context.currentTime + delay;
|
||||
@@ -21303,7 +21344,8 @@ const App = () => {
|
||||
var subCh = assignTrackMidiChannel(subTrack, secTracks);
|
||||
// MIDI item trong SECTION → Carla bridge khi VSTi loaded
|
||||
// (chỉ route Carla — không play FluidSynth GM sai âm)
|
||||
const subRouteCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(subTrack.synth_engine));
|
||||
const subRouteCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(subTrack.synth_engine)) && window.__carlaRunning !== false;
|
||||
if (subRouteCarla || window.SonicCarlaMidi.shouldRoutePlayback(subTrack.synth_engine)) ensureCarlaForPlayback(subTrack.synth_engine);
|
||||
|
||||
if (offsetTime < noteStartMain) {
|
||||
const delay = noteStartMain - offsetTime;
|
||||
@@ -21372,6 +21414,8 @@ const App = () => {
|
||||
// Solo playback for Local Selection Loop (LOOP_MAKER.md §2.2)
|
||||
const startLocalTrackPlayback = (trackId, offsetTime) => {
|
||||
const context = getAudioContext();
|
||||
try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (e) {}
|
||||
refreshCarlaStatus();
|
||||
const track = tracks.find(t => t.id === trackId);
|
||||
if (!track) return;
|
||||
const clips = track.clips && track.clips.length > 0 ? track.clips : track.buffer ? [{
|
||||
@@ -21426,7 +21470,7 @@ const App = () => {
|
||||
const program = track.instrumentProgram !== undefined ? track.instrumentProgram : 0;
|
||||
// MIDI item → Carla bridge khi VSTi loaded (chỉ route Carla — không
|
||||
// play FluidSynth GM sai âm chồng lên)
|
||||
const routeToCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(track.synth_engine));
|
||||
const routeToCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(track.synth_engine)) && window.__carlaRunning !== false;
|
||||
if (offsetTime < noteStartSec) {
|
||||
const delay = noteStartSec - offsetTime;
|
||||
const startTime = context.currentTime + delay;
|
||||
@@ -21469,6 +21513,8 @@ const App = () => {
|
||||
const schedulePianoRollMidi = (st, offsetSeconds, notesOverride) => {
|
||||
if (st.type !== 'PIANO_ROLL') return;
|
||||
const context = getAudioContext();
|
||||
try { if (window.__ensureMasteringRouting) window.__ensureMasteringRouting(); } catch (e) {}
|
||||
refreshCarlaStatus();
|
||||
const midiNotes = notesOverride || st.notes || [];
|
||||
const bpmVal = parseInt(bpm) || 120;
|
||||
const secondsPerBeat = 60.0 / bpmVal;
|
||||
@@ -21504,7 +21550,7 @@ const App = () => {
|
||||
const durMs = effectiveDur * 1000;
|
||||
// Track VSTi + Carla local → note PHẢI play qua Carla bridge (chỉ route
|
||||
// Carla — không play FluidSynth GM sai âm chồng lên)
|
||||
const routeToCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(synthEngine));
|
||||
const routeToCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(synthEngine)) && window.__carlaRunning !== false;
|
||||
if (!routeToCarla && window.SonicSF) {
|
||||
window.SonicSF.playNote(note.pitch || 60, note.velocity || 0.8, durMs, scheduledTime, instrumentProgram, destNode, mainCh, synthEngine);
|
||||
}
|
||||
@@ -21540,7 +21586,7 @@ const App = () => {
|
||||
var schedTime = startWallTime + effStart;
|
||||
var durMs = effDur * 1000;
|
||||
// Ghost note → Carla bridge khi ghost track VSTi (chỉ route Carla)
|
||||
var gRouteCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(ghostSynth));
|
||||
var gRouteCarla = !!(window.SonicCarlaMidi && window.SonicCarlaMidi.shouldRoutePlayback(ghostSynth)) && window.__carlaRunning !== false;
|
||||
if (!gRouteCarla && window.SonicSF) {
|
||||
window.SonicSF.playNote(note.pitch || 60, note.velocity || 0.8, durMs, schedTime, ghostProg, ghostDest, ghostCh, ghostSynth);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user