npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@audio/denoise

v0.3.7

Published

Noise reduction — gate, spectral subtraction, Wiener, OM-LSA, dehum, declick, decrackle, declip, deesser, dereverb

Readme

@audio/denoise npm license

Single-pass noise reduction. 13 specialised methods + an auto-classifier.

| | Domain | Targets | Quality | CPU | Best for | |---|---|---|---|---|---| | denoise | meta | auto | — | varies | "just clean it" | | gate | time | silence | ★ | very low | hard cut at threshold | | dehum | time | mains hum | ★★★★ | very low | 50/60 Hz + harmonics | | specsub | freq | broadband stationary | ★★ | medium | baseline | | wiener | freq | broadband stationary | ★★★ | medium | general broadband | | omlsa | freq | broadband non-stationary | ★★★★ | high | speech in changing noise | | declick | time | impulses | ★★★★ | medium | vinyl pops, edit clicks | | decrackle | time | dense impulses | ★★★ | medium | shellac crackle | | declip | time | hard clipping | ★★★ | medium | restoration | | dewind | time | LF rumble | ★★★ | very low | wind, handling noise | | deplosive | time | LF bursts | ★★★ | low | mic plosives (p, b) | | deesser | time | sibilance | ★★★★ | low | voice (s, sh) | | debreath | time | inter-word noise | ★★★ | low | breath / hiss in pauses | | dereverb | freq | late reverb | ★★ | medium | moderate room reverb |

For broader DSP needs use stretch, shift, pitch, beat.

Usage

npm install @audio/denoise
import { denoise, dehum, wiener, declick } from '@audio/denoise'

let cleaned   = denoise(samples)                              // auto-classify + dispatch
let unhummed  = dehum(samples, { freq: 60 })                  // explicit method
let { out, plan } = denoise(samples, { returnPlan: true })    // see what was chosen
// Streaming — pass options first, then call repeatedly with chunks.
let write = wiener({ fs: 48000 })
write(block1)
write(block2)
write()                                                        // → flush remaining samples

Mono Float32Array in/out. State lives on the params object; pass the same one across calls and biquad memory / spectral history persists. For stereo, process channels independently.

denoise

Content-aware auto-selector. Runs a single STFT classification sweep over the input and dispatches to the most suitable method.

denoise(data)                                                  // → cleaned Float32Array
denoise(data, { returnPlan: true })                            // → { out, plan }
denoise(data, { force: 'wiener' })                             // skip classifier

| Param | Default | | |---|---|---| | fs | 44100 | Sample rate | | force | — | One of 'dehum' \| 'declick' \| 'dewind' \| 'deesser' \| 'dereverb' \| 'omlsa' \| 'wiener' | | returnPlan | false | Return { out, plan } with classifier scores + chosen method |

Routing (in priority order):

  1. tonal hum (Goertzel — ≥2 of first 3 harmonics show 50× line/off-line ratio at 50 or 60 Hz)
  2. impulses (excess kurtosis of AR residual > 12)
  3. sibilance (high/mid band power ratio > 8)
  4. LF rumble (low/mid band power ratio > 3)
  5. non-stationary noise (CV of the rolling-minimum frame-energy floor > 0.3) → omlsa
  6. otherwise → wiener

Tonal & narrowband

dehum

Cascade of high-Q biquad notches at the fundamental + harmonics.

dehum(data, { freq: 60, harmonics: 4 })
dehum(data, { freq: 50, adaptive: true, drift: 0.5 })          // tracks slow mains drift

| Param | Default | | |---|---|---| | freq | 50 | Fundamental (Hz) | | harmonics | 4 | Number of notches placed | | Q | 30 | Notch sharpness — higher = narrower | | adaptive | false | Goertzel sweep refines freq ± drift Hz |

Use when: mains buzz, ground-loop hum, fixed tonal interference. Not for: broadband noise (use wiener/omlsa); shifting tones (use spectral methods).

dewind

Adaptive high-pass. Cutoff slides between cutoffMin and cutoffMax based on the LF/MF energy ratio.

dewind(data, { cutoffMin: 60, cutoffMax: 250 })

