fix(bounce): guardPlay drop het note-on — isPlayingRef bi render ghi de =false khi bounce setState; them isExportingRef vao guardPlay (bounce = dang phat that) + TMR_FIRE diag
This commit is contained in:
@@ -17850,6 +17850,10 @@ const App = () => {
|
||||
// khi hết âm).
|
||||
const isPlayingRef = useRef(false);
|
||||
isPlayingRef.current = isPlaying;
|
||||
// Bounce realtime = project đang phát thật; guardPlay (scheduleMidiNoteDispatch)
|
||||
// phải cho note fire dù isPlayingRef bị render ghi đè =false khi bounce setState.
|
||||
const isExportingRef = useRef(false);
|
||||
isExportingRef.current = isExporting;
|
||||
const [selectionStart, setSelectionStart] = useState(null);
|
||||
const [selectionEnd, setSelectionEnd] = useState(null);
|
||||
const [selectionFollowsTempo, setSelectionFollowsTempo] = useState(true);
|
||||
@@ -24597,7 +24601,7 @@ const App = () => {
|
||||
const startAt = startTime || ctx.currentTime; // undefined/null = phát ngay
|
||||
const delayMs = Math.max(0, (startAt - ctx.currentTime) * 1000);
|
||||
// Guard chống note-on trễ sau Stop: CHỈ khi là timeline (startTime thật).
|
||||
const guardPlay = startTime != null ? function () { return isPlayingRef.current || (subTabsRef.current && subTabsRef.current.some(s => s.isPlaying)); } : function () { return true; };
|
||||
const guardPlay = startTime != null ? function () { return isPlayingRef.current || (subTabsRef.current && subTabsRef.current.some(s => s.isPlaying)) || isExportingRef.current; } : function () { return true; };
|
||||
const trkId = track ? track.id : 0;
|
||||
// Percussion (bank 128) → router allocateChannel ch 9; melodic → round-robin.
|
||||
const isPerc = !!(synthEngine && synthEngine.soundfont_bank === 128);
|
||||
@@ -24609,6 +24613,7 @@ const App = () => {
|
||||
// V11: epoch guard — hủy timer cũ khi stop/loop restart (xem ref).
|
||||
const epoch = bridgeNoteEpochRef.current;
|
||||
setTimeout(function () {
|
||||
if (window.__sfDiag) window.__sfDiag('TMR_FIRE track=' + trkId + ' p=' + (pitch || 60) + ' epOk=' + (epoch === bridgeNoteEpochRef.current) + ' guard=' + (guardPlay() ? 1 : 0));
|
||||
if (epoch !== bridgeNoteEpochRef.current) return;
|
||||
if (!guardPlay()) return;
|
||||
if (window.__sfDiag) window.__sfDiag('DISPATCH_ON track=' + trkId + ' p=' + (pitch || 60));
|
||||
@@ -28282,6 +28287,7 @@ const App = () => {
|
||||
if (!masterBus) { showToast("Hãy phát thử một lần để khởi tạo audio engine trước.", "warning"); return; }
|
||||
if (isExporting) return;
|
||||
if (window.__sfDiag) window.__sfDiag('BOUNCE_START');
|
||||
isExportingRef.current = true; // guardPlay: bounce = đang phát thật
|
||||
setIsExporting(true);
|
||||
setShowExportPanel(false);
|
||||
setShowExportProgress(true);
|
||||
@@ -28385,6 +28391,7 @@ const App = () => {
|
||||
} catch (err) {
|
||||
showToast("Lỗi bounce: " + err.message, "error");
|
||||
} finally {
|
||||
isExportingRef.current = false;
|
||||
setIsExporting(false);
|
||||
setShowExportProgress(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user