feat(engine): fix SF2 path resolution, add synth_engine struct and fallback chain
- Fix SF2 path: search upload dir, system dir, static dir (backward compat) - Add synth_engine struct parsing with flat field fallback - Add 3-level fallback: selected SF -> default SF -> oscillator synth - Write synth_engine in setTrackInstrument UI setters - Pass synth_engine context to client SoundFontPlayer and AI gateway
This commit is contained in:
+16
-3
@@ -6492,7 +6492,17 @@ const App = () => {
|
||||
if (t.id !== trackId) return t;
|
||||
const hasInstrument = !!instrumentId;
|
||||
const isSfInstrument = instrumentId && typeof instrumentId === 'string' && instrumentId.startsWith('sf_');
|
||||
return { ...t, instrumentId, instrumentProgram: programNumber !== undefined ? programNumber : undefined, instrumentName: displayName, soundfont_bank: bankNumber !== undefined ? bankNumber : (isSfInstrument ? 0 : undefined), soundfont_program: programNumber !== undefined ? programNumber : undefined, type: hasInstrument ? 'MIDI' : (t.type === 'MIDI' ? 'audio' : t.type) };
|
||||
const sfBank = bankNumber !== undefined ? bankNumber : (isSfInstrument ? 0 : undefined);
|
||||
const sfProg = programNumber !== undefined ? programNumber : undefined;
|
||||
const instrType = isSfInstrument ? 'soundfont' : (hasInstrument ? 'vst3' : 'default');
|
||||
const synthEngine = hasInstrument ? {
|
||||
type: instrType,
|
||||
plugin_id: instrumentId,
|
||||
soundfont_bank: sfBank !== undefined ? sfBank : 0,
|
||||
soundfont_program: sfProg !== undefined ? sfProg : 0,
|
||||
soundfont_id: isSfInstrument ? instrumentId.replace('sf_', '') : ''
|
||||
} : undefined;
|
||||
return { ...t, instrumentId, instrumentProgram: sfProg, instrumentName: displayName, soundfont_bank: sfBank, soundfont_program: sfProg, synth_engine: synthEngine, type: hasInstrument ? 'MIDI' : (t.type === 'MIDI' ? 'audio' : t.type) };
|
||||
}));
|
||||
setInstrumentDropdownTrackId(null);
|
||||
setInstrumentDropdownBtnRect(null);
|
||||
@@ -6544,7 +6554,9 @@ const App = () => {
|
||||
// Set instrument on track immediately so Synth button shows the name
|
||||
updateActiveTracks(prev => prev.map(t => {
|
||||
if (t.id !== trackId) return t;
|
||||
return { ...t, instrumentId, instrumentProgram: undefined, instrumentName: displayName };
|
||||
const sfClean = instrumentId.replace('sf_', '');
|
||||
const synthEngine = { type: 'soundfont', plugin_id: instrumentId, soundfont_bank: 0, soundfont_program: 0, soundfont_id: sfClean };
|
||||
return { ...t, instrumentId, instrumentProgram: undefined, instrumentName: displayName, synth_engine: synthEngine };
|
||||
}));
|
||||
setSelectedSoundFontId(instrumentId);
|
||||
setSynthCategory('soundfont');
|
||||
@@ -10053,6 +10065,7 @@ const App = () => {
|
||||
const track = activeTracksRef.current ? activeTracksRef.current.find(t => t.id === st.trackId) : null;
|
||||
const destNode = getOrCreateTrackNode(track, context);
|
||||
const instrumentProgram = track ? track.instrumentProgram : undefined;
|
||||
const synthEngine = track ? track.synth_engine : undefined;
|
||||
midiNotes.forEach(note => {
|
||||
const noteOnBeat = note.start_beat || 0;
|
||||
const noteDurBeat = note.duration_beats || 1;
|
||||
@@ -10064,7 +10077,7 @@ const App = () => {
|
||||
const scheduledTime = startWallTime + effectiveStart;
|
||||
const durMs = effectiveDur * 1000;
|
||||
if (window.SonicSF) {
|
||||
window.SonicSF.playNote(note.pitch || 60, note.velocity || 0.8, durMs, scheduledTime, instrumentProgram, destNode);
|
||||
window.SonicSF.playNote(note.pitch || 60, note.velocity || 0.8, durMs, scheduledTime, instrumentProgram, destNode, undefined, synthEngine);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -218,6 +218,7 @@ Ví dụ: "Hãy chọn và copy từ bar 4 đến bar 12 của track 1 sau đó
|
||||
function buildAIPromptContext(dawState) {
|
||||
const tracks = (dawState.tracks || []).map(t => {
|
||||
const clips = t.clips && t.clips.length > 0 ? t.clips : (t.buffer ? [{ id: 'default_' + t.id, name: t.name, startTime: t.startTime || 0, duration: t.buffer.duration }] : []);
|
||||
const se = t.synth_engine || null;
|
||||
return {
|
||||
id: t.id,
|
||||
name: t.name,
|
||||
@@ -227,6 +228,7 @@ Ví dụ: "Hãy chọn và copy từ bar 4 đến bar 12 của track 1 sau đó
|
||||
solo: t.solo,
|
||||
volumeDb: t.volumeDb ?? 0,
|
||||
pan: t.pan ?? 0,
|
||||
synth_engine: se ? { type: se.type, plugin_id: se.plugin_id, soundfont_bank: se.soundfont_bank, soundfont_program: se.soundfont_program, soundfont_id: se.soundfont_id } : undefined,
|
||||
clips: clips.map(c => ({ id: c.id, name: c.name, startTime: parseFloat((c.startTime || 0).toFixed(3)), duration: parseFloat((c.buffer ? c.buffer.duration : 0).toFixed(3)) }))
|
||||
};
|
||||
});
|
||||
|
||||
@@ -57,7 +57,11 @@
|
||||
return ch;
|
||||
},
|
||||
|
||||
applyAITrackInstrument: function (bank, program) {
|
||||
applyAITrackInstrument: function (bank, program, synthEngine) {
|
||||
if (synthEngine) {
|
||||
bank = bank !== undefined ? bank : (synthEngine.soundfont_bank || 0);
|
||||
program = program !== undefined ? program : (synthEngine.soundfont_program || 0);
|
||||
}
|
||||
const channel = this.allocateChannel(bank);
|
||||
this.controllerChange(channel, 0, bank);
|
||||
this.programChange(channel, program);
|
||||
@@ -79,11 +83,20 @@
|
||||
return buffer;
|
||||
},
|
||||
|
||||
playNote: function (note, velocity, durationMs, startTime, program, destinationNode, channel) {
|
||||
playNote: function (note, velocity, durationMs, startTime, program, destinationNode, channel, synthEngine) {
|
||||
const ctx = getCtx();
|
||||
const freq = 440 * Math.pow(2, (note - 69) / 12);
|
||||
if (freq <= 0 || isNaN(freq)) return null;
|
||||
|
||||
// Apply synth_engine state if provided
|
||||
if (synthEngine) {
|
||||
const ch = channel !== undefined ? channel : (synthEngine.soundfont_bank === 128 ? 9 : 0);
|
||||
this.controllerChange(ch, 0, synthEngine.soundfont_bank || 0);
|
||||
this.programChange(ch, synthEngine.soundfont_program || 0);
|
||||
if (channel === undefined) channel = ch;
|
||||
if (program === undefined) program = synthEngine.soundfont_program;
|
||||
}
|
||||
|
||||
const osc = ctx.createOscillator();
|
||||
const noteGain = ctx.createGain();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user