fix: lag khi ARM sau reload + câm sau vài lần nhấn MIDI - dedup loadSoundFont (1 font=1 sfload, tránh cạn heap 256MB) + preload instrument khi mở/khôi phục dự án

This commit is contained in:
2026-08-03 10:43:26 +07:00
parent 0dc95386f2
commit 25471e6ea5
5 changed files with 45 additions and 5 deletions
+19
View File
@@ -4627,6 +4627,23 @@ const ProfileModal = ({
}
};
const preloadTrackInstruments = async (tracks) => {
// Preload each track's soundfont before the user plays otherwise the first
// MIDI key after reload triggers a lazy font load and the note sounds late.
if (!window.SonicSF || !window.SonicSF.selectInstrument) return;
for (const t of (tracks || [])) {
const se = t.synth_engine;
const sfId = (se && se.soundfont_id) || t.soundfont_id;
if (!sfId) continue;
const bank = se ? (se.soundfont_bank !== undefined ? se.soundfont_bank : 0) : (t.soundfont_bank !== undefined ? t.soundfont_bank : 0);
const prog = se ? (se.soundfont_program !== undefined ? se.soundfont_program : 0) : (t.soundfont_program !== undefined ? t.soundfont_program : 0);
var ch = window.SonicPianoRoll ? window.SonicPianoRoll.getTrackMidiChannel(t, tracks) : (t.midiChannel !== undefined ? t.midiChannel : 0);
try {
await window.SonicSF.selectInstrument(ch, bank, prog, sfId);
} catch (e) {}
}
};
const handleOpenProject = async (projectId, projectName) => {
setAppWarningModal({
title: "Mở dự án",
@@ -4685,6 +4702,7 @@ const ProfileModal = ({
}
setTracks(restoredTracks);
loadAudioBuffersForTracks(restoredTracks).catch(function(err) { console.warn('loadAudioBuffersForTracks error:', err); });
preloadTrackInstruments(restoredTracks).catch(function(err) { console.warn('preloadTrackInstruments error:', err); });
setBpm(restoredBpm.toString());
setSelectedTrackId(restoredTracks[0]?.id || '1');
setProjectName(proj.name);
@@ -12110,6 +12128,7 @@ const App = () => {
}
setTracks(restoredTracks);
loadAudioBuffersForTracks(restoredTracks).catch(function(err) { console.warn('loadAudioBuffersForTracks error:', err); });
preloadTrackInstruments(restoredTracks).catch(function(err) { console.warn('preloadTrackInstruments error:', err); });
setBpm(restoredBpm.toString());
setSelectedTrackId(restoredTracks[0]?.id || '1');
setProjectName(lastName);
File diff suppressed because one or more lines are too long
+15 -1
View File
@@ -23,6 +23,8 @@
let _activeOscillators = {};
let _gainNode = null;
let _scheduledNotes = [];
let _loadPromises = {};
let _sfloadSeq = 0;
const getCtx = function () {
if (_audioCtx) {
@@ -186,7 +188,7 @@
},
_tryLoadSFL: function (buf, ext) {
var fname = '/' + ext + '_' + Date.now();
var fname = '/' + ext + '_' + (++_sfloadSeq) + '_' + Date.now();
try { _fluidModule.FS.unlink(fname); } catch (e) {}
_fluidModule.FS.writeFile(fname, new Uint8Array(buf));
var cPath = this._allocCStr(fname);
@@ -203,6 +205,18 @@
_currentSfId = sfId;
return true;
}
// Deduplicate concurrent loads: rapid key presses (or several armed
// tracks) all call loadSoundFont for the same font before the first
// load resolves. Without this, the same soundfont is sfload'd several
// times (handles 1,2,3,4…) — wasting the 256MB WASM heap and stalling
// notes until each load finishes (audible lag, then silence).
if (!_loadPromises[sfId]) {
_loadPromises[sfId] = this._doLoadSoundFont(sfId);
}
return _loadPromises[sfId];
},
_doLoadSoundFont: async function (sfId) {
try {
var cache = window.SonicSFStorage;
var buf = cache ? await cache.getBuffer(sfId) : null;
+2 -2
View File
@@ -16,7 +16,7 @@
<script src="/static/js/services/audioEngine.js?v=202607271016"></script>
<script src="/static/js/services/storage.js?v=202607271016"></script>
<script src="/static/js/services/soundfontStorage.js?v=202607271016"></script>
<script src="/static/js/services/soundfontPlayer.js?v=202608031030"></script>
<script src="/static/js/services/soundfontPlayer.js?v=202608031040"></script>
<script src="/static/js/services/aiGateway.js?v=202607271016"></script>
<script src="/static/js/services/dawCommandDispatcher.js?v=202607271016"></script>
<script src="/static/js/services/pianoRollTabService.js?v=202607272044"></script>
@@ -24,7 +24,7 @@
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
<script src="/static/js/app.precompiled.js?v=202608022001" defer></script>
<script src="/static/js/app.precompiled.js?v=202608031040" defer></script>
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
<style>
:root {