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:
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user