feat: add SoundFont inspection engine + AI instrument schema

- SoundFontInspector (sf2utils) scans .sf2, generates full/condensed catalog
- GET /api/v1/plugins/soundfonts/catalog with lazy init + cache invalidation
- AI tool generate_multitrack_midi now requires soundfont_id/bank/program
- Condensed catalog auto-injected into AI system prompt with bank rules
- Server render: FluidSynth program_select uses bank/program + channel routing (drums→ch9)
- VST3 pedalboard path inserts CC0 bank select + program change before notes
- DecentSamplerManager loads .dspreset with CWD fix for relative sample paths
- Pianobook render branch in render_engine.py
- Client SonicSF: controllerChange, programChange, applyAITrackInstrument
- Post-AI track creation applies instrument via applyAITrackInstrument
- Background cache rescan on .sf2 upload, frontend re-fetches catalog
- libcurl4 + VST3 dirs in Dockerfile
This commit is contained in:
2026-07-26 12:36:48 +07:00
parent f16467eba1
commit 89c7237379
12 changed files with 361 additions and 13 deletions
+17 -1
View File
@@ -3351,9 +3351,13 @@ const PluginManagerModal = ({ isOpen, onClose, pluginsData }) => {
try {
const result = await window.SonicAPI.uploadSoundFont(file);
setSfUploadStatus('Uploaded: ' + result.name);
// Refresh plugin list
// Refresh plugin list and catalog
const data = await window.SonicAPI.listPlugins();
setLocalData(data);
try {
const cat = await window.SonicAPI.getSoundfontCatalog();
window.__soundfontCatalog = cat;
} catch (_) {}
} catch (err) {
setSfUploadStatus('Error: ' + err.message);
}
@@ -7027,6 +7031,11 @@ const App = () => {
if (active) setSelectedProviderId(active.id);
}
} catch (e) { }
try {
window.SonicAPI.getSoundfontCatalog().then(cat => {
window.__soundfontCatalog = cat;
}).catch(() => {});
} catch (e) { }
})();
}
};
@@ -13802,6 +13811,13 @@ const App = () => {
}))
};
targetTrack.midiItems = [...(targetTrack.midiItems || []), newMidiItem];
if (aiTrack.soundfont_bank !== undefined && aiTrack.soundfont_program !== undefined) {
targetTrack.soundfont_bank = aiTrack.soundfont_bank;
targetTrack.soundfont_program = aiTrack.soundfont_program;
if (window.SonicSF && window.SonicSF.applyAITrackInstrument) {
window.SonicSF.applyAITrackInstrument(aiTrack.soundfont_bank, aiTrack.soundfont_program);
}
}
});
return updatedTracks;
});