Files
suaveplan/packages/media/audio-fx/audio-fx-plugin-gate/src/gate/gate.md
2026-05-27 23:47:53 +01:00

3.7 KiB
Raw Blame History

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 extends AbstractAudioFxPlugin)
    • new GatePlugin(options?: GatePluginOptions) — throws AUDIO_FX.INVALID_OPTIONS on 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.