Concept
Parameter
A named float you drive at runtime. Subscribers update immediately. Bind it to bus levels, FX values, anything.
TL;DR
A Parameter is the abstraction between "I want intensity to go
up" and "ten things change in the mix." You set the parameter; everything
bound to it (bus levels, FX wet, filter cutoff) updates with the curve and
range you specified.
Mental model
API surface
engine.parameter(name, initial?): Parameter
class Parameter {
readonly name: string;
readonly value: number;
set(v: number): void;
subscribe(fn: (v: number) => void): () => void;
bindTo(setter: (mapped: number) => void, opts?: {
from?: number; // default 0
to?: number; // default 1
curve?: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'equal-power';
}): () => void;
} Live demo
One slider drives bus level and a derived value. Curves, ranges, the works.
Recipes
Get / set
const intensity = engine.parameter('intensity', 0.3);
intensity.set(0.7); // updates all bound targets Bind to one or more targets
intensity.bindTo((v) => engine.bus('music').level = v, {
from: 0.4, to: 1.0, curve: 'easeInOut',
});
intensity.bindTo((v) => filter.setFrequency(v), {
from: 800, to: 12000, curve: 'easeIn',
}); Subscribe for UI updates
const off = intensity.subscribe((v) => console.log('intensity:', v));
// later: off(); Pitfalls
Parameters aren't ramps.
A parameter is a discrete value. Subscribers turn it into a ramp on their
own (e.g. by writing to a bus level which has its own 10 ms internal ramp).
For a guaranteed N-millisecond crossfade, use a Snapshot.
Don't
Each set runs every subscriber synchronously. If you're driving a parameter
from set in a tight loop.requestAnimationFrame, you're already at 60 Hz — fine.
Anything denser, throttle it.