| Param | Default | | |---|---|---| | cutoffMin | 60 | Hz — minimum cutoff (LF mostly clean) | | cutoffMax | 250 | Hz — maximum cutoff (heavy rumble) | | order | 2 | HP sections (each 12 dB/oct) | | Q | 0.707 | Butterworth-ish | | blockSize | 1024 | Coefficient update interval (samples) |

Use when: intermittent wind buffeting, handling thumps, low-frequency room modes — the adaptive cutoff opens on gusts and closes between them (measured: beats wiener on gusty wind at ~1/10 the CPU). Not for: continuous rumble under speech — a time-domain cutoff can't separate overlapping spectra; use wiener/omlsa there (measured ~9 dB vs ~1 dB SNR gain). An LPC-null post-filter was evaluated and rejected: voiced speech is as AR-predictable as wind, so nulling wind poles whitens vowels too (LSD improves, SNR and speech level degrade).

deplosive

Splits the signal into an LF band (< crossover) and its exact complement; ducks the LF band when its energy spikes above triggerRatio× the high band (a plosive signature). With no plosive present the output equals the input sample-for-sample — no crossover coloration.

deplosive(data, { triggerRatio: 4, attack: 0.005, release: 0.08 })

| Param | Default | | |---|---|---| | triggerRatio | 4 | LF/high energy ratio that opens the duck | | attenuation | -18 | dB cut on the LF band when triggered | | crossover | 200 | Hz — LF/high split point | | attack | 0.005 | s | | release | 0.08 | s |

Use when: mic plosives (p, b, t) producing low-frequency thuds.

deesser

Dynamic peaking EQ centred on the sibilance band. Detection runs on a HP side-chain; when the envelope exceeds threshold, a negative-gain peaking EQ at freq engages on the audio path. Re-computed every block samples for smooth gain riding. Backed by @audio/dynamics-deesser mode: 'band' since the 2026-07 near-dupe merge — same seconds-based options here.

deesser(data, { freq: 6500, threshold: -28, ratio: 4 })

| Param | Default | | |---|---|---| | freq | 6000 | Sibilance centre (Hz) | | threshold | -30 | dBFS — engagement level | | ratio | 4 | Compression ratio above threshold | | attack | 0.001 | s — how fast the cut engages | | release | 0.05 | s — how slowly it recovers | | Q | 1.4 | Peaking EQ Q | | block | 64 | Coefficient update interval (samples) |

Use when: voice post-production with hot s/sh; vocal bus de-essing.

Broadband & spectral

specsub

Berouti spectral subtraction (1979). Estimates noise from the first noiseFrames (or tracks it via Minimum Statistics) and subtracts α(γ)·N̂(k) — an SNR-adaptive over-subtraction factor — from each magnitude frame, with a β·|Y(k)|² spectral floor. Pass an explicit alpha to force a fixed factor.

specsub(data, { beta: 0.02, noiseFrames: 6 })                 // adaptive α(γ)
specsub(data, { alpha: 2, beta: 0.02 })                       // fixed over-subtraction

| Param | Default | | |---|---|---| | alpha | adaptive | Fixed over-subtraction factor; omit for Berouti α(γ) | | beta | 0.02 | Spectral floor (fraction of the noisy spectrum) | | noiseFrames | first 4 frames | Leading noise-only frames for the PSD bootstrap |

Use when: quick baseline; offline cleanup with a known noise-only preamble. Not for: musical-noise-sensitive material — use wiener or omlsa.

wiener

MMSE Wiener / log-MMSE (Ephraim-Malah 1984/1985) with decision-directed a-priori SNR.

wiener(data, { rule: 'wiener' })                              // pure Wiener gain
wiener(data)                                                   // defaults: 'mmse-lsa' rule

| Param | Default | | |---|---|---| | rule | 'mmse-lsa' | 'wiener' or 'mmse-lsa' (log-spectral, less musical noise) | | alpha | 0.98 | Decision-directed smoothing (alias of alphaDD) | | frameSize | 2048 | STFT frame | | hopSize | frameSize/4 | OLA hop | | noiseFrames | first 4 frames | Leading noise-only frames for PSD bootstrap |

