Skip to content

audiojs/audio-effect

Repository files navigation

audio-effect

Canonical audio effect implementations.

Modulation
Phaser · Flanger · Chorus · Wah-wah · Tremolo · Vibrato · Ring mod · Pitch shifter · Auto-wah

Dynamics
Compressor · Limiter · Noise gate · Envelope follower · Transient shaper · Expander

Delay
Delay · Multitap · Ping-pong · Reverb

Distortion
Distortion / saturation · Bitcrusher

Spatial
Stereo widener · Haas effect · Panner

Utility
Gain · Mixer · Slew limiter · Noise shaping

Install

npm install audio-effect
// 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:

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:

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]:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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)

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

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)

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)

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

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

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)

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)

About

Canonical audio effects collection

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors