Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
# `gate`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
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
```ts
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.