An open API service indexing awesome lists of open source software.

https://github.com/audiojs/audio-effect

Canonical audio effects collection
https://github.com/audiojs/audio-effect

Last synced: about 1 month ago
JSON representation

Canonical audio effects collection

Awesome Lists containing this project

README

          

# audio-effect

Canonical audio effect implementations.

**[Modulation](#modulation)**

[Phaser](#phaser) · [Flanger](#flanger) · [Chorus](#chorus) · [Wah-wah](#wah-wah) · [Tremolo](#tremolo) · [Vibrato](#vibrato) · [Ring mod](#ring-mod) · [Pitch shifter](#pitch-shifter) · [Auto-wah](#auto-wah)

**[Dynamics](#dynamics)**

[Compressor](#compressor) · [Limiter](#limiter) · [Noise gate](#noise-gate) · [Envelope follower](#envelope-follower) · [Transient shaper](#transient-shaper) · [Expander](#expander)

**[Delay](#delay)**

[Delay](#delay-1) · [Multitap](#multitap) · [Ping-pong](#ping-pong) · [Reverb](#reverb)

**[Distortion](#distortion)**

[Distortion / saturation](#distortion--saturation) · [Bitcrusher](#bitcrusher)

**[Spatial](#spatial)**

[Stereo widener](#stereo-widener) · [Haas effect](#haas-effect) · [Panner](#panner)

**[Utility](#utility)**

[Gain](#gain) · [Mixer](#mixer) · [Slew limiter](#slew-limiter) · [Noise shaping](#noise-shaping)

## Install

```
npm install audio-effect
```

```js
// import everything
import * as fx from 'audio-effect'

// import by category
import { phaser, flanger, chorus, wah, autoWah, pitchShifter } from 'audio-effect/modulation'
import { compressor, limiter, gate, envelope, expander } from 'audio-effect/dynamics'
import { delay, multitap, pingPong, reverb } from 'audio-effect/delay'
import { distortion, bitcrusher } from 'audio-effect/distortion'
import { stereoWidener, haas, panner } from 'audio-effect/spatial'
import { gain, mixer, slewLimiter, noiseShaping } from 'audio-effect/utility'
```

## API

All effects share one shape:

```js
effect(buffer, params) // → buffer (modified in-place)
```

Takes a `Float32Array`/`Float64Array`, modifies it in-place, returns it. Pass the same params object on every call — internal state (`_phase`, `_env`, etc.) persists across blocks automatically:

```js
let params = { rate: 1, depth: 0.7, fc: 1000, fs: 44100 }
for (let buf of stream) phaser(buf, params)
```

Spatial effects take two channels and return `[left, right]`:

```js
stereoWidener(left, right, { width: 1.5 }) // → [left, right]
haas(left, right, { time: 0.02, fs: 44100 }) // → [left, right]
panner(left, right, { pan: -0.5 }) // → [left, right]
```

## Modulation

LFO-driven effects that vary a parameter periodically.

### Phaser

Cascade of swept allpass filters creating moving notches and peaks.

**`rate`** LFO rate in Hz (default 0.5) · **`depth`** sweep depth 0–1 (default 0.7) · **`stages`** allpass stages (default 4) · **`feedback`** 0–1 (default 0.5) · **`fc`** center frequency Hz (default 1000) · **`fs`** sample rate

```js
import { phaser } from 'audio-effect/modulation'

let p = { rate: 0.5, depth: 0.7, stages: 4, feedback: 0.5, fc: 1000, fs: 44100 }
for (let buf of stream) phaser(buf, p)
```

**Use when**: electric guitar, synth pads, vintage phase effects

**Not for**: spatial positioning (use stereoWidener or haas)

### Flanger

Modulated short delay (1–10 ms) with feedback — creates comb filter sweep.

**`rate`** LFO rate in Hz (default 0.3) · **`depth`** modulation depth 0–1 (default 0.7) · **`delay`** center delay in ms (default 3) · **`feedback`** 0–1 (default 0.5) · **`fs`** sample rate

```js
import { flanger } from 'audio-effect/modulation'

let p = { rate: 0.3, depth: 0.7, delay: 3, feedback: 0.5, fs: 44100 }
for (let buf of stream) flanger(buf, p)
```

**Use when**: jet sweeps, metallic modulation, guitar/bass

**Not for**: subtle pitch modulation (use vibrato)

### Chorus

Multiple detuned delay voices layered over dry signal — ensemble thickening.

**`rate`** LFO rate in Hz (default 1.5) · **`depth`** modulation depth 0–1 (default 0.5) · **`delay`** center delay in ms (default 20) · **`voices`** number of chorus voices (default 3) · **`fs`** sample rate

```js
import { chorus } from 'audio-effect/modulation'

let p = { rate: 1.5, depth: 0.5, delay: 20, voices: 3, fs: 44100 }
for (let buf of stream) chorus(buf, p)
```

**Use when**: thickening strings, vocals, synth pads

**Not for**: transparent processing (adds modulation artifacts)

### Wah-wah

Swept resonant bandpass filter — auto (LFO) or fixed frequency mode.

**`rate`** LFO rate in Hz (default 1.5) · **`depth`** sweep depth 0–1 (default 0.8) · **`fc`** center frequency Hz (default 1000) · **`Q`** resonance (default 5) · **`mode`** `'auto'` LFO or `'manual'` fixed (default `'auto'`) · **`fs`** sample rate

```js
import { wah } from 'audio-effect/modulation'

let p = { rate: 1.5, depth: 0.8, fc: 1000, Q: 5, fs: 44100 }
for (let buf of stream) wah(buf, p)
```

**Use when**: classic wah sound, filter sweeps

**Not for**: signal-driven wah (use autoWah)

### Tremolo

Amplitude modulation via LFO — periodic volume pulsing.

**`rate`** LFO rate in Hz (default 5) · **`depth`** modulation depth 0–1 (default 0.5) · **`fs`** sample rate

```js
import { tremolo } from 'audio-effect/modulation'

let p = { rate: 5, depth: 0.7, fs: 44100 }
for (let buf of stream) tremolo(buf, p)
```

**Use when**: vintage amp tremolo, rhythmic pulsing, guitar effects

**Not for**: pitch modulation (use vibrato)

### Vibrato

Pitch modulation via modulated delay line — periodic pitch wobble.

**`rate`** LFO rate in Hz (default 5) · **`depth`** delay modulation depth in seconds (default 0.003) · **`fs`** sample rate

```js
import { vibrato } from 'audio-effect/modulation'

let p = { rate: 5, depth: 0.003, fs: 44100 }
for (let buf of stream) vibrato(buf, p)
```

**Use when**: vocal vibrato, string wobble, instrument simulation

**Not for**: amplitude variation (use tremolo)

### Ring mod

Multiplies signal by a carrier oscillator — produces sum and difference frequencies.

**`fc`** carrier frequency Hz (default 440) · **`mix`** wet/dry 0–1 (default 1) · **`fs`** sample rate

```js
import { ringMod } from 'audio-effect/modulation'

let p = { fc: 300, mix: 1, fs: 44100 }
for (let buf of stream) ringMod(buf, p)
```

**Use when**: metallic/robotic tones, experimental textures, AM synthesis

**Not for**: clean frequency shifting

### Pitch shifter

Granular OLA pitch shifting via varispeed read with crossfade grain boundaries.

**`shift`** pitch ratio (default 1.5 · 2 = +octave · 0.5 = −octave) · **`grain`** grain size in samples (default 2048) · **`fs`** sample rate

```js
import { pitchShifter } from 'audio-effect/modulation'

let p = { shift: 1.5, grain: 2048, fs: 44100 }
for (let buf of stream) pitchShifter(buf, p)
```

**Use when**: harmonizer, octave up/down, pitch correction

**Not for**: high-quality transposition (use phase vocoder for that)

### Auto-wah

Envelope follower drives a resonant bandpass filter — signal level controls the sweep.

**`base`** minimum cutoff Hz (default 300) · **`range`** sweep range Hz (default 3000) · **`Q`** resonance (default 5) · **`attack`** envelope attack seconds (default 0.002) · **`release`** envelope release seconds (default 0.1) · **`sens`** input sensitivity multiplier (default 2) · **`fs`** sample rate

```js
import { autoWah } from 'audio-effect/modulation'

let p = { base: 300, range: 3000, Q: 5, sens: 2, fs: 44100 }
for (let buf of stream) autoWah(buf, p)
```

**Use when**: funk guitar, touch-sensitive filter sweeps, envelope filter

**Not for**: LFO-driven wah (use wah with `mode: 'auto'`)

## Dynamics

Gain-control effects that respond to signal level.

### Compressor

Reduces dynamic range above threshold — feedforward with envelope follower and soft knee.

**`threshold`** dB (default −20) · **`ratio`** compression ratio (default 4) · **`attack`** seconds (default 0.003) · **`release`** seconds (default 0.1) · **`knee`** soft knee width dB (default 0) · **`makeupGain`** dB (default 0) · **`fs`** sample rate

```js
import { compressor } from 'audio-effect/dynamics'

let p = { threshold: -18, ratio: 4, attack: 0.003, release: 0.1, fs: 44100 }
for (let buf of stream) compressor(buf, p)
```

**Use when**: taming peaks, bus glue, leveling vocals

**Not for**: hard limiting (use limiter)

### Limiter

Hard ceiling — infinite-ratio compressor, clamps peaks to threshold.

**`threshold`** linear amplitude ceiling (default 0.9) · **`release`** seconds (default 0.1) · **`fs`** sample rate

```js
import { limiter } from 'audio-effect/dynamics'

let p = { threshold: 0.9, release: 0.05, fs: 44100 }
for (let buf of stream) limiter(buf, p)
```

**Use when**: preventing clipping, master bus ceiling, broadcast compliance

**Not for**: transparent dynamic control (use compressor)

### Noise gate

Attenuates signal below threshold — cleans up noise in pauses.

**`threshold`** dB (default −40) · **`range`** attenuation when closed dB (default −80) · **`attack`** seconds (default 0.001) · **`release`** seconds (default 0.05) · **`fs`** sample rate

```js
import { gate } from 'audio-effect/dynamics'

let p = { threshold: -30, range: -80, attack: 0.001, release: 0.05, fs: 44100 }
for (let buf of stream) gate(buf, p)
```

**Use when**: removing mic bleed, drum gate, noise floor cleanup

**Not for**: compression or amplitude control

### Envelope follower

Rectifies and smooths signal to extract amplitude envelope — outputs envelope as signal.

**`attack`** seconds (default 0.01) · **`release`** seconds (default 0.1) · **`fs`** sample rate

```js
import { envelope } from 'audio-effect/dynamics'

let p = { attack: 0.005, release: 0.05, fs: 44100 }
for (let buf of stream) envelope(buf, p)
// buf now contains the envelope curve
```

**Use when**: sidechain source, envelope-controlled parameters, VCA control

**Not for**: gain reduction (use compressor)

### Transient shaper

Separately amplifies or attenuates transient (attack) and sustain portions.

**`attackGain`** transient multiplier (default 1) · **`sustainGain`** sustain multiplier (default 0) · **`fs`** sample rate

```js
import { transientShaper } from 'audio-effect/dynamics'

let p = { attackGain: 2, sustainGain: -0.5, fs: 44100 }
for (let buf of stream) transientShaper(buf, p)
```

**Use when**: drum punch enhancement, click reduction, transient design

**Not for**: general dynamic range control

### Expander

Downward expansion below threshold — attenuates quiet signals, complementing compression.

**`threshold`** dB (default −40) · **`ratio`** expansion ratio > 1 (default 2) · **`range`** maximum attenuation floor dB (default −60) · **`attack`** seconds (default 0.001) · **`release`** seconds (default 0.1) · **`fs`** sample rate

```js
import { expander } from 'audio-effect/dynamics'

let p = { threshold: -40, ratio: 2, range: -60, attack: 0.001, release: 0.1, fs: 44100 }
for (let buf of stream) expander(buf, p)
```

**Transfer function**: for each `dB < threshold`, `gainDB = max((ratio−1)×(dB−threshold), range)`

| ratio | effect |
|---|---|
| 2 | gentle expansion, doubles apparent dynamic range |
| 4 | aggressive, close to gate behavior |
| ∞ | pure gate |

**Use when**: subtle noise reduction, dynamic restoration, complementing compression

**Not for**: hard noise removal (use gate)

## Delay

Time-based echo and reverberation effects.

### Delay

Simple delay — dry signal mixed with delayed copy and optional feedback.

**`time`** delay time in seconds (default 0.25) · **`feedback`** echo decay 0–1 (default 0.3) · **`mix`** wet/dry 0–1 (default 0.5) · **`fs`** sample rate

```js
import { delay } from 'audio-effect/delay'

let p = { time: 0.25, feedback: 0.4, mix: 0.5, fs: 44100 }
for (let buf of stream) delay(buf, p)
```

**Use when**: slap-back echo, rhythmic delays, tape delay emulation

**Not for**: diffuse reverberation (use reverb)

### Multitap

Multiple independent delay taps at different times with individual gains.

**`taps`** array of `{ time, gain }` objects · **`fs`** sample rate

```js
import { multitap } from 'audio-effect/delay'

let p = {
taps: [{ time: 0.1, gain: 0.6 }, { time: 0.25, gain: 0.4 }, { time: 0.4, gain: 0.2 }],
fs: 44100
}
for (let buf of stream) multitap(buf, p)
```

**Use when**: complex rhythmic echo patterns, vintage tape echo with multiple heads

**Not for**: simple single echo (use delay)

### Ping-pong

Cross-fed stereo delay — left echo bounces to right, right to left.

**`time`** delay time in seconds (default 0.25) · **`feedback`** 0–1 (default 0.3) · **`mix`** wet/dry 0–1 (default 0.5) · **`fs`** sample rate

```js
import { pingPong } from 'audio-effect/delay'

let p = { time: 0.15, feedback: 0.5, mix: 0.5, fs: 44100 }
for (let [L, R] of stereoStream) pingPong(L, R, p)
```

**Use when**: stereo width from delays, spatial depth, rhythmic bounce effects

**Not for**: mono output

### Reverb

Schroeder reverb — 4 parallel feedback comb filters with LP damping, 2 series allpass diffusers.

**`decay`** reverb time 0–1 (default 0.84) · **`damping`** high-frequency rolloff 0–1 (default 0.5) · **`mix`** wet/dry 0–1 (default 0.3) · **`fs`** sample rate

```js
import { reverb } from 'audio-effect/delay'

let p = { decay: 0.84, damping: 0.5, mix: 0.3, fs: 44100 }
for (let buf of stream) reverb(buf, p)
```

**Implementation**: 4 parallel comb delays (1277–1523 samples at 44100 Hz), LP filter on feedback path, 2 Schroeder allpass stages (277, 349 samples)

**Use when**: room ambience, plate reverb character, spatial depth

**Not for**: convolution reverb accuracy (use an IR-based approach for that)

## Distortion

Non-linear waveshaping effects.

### Distortion / saturation

Four waveshaping types: cubic soft clip, hard clip, tanh saturation, and wavefolding.

**`drive`** distortion amount 0–1 (default 0.5, maps to 1–10× input gain) · **`type`** `'soft'` | `'hard'` | `'tanh'` | `'foldback'` (default `'soft'`) · **`mix`** wet/dry 0–1 (default 1) · **`fs`** sample rate

```js
import { distortion } from 'audio-effect/distortion'

// Soft saturation
let p = { drive: 0.6, type: 'soft', fs: 44100 }
for (let buf of stream) distortion(buf, p)

// Hard clip
distortion(buf, { drive: 0.8, type: 'hard' })

// Tanh (asymptotically smooth, never clips hard)
distortion(buf, { drive: 0.5, type: 'tanh' })

// Wavefolding (metallic/harsh)
distortion(buf, { drive: 0.7, type: 'foldback' })
```

| type | character | clamps at ±1 |
|---|---|---|
| `soft` | cubic saturation, smooth knee | yes |
| `hard` | brickwall clip, harsh | yes |
| `tanh` | asymptotically smooth | approaches 1 |
| `foldback` | metallic, complex harmonics | yes |

**Use when**: guitar overdrive, tube saturation, lo-fi crunch, harmonic enrichment

**Not for**: transparent limiting (use limiter)

### Bitcrusher

Sample-rate reduction (zero-order hold) + bit-depth quantization.

**`bits`** target bit depth 1–24 (default 8) · **`rate`** sample rate ratio 0–1 (default 0.25, quarter rate) · **`fs`** sample rate

```js
import { bitcrusher } from 'audio-effect/distortion'

// 8-bit, quarter sample rate (lo-fi)
let p = { bits: 8, rate: 0.25, fs: 44100 }
for (let buf of stream) bitcrusher(buf, p)

// Bit depth only, no rate reduction
bitcrusher(buf, { bits: 4, rate: 1 })
```

**Use when**: lo-fi aesthetics, game audio, retro console sound, stutter effects

**Not for**: smooth saturation (use distortion)

## Spatial

Stereo image and positioning effects. All take `(left, right, params)` and return `[left, right]`.

### Stereo widener

Mid/side processing to widen or narrow the stereo image.

**`width`** 0 = mono, 1 = unchanged, 2 = full side emphasis (default 1.5)

```js
import { stereoWidener } from 'audio-effect/spatial'

let p = { width: 1.5 }
for (let [L, R] of stereoStream) stereoWidener(L, R, p)
```

**Use when**: widening narrow mixes, mono-compatibility check (width=0), mastering

**Not for**: positioning a single source (use panner)

### Haas effect

Delays one channel by 1–35 ms — creates phantom stereo from mono source.

**`time`** delay in seconds (default 0.02 = 20 ms) · **`channel`** `'left'` or `'right'` (default `'right'`) · **`fs`** sample rate

```js
import { haas } from 'audio-effect/spatial'

let p = { time: 0.015, channel: 'right', fs: 44100 }
for (let [L, R] of stereoStream) haas(L, R, p)
```

**Use when**: mono-to-stereo widening, spatial placement, drum room simulation

**Not for**: large delays (use ping-pong delay instead)

### Panner

Constant-power stereo panning using cos/sin law.

**`pan`** −1 = full left, 0 = center, +1 = full right (default 0)

```js
import { panner } from 'audio-effect/spatial'

let p = { pan: -0.3 }
for (let [L, R] of stereoStream) panner(L, R, p)
```

**Use when**: placing sources in the stereo field

**Not for**: 3D spatial audio

## Utility

Signal conditioning and mixing tools.

### Gain

Simple level adjustment in decibels.

**`dB`** gain in dB (default 0)

```js
import { gain } from 'audio-effect/utility'

for (let buf of stream) gain(buf, { dB: -6 })
```

### Mixer

Sums an array of buffers with individual gain multipliers.

**`channels`** array of `{ buffer, gain }` objects

```js
import { mixer } from 'audio-effect/utility'

let out = mixer([
{ buffer: drums, gain: 0.8 },
{ buffer: bass, gain: 0.7 },
{ buffer: synth, gain: 0.5 },
])
```

**Use when**: combining signals, bus summing, stem mixing

### Slew limiter

Clips the derivative — limits how fast the signal can change.

**`rise`** maximum rise rate in units/second (default 1000) · **`fall`** maximum fall rate (default 1000) · **`fs`** sample rate

```js
import { slewLimiter } from 'audio-effect/utility'

let p = { rise: 5000, fall: 5000, fs: 44100 }
for (let buf of stream) slewLimiter(buf, p)
```

**Use when**: click removal, smoothing control signals, limiting slew on CVs

**Not for**: dynamic range control

### Noise shaping

Error-feedback quantization — shapes quantization noise out of the audible band.

**`bits`** target bit depth (default 16)

```js
import { noiseShaping } from 'audio-effect/utility'

for (let buf of stream) noiseShaping(buf, { bits: 16 })
```

**Use when**: dithering before bit-depth reduction, quantization to lower bit depths

**Not for**: audio compression (unrelated to lossy codecs)