fix: program_change at call time overrides subsequent notes
_playNoteFluid called program_change synchronously at call time, not at scheduled note time. startTrackPlayback processes all MIDI items first, then all sections -> each note's program_change overwritten by the last type processed. All notes played with section instrument regardless of actual time position. Moved program_change into doNote (setTimeout callback) so it fires at correct time.
This commit is contained in:
@@ -362,41 +362,29 @@
|
||||
typeof velocity === 'number' ? (velocity > 1 ? velocity : velocity * 127) : 100
|
||||
)));
|
||||
var _origChannel = channel;
|
||||
var ch = channel;
|
||||
var usedBank = 0, usedProg = 0;
|
||||
if (synthEngine) {
|
||||
usedBank = synthEngine.soundfont_bank || 0;
|
||||
usedProg = synthEngine.soundfont_program || 0;
|
||||
if (ch === undefined) {
|
||||
if (channel === undefined) {
|
||||
var engKey = (synthEngine.soundfont_id || '') + ':' + usedBank + ':' + usedProg;
|
||||
var mappedCh = _engineChMap[engKey];
|
||||
if (mappedCh !== undefined) {
|
||||
ch = mappedCh;
|
||||
channel = mappedCh;
|
||||
} else {
|
||||
ch = usedBank === 128 ? 9 : 0;
|
||||
channel = usedBank === 128 ? 9 : 0;
|
||||
}
|
||||
}
|
||||
if (ch === undefined) ch = (usedBank === 128 ? 9 : 0);
|
||||
var sfHandle = synthEngine.soundfont_id ? _sfHandleMap.get(synthEngine.soundfont_id) : undefined;
|
||||
if (sfHandle !== undefined) {
|
||||
try {
|
||||
_fluidModule._fluid_synth_program_select(_synthPtr, ch, sfHandle, usedBank, usedProg);
|
||||
} catch (e) {}
|
||||
} else {
|
||||
try { _fluidModule._fluid_synth_bank_select(_synthPtr, ch, usedBank); } catch (e) {}
|
||||
try { _fluidModule._fluid_synth_program_change(_synthPtr, ch, usedProg); } catch (e) {}
|
||||
}
|
||||
if (channel === undefined) channel = (usedBank === 128 ? 9 : 0);
|
||||
} else if (program !== undefined) {
|
||||
usedProg = program;
|
||||
if (ch === undefined) ch = 0;
|
||||
try {
|
||||
_fluidModule._fluid_synth_program_change(_synthPtr, ch, usedProg);
|
||||
} catch (e) {}
|
||||
if (channel === undefined) channel = 0;
|
||||
} else {
|
||||
// No instrument configured: silent — no FluidSynth, no oscillator.
|
||||
return;
|
||||
}
|
||||
if (ch === undefined) ch = (usedBank === 128 ? 9 : 0);
|
||||
if (channel === undefined) channel = (usedBank === 128 ? 9 : 0);
|
||||
var ch = channel;
|
||||
var ctx = getCtx();
|
||||
var now = ctx.currentTime;
|
||||
var delay = (typeof startTime === 'number' && startTime > now) ? (startTime - now) : 0;
|
||||
@@ -405,6 +393,23 @@
|
||||
var self = this;
|
||||
var doNote = function () {
|
||||
try {
|
||||
// Program change at note time, not call time — ensures correct
|
||||
// instrument for each item regardless of processing order.
|
||||
if (synthEngine) {
|
||||
var sfHandle = synthEngine.soundfont_id ? _sfHandleMap.get(synthEngine.soundfont_id) : undefined;
|
||||
if (sfHandle !== undefined) {
|
||||
try {
|
||||
_fluidModule._fluid_synth_program_select(_synthPtr, ch, sfHandle, usedBank, usedProg);
|
||||
} catch (e) {}
|
||||
} else {
|
||||
try { _fluidModule._fluid_synth_bank_select(_synthPtr, ch, usedBank); } catch (e) {}
|
||||
try { _fluidModule._fluid_synth_program_change(_synthPtr, ch, usedProg); } catch (e) {}
|
||||
}
|
||||
} else if (program !== undefined) {
|
||||
try {
|
||||
_fluidModule._fluid_synth_program_change(_synthPtr, ch, usedProg);
|
||||
} catch (e) {}
|
||||
}
|
||||
console.log("[SonicSF] noteOn ch:", ch, "pitch:", midiPitch, "vel:", midiVel);
|
||||
_fluidModule._fluid_synth_noteon(_synthPtr, ch, midiPitch, midiVel);
|
||||
var noteMapKey = (_origChannel !== undefined ? _origChannel : 0) + ':' + midiPitch;
|
||||
|
||||
Reference in New Issue
Block a user