Use when: transparent broadband denoise; the "safe default" for stationary noise.

omlsa

Optimally-Modified Log-Spectral Amplitude estimator (Cohen 2002) driven by IMCRA noise tracking. Combines an LSA gain with a minimum-gain floor weighted by speech presence probability: G = G_LSA^p · G_min^(1-p).

omlsa(data)
omlsa(data, { gMinDb: -25 })                                   // less aggressive floor

| Param | Default | | |---|---|---| | gMinDb | -20 | dB floor for non-speech bins (alias of gMin) | | alpha | 0.92 | Decision-directed smoothing (alias of alphaDD) | | frameSize | 2048 | | | hopSize | frameSize/4 | |

Use when: speech in non-stationary noise (street, café, car); generally the highest-quality choice for noisy speech.

Impulses

declick

Detects impulses as AR-residual outliers (> threshold·σ); replaces each click region with an AR-LS interpolation (Janssen 1986 / Godsill-Rayner 1998).

declick(data, { threshold: 4, order: 60 })

| Param | Default | | |---|---|---| | threshold | 4 | σ-multiple for click detection | | order | 60 | AR model order | | guard | 2 | Extra samples on each side of the detected click | | maxBurst | 64 | Longest run repaired (longer → left as a real transient) |

Use when: vinyl pops, edit clicks, occasional impulse noise. Not for: dense crackle (use decrackle); long dropouts (use arInterpolate directly).

decrackle

Continuous AR-residual outlier detection with MAD-based threshold. Suited to high-rate impulse noise.

decrackle(data, { threshold: 3 })

Use when: shellac / 78 RPM crackle; persistent low-amplitude clicks.

declip

Detects runs of samples at ±clipLevel, fits AR on the un-clipped neighbourhood, extrapolates a sign-constrained interpolation.

declip(data, { clipLevel: 0.95 })                              // explicit threshold
declip(data)                                                   // auto-detects clip level

| Param | Default | | |---|---|---| | clipLevel | auto | Detected from histogram of |x| > 0.5 | | order | 100 | AR model order | | maxRun | order/2 | Longest run that gets restored |

Use when: hard digital clipping with short clip runs. Not for: sustained clipping covering many cycles (use sparsity-based methods).

Reverb

dereverb

Late-reverb suppression (Lebart, Boucher & Denbigh 2001 estimate, Habets-class gain). Models the late tail as a decaying sum of past frames' power, then applies a decision-directed Wiener gain on the signal-to-reverb ratio — the cross-frame smoothing suppresses the musical noise hard subtraction produces.

dereverb(data, { t60: 0.6, predelay: 0.04 })

| Param | Default | | |---|---|---| | t60 | 0.5 | Assumed reverberation time (s) | | predelay | 0.04 | Direct-sound passthrough (s) | | alpha | 1.5 | Reverb-PSD over-estimation factor | | alphaDD | 0.98 | Decision-directed SIR smoothing | | gMin | 0.05 | Gain floor for reverb-dominated bins |

Use when: moderate room reverb (RT60 ≤ 1 s) on a single channel. Not for: heavy reverb or convolutive distortion — use multi-channel WPE (out of scope).

Gates & inter-word

gate

Look-ahead noise gate with hysteresis. Backed by @audio/dynamics-gate since the 2026-07 near-dupe merge — same seconds-based options here; closeThreshold (default threshold − 6 dB) sets the hysteresis close level.

gate(data, { threshold: -45, attack: 0.005, release: 0.1, hold: 0.05, lookahead: 0.005 })

Use when: silence enforcement; aggressive cut between phrases. Not for: continuous denoise — use wiener/omlsa.

debreath

VAD-driven inverse gate. Uses energy + spectral flatness with a percentile-based noise floor; attenuates frames classified as non-speech with smooth attack/release.

debreath(data, { range: -10 })                                // -10 dB on non-speech (default -12)

Use when: breath, mouth noise, hiss in pauses on a voiceover.

Quality measurement

