Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@suaveplan/audio-fx-plugin-spessasynth - SF2/SF3 SoundFont synthesizer plugin for the @suaveplan/audio-fx-plugin-* family.
SF2/SF3 SoundFont synthesizer plugin for the @suaveplan/audio-fx-plugin-* family. Wraps the MIT-licensed SpessaSynth engine as a standard AudioFxPlugin, so it composes inside any PluginChain, accepts MIDI from a MidiPortLike consumer, and exposes its 16-channel parameter surface through the same automation / snapshot / preset machinery every other plugin uses.
spessasynth_lib is declared as an optionalDependencies entry and pulled in only via lazy import() inside the loader, so consumers who never call init() pay zero bundle cost.
Documentation tree
- error-codes — Defines the stable
SPESSASYNTH.*error-code namespace used by every other module in `@suaveplan/audio-fx-plugin-spess…- error-codes — Defines the stable
SPESSASYNTH.*error-code namespace used by every other module in `@suaveplan/audio-fx-plugin-spess…
- error-codes — Defines the stable
- loader — Lazy entry point for the SF2/SF3/DLS SoundFont pipeline. The loader is the only place in the package where `spessas…
- soundfont-loader — Lazy entry point for the SF2/SF3/DLS SoundFont pipeline. The loader is the only place in the package where `spessas…
- midi-router — Routes
MidiMessageevents from aMidiPortLike(or a directhandle()call) into the upstream `SpessaSynthProcessor…- midi-router — Routes
MidiMessageevents from aMidiPortLike(or a directhandle()call) into the upstream `SpessaSynthProcessor…
- midi-router — Routes
- parameters — Declares the parameter surface the
SpessaSynthPluginexposes to the host chain: 16 GM channels × 5 controls (volume…- parameters — Declares the parameter surface the
SpessaSynthPluginexposes to the host chain: 16 GM channels × 5 controls (volume…
- parameters — Declares the parameter surface the
- plugin —
SpessaSynthPluginis theAudioFxPluginimplementation that wraps the SpessaSynth SF2/SF3 SoundFont engine. It is a…- spessasynth-plugin —
SpessaSynthPluginis theAudioFxPluginimplementation that wraps the SpessaSynth SF2/SF3 SoundFont engine. It is a…
- spessasynth-plugin —
- register — Provides the one-call helper
registerSpessaSynthPlugin(registry)that attaches the SpessaSynth plugin factory to a `P…- register — Provides the one-call helper
registerSpessaSynthPlugin(registry)that attaches the SpessaSynth plugin factory to a `P…
- register — Provides the one-call helper
- telemetry — OpenTelemetry instrument bridge for the SpessaSynth plugin. Exposes three instruments under the meter `@suaveplan/audio…
- telemetry — OpenTelemetry instrument bridge for the SpessaSynth plugin. Exposes three instruments under the meter `@suaveplan/audio…
- voice-manager — Owns the polyphony cap and the voice-stealing policy layered on top of the upstream
SpessaSynthProcessor. The process…- voice-manager — Owns the polyphony cap and the voice-stealing policy layered on top of the upstream
SpessaSynthProcessor. The process…
- voice-manager — Owns the polyphony cap and the voice-stealing policy layered on top of the upstream
Quickstart
import { SpessaSynthPlugin } from "@suaveplan/audio-fx-plugin-spessasynth";
const plugin = new SpessaSynthPlugin();
await plugin.init({
soundFontUrl: "/assets/gm.sf2",
sampleRate: 48_000,
});
await plugin.setup(
{ sampleRate: 48_000, channels: 2, blockSize: 128 },
chainContext
);
plugin.sendMidi({ type: "noteOn", channel: 0, note: 60, velocity: 100 });
const out: Float32Array[] = [
new Float32Array(128),
new Float32Array(128),
];
plugin.process([], out, {
blockOffsetSamples: 0,
sampleRate: 48_000,
channels: 2,
opts: {},
});
SF2 loading
// From a URL (browser):
await plugin.init({ soundFontUrl: "/assets/gm.sf2" });
// From an in-memory blob (offline render / tests):
await plugin.init({ soundFontBytes: sf2Bytes });
// With an AbortController:
await plugin.init({ soundFontUrl, signal: ac.signal });
Control-surface integration
import {
SpessaSynthPlugin,
channelParameterId,
MASTER_GAIN_ID,
} from "@suaveplan/audio-fx-plugin-spessasynth";
// A control-surface knob driving channel-0 volume in real time:
controlSurface.onKnobMove((value) => {
plugin.setParameter(channelParameterId(0, "volume"), value);
});
// Automate the master gain over half a second:
plugin.setParameterCurve(MASTER_GAIN_ID, {
type: "linear",
value: 0,
duration: 0.5,
});
Registry
import { PluginRegistry } from "@suaveplan/audio-fx-plugin-base/registry";
import { registerSpessaSynthPlugin } from "@suaveplan/audio-fx-plugin-spessasynth/register";
const registry = new PluginRegistry();
registerSpessaSynthPlugin(registry);
// Now `chain.restore(snapshot, registry)` can rehydrate any snapshot
// containing a SpessaSynth slot.
Modules
error-codes—SPESSASYNTH.*codes viadefineCodes.loader— lazyimport("spessasynth_lib"), SF2/SF3/DLS magic sniff, parse.midi-router— channel-voice + program-change + NRPN/RPN reassembly.parameters— 16-channel × 5-control + master gain (81 parameters).voice-manager— polyphony cap + voice-stealing.plugin—SpessaSynthPlugin(theAudioFxPluginimplementation).telemetry— OTel counter + histogram + observable gauge.register— registry helper for snapshot-restore.
License
MIT.