68 lines
3.3 KiB
Markdown
68 lines
3.3 KiB
Markdown
# parameters
|
||
|
||
<!-- begin:auto-docs -->
|
||
_(no submodules)_
|
||
<!-- end:auto-docs -->
|
||
|
||
## Purpose
|
||
|
||
Declares the parameter surface the `SpessaSynthPlugin` exposes to the host chain: 16 GM channels × 5 controls (`volume`, `pan`, `program`, `reverbSend`, `chorusSend`) plus a master gain, for a total of 81 parameters. Each is described as a `PluginParameter` from `@suaveplan/audio-fx-plugin-base` so the host chain's automation lanes, parameter-curve scheduler, and preset snapshot machinery treat them uniformly with every other plugin in the chain.
|
||
|
||
Parameter ids follow the deterministic `channel/<n>/<kind>` pattern (and the singleton `master/gain`) so external systems — control surfaces, OSC bridges, MIDI-learn UIs — can address any control by literal string without consulting a runtime registry.
|
||
|
||
## Features
|
||
|
||
- `buildParameterDeclarations()` — emits 81 `PluginParameter` records in deterministic order.
|
||
- `channelParameterId(channel, kind)` / `parseChannelParameterId(id)` — symmetric id encode / decode.
|
||
- `assertChannel(channel)` — throws `SPESSASYNTH.INVALID_CHANNEL` for non-integer or out-of-range channels.
|
||
- `CHANNEL_COUNT`, `CHANNEL_PARAM_KINDS`, `MASTER_GAIN_ID` — closed-enum constants.
|
||
- All ratios use `[0, 1]` for sends and volume, `[-1, 1]` for pan, `[0, 127]` for program selection, `[0, 4]` for master gain.
|
||
- Every parameter except `program` is marked `automatable: true` (program-change is a discrete enum jump and shouldn't be interpolated).
|
||
|
||
## Usage: Basic
|
||
|
||
```ts
|
||
import {
|
||
buildParameterDeclarations,
|
||
channelParameterId,
|
||
} from "@suaveplan/audio-fx-plugin-spessasynth/parameters";
|
||
|
||
const parameters = buildParameterDeclarations();
|
||
console.log(channelParameterId(0, "volume")); // "channel/0/volume"
|
||
```
|
||
|
||
## Usage: Advanced
|
||
|
||
```ts
|
||
import {
|
||
parseChannelParameterId,
|
||
MASTER_GAIN_ID,
|
||
assertChannel,
|
||
} from "@suaveplan/audio-fx-plugin-spessasynth/parameters";
|
||
|
||
function applyAutomation(id: string, value: number) {
|
||
if (id === MASTER_GAIN_ID) {
|
||
processor.setMasterGain(value);
|
||
return;
|
||
}
|
||
const decoded = parseChannelParameterId(id);
|
||
if (!decoded) return;
|
||
assertChannel(decoded.channel);
|
||
routeToChannel(decoded.channel, decoded.kind, value);
|
||
}
|
||
```
|
||
|
||
## API Reference
|
||
|
||
- `CHANNEL_COUNT: 16`, `MAX_CHANNEL_INDEX: 15`.
|
||
- `CHANNEL_PARAM_KINDS: ReadonlyArray<"volume" | "pan" | "program" | "reverbSend" | "chorusSend">`.
|
||
- `channelParameterId(channel: number, kind: ChannelParamKind): string`.
|
||
- `parseChannelParameterId(id: string): { channel, kind } | undefined`.
|
||
- `buildParameterDeclarations(): ReadonlyArray<PluginParameter>`.
|
||
- `assertChannel(channel: number): void`.
|
||
- `MASTER_GAIN_ID: "master/gain"`.
|
||
|
||
## Implementation Notes
|
||
|
||
`program` is declared `automatable: false` because the host chain's parameter-schedule evaluator interpolates linearly; an in-flight ramp between two program numbers would emit non-integer program values to the underlying synth, which has no defined semantics. Treating program-change as a discrete `setParameter` write keeps the contract clean. `volume` is `[0, 1]` to match MIDI CC #7 semantics — callers that need pre-master headroom should drive `master/gain` (which goes to 4×) rather than over-driving channel volume. The parameter order — channels in numeric order, kinds in declaration order, master last — is deterministic so snapshots and UI iteration produce stable byte-for-byte output.
|