3.7 KiB
gate
(no submodules)
Purpose
GatePlugin is the universal noise gate. When the input envelope falls below threshold, the gate closes after hold ms via the release envelope; when the envelope rises back above threshold, the gate opens via attack. The envelope is linked across input channels so a transient on any channel opens the gate for the whole frame, keeping the stereo image phase-coherent during gated passages.
The plugin extends AbstractAudioFxPlugin, so it runs identically across browser / server / worklet renderers. Gate state is one number (currentGain) plus a hold-sample counter; reset() zeros both in place.
Features
- Four parameters:
threshold(dB, -80..0),attack(ms, 0.1..100),hold(ms, 0..500),release(ms, 1..1000). - Linked envelope detection:
max(|in_c|)across all input channels per sample so a stereo transient on either channel opens the gate. - One-pole attack/release smoothing with
coef = 1 − exp(-1/(τ · sr))per direction. - Hold counter resets every time the envelope crosses the threshold so a sustained-but-fluctuating signal stays gated open.
getCurrentGain()accessor exposes the live gate gain for metering / VCAs that mirror the gate.
Usage: Basic Example
import { GatePlugin } from "@suaveplan/audio-fx-plugin-gate";
const gate = new GatePlugin({
initialThresholdDb: -40,
initialAttackMs: 1,
initialHoldMs: 20,
initialReleaseMs: 100,
});
chain.add(gate);
Usage: Advanced Example
import { GatePlugin } from "@suaveplan/audio-fx-plugin-gate";
// Tight drum-bus gate: fast attack/release, short hold, aggressive
// threshold. Useful for cleaning up cymbal bleed under snare hits.
const gate = new GatePlugin({
initialThresholdDb: -25,
initialAttackMs: 0.5,
initialHoldMs: 30,
initialReleaseMs: 60,
});
await gate.setup({ sampleRate: 48_000, channels: 2, blockSize: 512 }, ctx);
// Drive a UI meter from the live gate gain.
requestAnimationFrame(function tick() {
meter.write(gate.getCurrentGain());
requestAnimationFrame(tick);
});
API Reference
GatePlugin(class extendsAbstractAudioFxPlugin)new GatePlugin(options?: GatePluginOptions)— throwsAUDIO_FX.INVALID_OPTIONSon malformed options.getCurrentGain(): number— current gate gain (0..1).- Inherited parameter accessors for
threshold,attack,hold,release.
Implementation Notes
The envelope detector is per-sample peak across channels: level = max(|in_c[i]|). This is the cheapest detector that still responds to fast transients; an RMS detector would smooth out kick-drum attacks, which is rarely what a noise gate wants.
The hold counter resets every time level >= thresholdLin, then decrements while the envelope is below threshold. While hold > 0 the target gain stays at 1; once hold === 0 the target drops to 0 and the release ramp engages. This implements the spec's "after the hold time" semantics literally.
attackCoef and releaseCoef are one-pole filter coefficients (1 − exp(-1/(τ · sr))). At each sample, gain += coef · (target − gain), asymptoting toward target with the relevant time constant. With release = 100 ms at 48 kHz the gain falls by ~63% in the first 100 ms, ~95% in 300 ms, effectively closed within ~500 ms.
The threshold is converted to linear via 10^(thresholdDb / 20) once per block; per-sample the gate compares level (already linear) to that constant.
The plugin has no setSidechain member — gates are usually program-side detection; if a future build wants an external key input, setSidechain can be added behind a hasSidechain: true capability flag without API breakage.