fix: clean sfload with _allocCStr helper + printErr debug + verbose FluidSynth
- Thay MEMFS path từ /soundfonts/ → root / (tránh lỗi thư mục) - Helper _allocCStr + _tryLoadSFL: unique filename, manual C string alloc, cleanup - Thêm printErr callback để capture FluidSynth C stderr log - Bật synth.verbose=1, synth.ladspa.active=0 - Loại bỏ _fluid_synth_get_sfont_count (không export) - Log buffer magic bytes (RIFF/sfbk) để verify file valid
This commit is contained in:
@@ -81,7 +81,10 @@
|
|||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
},
|
},
|
||||||
TOTAL_MEMORY: TOTAL_MEMORY
|
TOTAL_MEMORY: TOTAL_MEMORY,
|
||||||
|
printErr: function (msg) {
|
||||||
|
if (msg.indexOf('stderr') === -1) console.warn('[FluidSynth:err]', msg);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_fluidModule || !_fluidModule._new_fluid_settings) {
|
if (!_fluidModule || !_fluidModule._new_fluid_settings) {
|
||||||
@@ -89,9 +92,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_settingsPtr = _fluidModule._new_fluid_settings();
|
_settingsPtr = _fluidModule._new_fluid_settings();
|
||||||
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.sample-rate", _audioCtx.sampleRate);
|
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.sample-rate", _audioCtx.sampleRate || 44100);
|
||||||
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.gain", 0.5);
|
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.gain", 0.5);
|
||||||
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.polyphony", 256);
|
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.polyphony", 256);
|
||||||
|
_fluidModule._fluid_settings_setint(_settingsPtr, "synth.verbose", 1);
|
||||||
|
_fluidModule._fluid_settings_setint(_settingsPtr, "synth.ladspa.active", 0);
|
||||||
|
_fluidModule._fluid_settings_setstr(_settingsPtr, "player.timing-source", "audio");
|
||||||
|
console.log("[SonicSF] FluidSynth settings configured");
|
||||||
|
|
||||||
_synthPtr = _fluidModule._new_fluid_synth(_settingsPtr);
|
_synthPtr = _fluidModule._new_fluid_synth(_settingsPtr);
|
||||||
if (!_synthPtr) throw new Error("Failed to create FluidSynth synthesizer");
|
if (!_synthPtr) throw new Error("Failed to create FluidSynth synthesizer");
|
||||||
@@ -117,6 +124,26 @@
|
|||||||
return _initPromise;
|
return _initPromise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_allocCStr: function (str) {
|
||||||
|
var ptr = _fluidModule._malloc(str.length + 1);
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
_fluidModule.HEAPU8[ptr + i] = str.charCodeAt(i);
|
||||||
|
}
|
||||||
|
_fluidModule.HEAPU8[ptr + str.length] = 0;
|
||||||
|
return ptr;
|
||||||
|
},
|
||||||
|
|
||||||
|
_tryLoadSFL: function (buf, ext) {
|
||||||
|
var fname = '/' + ext + '_' + Date.now();
|
||||||
|
try { _fluidModule.FS.unlink(fname); } catch (e) {}
|
||||||
|
_fluidModule.FS.writeFile(fname, new Uint8Array(buf));
|
||||||
|
var cPath = this._allocCStr(fname);
|
||||||
|
var handle = _fluidModule._fluid_synth_sfload(_synthPtr, cPath, 1);
|
||||||
|
_fluidModule._free(cPath);
|
||||||
|
try { _fluidModule.FS.unlink(fname); } catch (e) {}
|
||||||
|
return handle;
|
||||||
|
},
|
||||||
|
|
||||||
loadSoundFont: async function (sfId) {
|
loadSoundFont: async function (sfId) {
|
||||||
if (!_initialized || !_fluidModule) return false;
|
if (!_initialized || !_fluidModule) return false;
|
||||||
if (_currentSfId === sfId) return true;
|
if (_currentSfId === sfId) return true;
|
||||||
@@ -137,31 +164,14 @@
|
|||||||
buf = await resp.arrayBuffer();
|
buf = await resp.arrayBuffer();
|
||||||
if (cache) await cache.saveBuffer(sfId, buf);
|
if (cache) await cache.saveBuffer(sfId, buf);
|
||||||
}
|
}
|
||||||
var ext = '.sf3';
|
var sfHandle = this._tryLoadSFL(buf, '.sf3');
|
||||||
var virtualPath = '/soundfonts/' + sfId + ext;
|
|
||||||
console.log("[SonicSF] Writing to MEMFS:", virtualPath, (buf.byteLength / 1024 / 1024).toFixed(2) + 'MB');
|
|
||||||
try { _fluidModule.FS.unlink(virtualPath); } catch (e) {}
|
|
||||||
_fluidModule.FS.writeFile(virtualPath, new Uint8Array(buf));
|
|
||||||
var fsSize = 0;
|
|
||||||
try { fsSize = _fluidModule.FS.stat(virtualPath).size; } catch (e) {}
|
|
||||||
console.log("[SonicSF] MEMFS stat:", fsSize, "bytes");
|
|
||||||
var sfHandle = _fluidModule._fluid_synth_sfload(_synthPtr, virtualPath, 1);
|
|
||||||
if (sfHandle === -1) {
|
if (sfHandle === -1) {
|
||||||
var errPtr = _fluidModule._fluid_synth_error(_synthPtr);
|
console.warn("[SonicSF] sfload .sf3 failed, trying .sf2 for", sfId);
|
||||||
var errMsg = errPtr ? _fluidModule.UTF8ToString(errPtr) : "unknown";
|
sfHandle = this._tryLoadSFL(buf, '.sf2');
|
||||||
console.warn("[SonicSF] sfload failed for", sfId, "as", ext, "error:", errMsg);
|
}
|
||||||
try { _fluidModule.FS.unlink(virtualPath); } catch (e) {}
|
if (sfHandle === -1) {
|
||||||
ext = '.sf2';
|
console.error("[SonicSF] FluidSynth failed to parse SoundFont:", sfId);
|
||||||
virtualPath = '/soundfonts/' + sfId + ext;
|
return false;
|
||||||
_fluidModule.FS.writeFile(virtualPath, new Uint8Array(buf));
|
|
||||||
sfHandle = _fluidModule._fluid_synth_sfload(_synthPtr, virtualPath, 1);
|
|
||||||
if (sfHandle === -1) {
|
|
||||||
var errPtr2 = _fluidModule._fluid_synth_error(_synthPtr);
|
|
||||||
var errMsg2 = errPtr2 ? _fluidModule.UTF8ToString(errPtr2) : "unknown";
|
|
||||||
console.error("[SonicSF] FluidSynth failed to parse", sfId, "even as .sf2:", errMsg2);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
console.log("[SonicSF] Loaded", sfId, "as .sf2 fallback, handle:", sfHandle);
|
|
||||||
}
|
}
|
||||||
_sfHandleMap.set(sfId, sfHandle);
|
_sfHandleMap.set(sfId, sfHandle);
|
||||||
_currentSfId = sfId;
|
_currentSfId = sfId;
|
||||||
|
|||||||
Reference in New Issue
Block a user