import { snr, segSnr, lsd, nrr, speechAttenuation } from '@audio/denoise'

snr(reference, processed)                                       // global SNR (dB)
segSnr(reference, processed)                                    // segmental SNR (dB)
lsd(reference, processed)                                       // log-spectral distance
nrr(noisyInput, processed)                                      // noise reduction ratio
speechAttenuation(reference, processed)                         // dB lost on speech segments

| Metric | Higher is better | What it captures | |---|---|---| | snr | ✓ | Energy ratio reference / error | | segSnr | ✓ | Time-localised SNR — better correlates with perception | | lsd | ✗ | Mean log-magnitude error per bin | | nrr | ✓ | Floor reduction in non-speech regions | | speechAttenuation | ✗ | Loss of speech energy (over-aggressive denoising) |

Lower-level building blocks

import { stftBatch, stftStream, stftAnalyse } from '@audio/denoise'
import { vad, spp, ddSnr } from '@audio/denoise'
import { noiseProfile, minStats, imcra } from '@audio/denoise'
  • stft* — analysis-modification-synthesis with Hann + ∑win² OLA reconstruction. Visit (mag, phase, state, ctx) => { mag, phase }.
  • vad — frame-level activity (energy + spectral flatness, percentile floor).
  • spp — per-bin Speech Presence Probability under Gaussian model.
  • ddSnr — decision-directed a-priori SNR (Ephraim-Malah).
  • noiseProfile — average PSD over leading frames.
  • minStats — Martin (2001) minimum-statistics noise PSD tracker.
  • imcra — Cohen (2003) Improved Minima-Controlled Recursive Averaging — drives omlsa.

Measurements

npm run measure produces a Markdown table of SNR / segSNR / LSD / NRR per method on canonical scenarios. Headline numbers on the included audio-lena fixture (8 s mono speech, 44.1 kHz):

| scenario | SNR-in | best method | SNR-out | NRR | ms | |---|---:|---|---:|---:|---:| | 60 Hz hum + harmonics | -5.2 dB | dehum | 15.0 dB | 6.3 dB | 5 | | white noise (~13 dB SNR) | 13.2 dB | wiener | 19.8 dB | 0.3 dB | 82 | | clicks (vinyl-style) | 24.1 dB | declick | 44.1 dB | — | 462 | | 7 kHz sibilance | 2.0 dB | deesser | 9.5 dB | 1.9 dB | 5 |

Higher = better.

Demo

demo.html is a self-contained browser demo: pick a noise scenario, pick a method (or auto), inspect input/output waveforms, hear the difference, and read the live classifier scores.

References

  • Boll, Suppression of Acoustic Noise in Speech Using Spectral Subtraction, IEEE TASSP 1979.
  • Berouti, Schwartz, Makhoul, Enhancement of Speech Corrupted by Acoustic Noise, ICASSP 1979.
  • Ephraim & Malah, Speech Enhancement Using a Minimum Mean-Square Error Short-Time Spectral Amplitude Estimator, IEEE TASSP 1984.
  • Ephraim & Malah, Speech Enhancement Using a Minimum Mean-Square Error Log-Spectral Amplitude Estimator, IEEE TASSP 1985.
  • Martin, Noise Power Spectral Density Estimation Based on Optimal Smoothing and Minimum Statistics, IEEE TSAP 2001.
  • Cohen, Optimal Speech Enhancement Under Signal Presence Uncertainty Using Log-Spectral Amplitude Estimator, IEEE SPL 2002.
  • Cohen, Noise Spectrum Estimation in Adverse Environments: Improved Minima Controlled Recursive Averaging, IEEE TSAP 2003.
  • Janssen, Veldhuis & Vries, Adaptive Interpolation of Discrete-Time Signals That Can Be Modeled as Autoregressive Processes, IEEE TASSP 1986.
  • Godsill & Rayner, Digital Audio Restoration, Springer 1998.
  • Lebart, Boucher & Denbigh, A New Method Based on Spectral Subtraction for Speech Dereverberation, Acta Acustica 2001.
  • RBJ Audio EQ Cookbook (biquad coefficients).

License

MIT