Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
# @suaveplan/audio-fx-plugin-spessasynth — SF2/SF3 SoundFont synthesizer plugin
- **Target path**: `packages/media/audio-fx/audio-fx-plugin-spessasynth/`
- **Tier**: browser (lazy `import()` of `spessasynth_lib`; universal-tier core fallback for offline rendering)
- **Date**: 2026-05-23
- **Status**: PROPOSED
## Why
The audio-fx-plugin family covers EQ, mixer, distortion, delay, gate, pitch-shifter, phaser, tremolo, sampler, microphone, audio-player, and 5 others — but offers no general-purpose virtual instrument. Piano, organ, drum kits, orchestral instruments, classic synths — all of these are commodity-grade content delivered as SoundFont files (`.sf2` / `.sf3`). [SpessaSynth](https://github.com/spessasus/SpessaSynth) is an MIT-licensed pure-JS SoundFont 2.04 + 2.04+ synth engine with full GM/GS/XG support, 24-bit ogg-compressed SF3 support, polyphony management, modulators, and per-voice DSP — exactly the right primitive to wrap.
Wrapping SpessaSynth as an `AudioFxPlugin` (the same contract every existing fx plugin implements) means it composes inside any `PluginChain`, accepts MIDI from `@suaveplan/react-midi`, renders into `@suaveplan/audio-engine-browser` or `@suaveplan/audio-engine-server`, and exposes its parameter set (per-channel volume/pan/program-change/reverb-send/chorus-send + global master volume) through the same automation/snapshot/preset machinery every other plugin uses.
## What changes
1. **NEW package** `@suaveplan/audio-fx-plugin-spessasynth` at `packages/media/audio-fx/audio-fx-plugin-spessasynth/`.
2. **Workspace catalog** — add `spessasynth_lib` (browser-tier) and the SF2 spec test files (vendored fixtures) under `catalog:audio`.
3. **`SpessaSynthPlugin`** implementing `AudioFxPlugin` from `@suaveplan/audio-fx-plugin-base`:
- `process(input, output, ctx)` — input is ignored (instrument is a source); output is the synth's rendered PCM at the chain's sample rate.
- `init({ soundFontUrl?, soundFontBytes?, sampleRate })` — lazy `import("spessasynth_lib")`, async-loads SF2/SF3 from URL or bytes; rejects with `SPESSASYNTH.SOUNDFONT_LOAD_FAILED` on parse failure.
- `dispose()` — releases the underlying synth + frees voice buffers.
4. **MIDI input** — accepts `MidiMessage` events via a structural `MidiPortLike` consumer; routes channel-voice messages to the synth, program-change to the appropriate SF2 preset, NRPN/RPN to the standard handlers (per-note tuning, master fine-tune).
5. **Parameter surface** — 16 channels × `{ volume, pan, program, reverbSend, chorusSend }` + master gain + per-channel mute/solo. Each is an automatable parameter the chain can drive (so a knob on a control surface can pan channel 1 in real time).
6. **Voice management** — exposes `getActiveVoiceCount()`, `setMaxPolyphony(n)`, `allNotesOff(channel?)`. Voice stealing per the SF2 spec.
7. **Preset / snapshot integration** — saves selected SoundFont URL, per-channel program selection, per-channel parameter values via `PluginChain`'s standard snapshot API.
8. **Browser + server tiers** — same plugin works under `audio-engine-browser` (WebAudio) and `audio-engine-server` (offline render); SpessaSynth runs in either context since it's pure JS.
9. **Error codes** — `SPESSASYNTH.{SOUNDFONT_LOAD_FAILED, SOUNDFONT_PARSE_FAILED, UNSUPPORTED_FORMAT, VOICE_LIMIT_EXCEEDED, NOT_INITIALIZED}` via `defineCodes`.
10. **OTel instrumentation** — counter `spessasynth_voices_triggered_total`, gauge `spessasynth_voices_active`, histogram `spessasynth_process_duration_us`.
11. **Demo SF2 fixture** — small (≤2 MiB) public-domain SoundFont vendored under `tests/fixtures/` for round-trip integration tests.
## Impact
- New package in the `audio-fx-plugin-*` family — automatically picked up by the existing `audio-fx-plugin-base` plugin-discovery / chain machinery.
- Unblocks: virtual piano / drum-kit / synth UIs in `@suaveplan/react-control-surface`, the live-DJ scenario (DJ plays piano remotely, sound renders locally via SpessaSynth), GM/GS/XG playback in `@suaveplan/audio-cli`, multimedia exports in `@suaveplan/audio-engine-server`.
- `spessasynth_lib` (~200 KiB minified) added as a lazy `import()` — gated by `optionalDependencies` so consumers who don't use this plugin don't pay the cost.