@audio/noise-estimate

中文文档
2.3.0发布于 2026/10/06MITTypeScriptES Module近 30 天下载 1825

Noise PSD estimation — minimum statistics (Martin 2001), IMCRA (Cohen 2003), and quiet-segment profiling for spectral denoisers

原始使用文档
文档目录7 节
  1. minStats(half, opts?)
  2. imcra(half, opts?)
  3. partials(bins, opts?)
  4. noiseProfile(data, opts?)
  5. known(profile, opts?)
  6. References
  7. Notes

@audio/noise-estimate

Noise power-spectral-density estimation — the noise floor that spectral denoisers subtract, kept off a program's held notes.

Stateful estimators over STFT magnitude frames. Feed them per-frame; read .psd (a Float64Array of N/2+1 bins) whenever you need the current noise estimate.

import { minStats } from '@audio/noise-estimate'
import { stftAnalyse } from '@audio/stft'

let est = minStats(1024, { D: 96 })          // half = frameSize/2
stftAnalyse(signal, mag => est.update(mag), { frameSize: 2048 })
let noisePsd = est.psd                        // drive Wiener / MMSE / OM-LSA gain

minStats(half, opts?)

Minimum Statistics (Martin 2001): the minimum of the recursively smoothed periodogram over the last D frames, times the bias compensation Bmin that makes it estimate the noise power rather than its lower tail. opts: D (window frames, default 96: 1.1 s at hop 512, 44.1 kHz), alpha (smoothing, 0.7), bias (default Bmin(D, α), Martin 2001 eq. 17: 3.44 for the defaults; the window's mean caps it either way), partials (with fs and hop: see partials). Returns { psd, bias, partials, update(mag) }.

Once the window holds D frames, the estimate never exceeds their mean. Bmin is Gaussian noise's ratio of mean to minimum; a steady line (a whine, a pilot tone, a carrier) hardly swings, its minimum is its mean, and Bmin put it 5–7 dB over (6.5 dB in @audio/denoise-wiener's 1.5 s window at 44.1 kHz, where the line then came through 6 dB louder than on its learned profile). The noise holds no more power than its bin: the window's mean caps it, and where the bin swings as noise or speech does, the minimum governs. Before the window is full the minimum alone counts: over fewer frames Bmin(D) runs over the Gaussian bias of that window, and the mean would undercut it everywhere.

The smoother starts as the mean of the frames so far, and its values enter the minimum once its memory, ⌈1/(1−α)⌉ frames (4 at α 0.7), is full; until then that mean is the estimate. Frames of digital silence are skipped: neither a warm-up from zero nor an edited-out pause becomes the window's minimum. Before 2.2.0 the smoother started on the first frame's periodogram, which swings over 2 degrees of freedom rather than the smoothed 2(1+α)/(1−α) Bmin is for: 1 % of bins started 20 dB low and the minimum held them there for D frames (on white noise in a 1.5 s window at 48 kHz, 2.6 % of bins 10 dB under over the first window; now 0.09 %). On white Gaussian noise through 2048/512 Hann frames the estimate's mean is 0.4–0.7 dB under the noise power for D 48–96 and α 0.7–0.95 (the cap takes 0.03–0.35 dB of it, where Pmin·Bmin spreads over the mean).

imcra(half, opts?)

Improved Minima Controlled Recursive Averaging (Cohen 2003): recursive averaging of the noisy power, frozen by the speech presence probability, with that probability from two iterations of time–frequency smoothing and minimum tracking. As the paper (eqs. 7, 10–12, 14–29, Table I), with Cohen's own omlsa.m for what it leaves open; scripts/reference.py in @audio/denoise is written from the paper and reproduces omlsa.m to the last bit on VoiceBank frames (but for near-empty bins, where omlsa.m's absolute 1e-10 floors bind), and test.js holds this code to it.

opts: fs and hop (the frame step: Table I's constants are for 8 ms frames and are rescaled to it, the decision-directed α among them, so time constants and the ~1 s minimum window hold in seconds; without them the constants apply per frame), alpha (αs, 0.9), alphaD (αd, 0.85), beta (1.47), bMin (1.66), gamma0 (4.6), gamma1 (3), zeta0 (1.67), w (1), U (8), V (15 frames of 8 ms), alphaDD (0.92 per 8 ms) and xiMin (−25 dB) for the decision-directed a priori SNR, partials (partials). Until 2.2.0 alphaDD applied per frame, whatever the frame: its memory ran 1.8× longer at 48 kHz (10.7 ms steps) than at 44.1 kHz (5.8 ms).

Returns { psd, xi, xi0, gamma, v, gain, p, frames, update(mag, spp?) }: per frame, on the updated noise estimate, the a priori SNR ξ (xi0: on the previous estimate, what the speech presence probability used), the a posteriori SNR γ, v = γξ/(1+ξ), the LSA gain GH1 and the speech presence probability p. spp (a number or per-bin array) replaces p. Digital silence is skipped. On white Gaussian noise the estimate's mean is within 0.4 dB of the noise power at 16, 44.1 and 48 kHz.

partials(bins, opts?)

A program's partials kept out of a tracked noise. Minimum statistics and IMCRA take whatever holds a bin for about a second as noise: a held note, a sustained vowel, a chord's partials were learned, and the gain built on the estimate took them down. update(y2, psd), each frame after the tracker's own update, reads where a partial stands and there holds psd at what the bin held before the partial came:

  • P, |Y|² smoothed over 30 ms, and F, its morphological opening across frequency (the least over ±4 bins, then the largest of that over ±4): a peak narrower than 9 bins is taken off, the floor between partials stays (the inverse harmonic mask of Nelke, Naylor & Vary, ICASSP 2015).
  • A partial: P over 6 F (7.8 dB) within ±1 bin (vibrato, a glide) for 0.3 s running, and 10 dB over the bin's noise memory. It and its Hann main lobe (±2 bins) are held; a held bin stays held while the tracker reads it 6 dB over its memory, for the tracker still holds what the partial left after it ends.
  • The memory: the tracker's estimate averaged over the bin's free frames (neither peaked nor held), per eighth of T (60 s), the least of the last eight.

A line steady from the take's start (hum, a fan's whine, an engine) has no free frame and no memory: it stays noise. One that starts mid-take is held as a partial until its bin has had no free frame for T, then it is learned, as is a note held longer. A note sounding from the first frame is learned until its bin is once free of it: nothing tells it from a line there. On Gaussian noise alone nothing is held, and the estimate is the tracker's to the bit. Returns { flag, lines, mem, update }: flag, the bins held this frame; lines, the bins with no free frame in the window that have peaked for T/8 running or more (the lines of a noise bed, or a note sounding since the take began); mem, the memory. opts: dt (the frame step, s) and T.

minStats and imcra take it as partials: true (or its options) with fs and hop; their estimators then carry it as .partials. Off by default here; @audio/denoise-omlsa, -wiener and -spectral turn it on. The 0.3 s, the 10 dB and the 60 s were chosen on VoiceBank+DEMAND training speech, four music recordings and VocalSet long tones (scripts/broadband.mjs in @audio/denoise): held from 54 ms on, the guard also held down a noise rising under a voice's harmonics (PESQ −0.015); without the 10 dB rise over the memory, a noise's own peaks were held as partials; a 10 s window let a song's repeated chords be learned (Slakh mixes cut six times as much).

noiseProfile(data, opts?)

One-shot baseline: averages |X|² over a quiet segment (opts.from/opts.to samples). Returns a Float64Array PSD. Use when you can point at a known noise-only region.

known(profile, opts?)

A noise known rather than tracked: profile (a noiseProfile) is held, and each update(mag) gives what imcra gives on it: ξ, decision-directed on GH1 (alphaDD 0.92 per 8 ms, rescaled to the frame step given fs and hop as imcra's; xiMin −25 dB), γ, v and GH1, so a gain written for imcra (OM-LSA's) runs on a learned noise unchanged. xi0 is xi; p stays 0. Digital silence is skipped.

References

R. Martin, "Noise power spectral density estimation based on optimal smoothing and minimum statistics", IEEE Trans. Speech Audio Process. 9(5), 2001 · R. Martin, "Bias compensation methods for minimum statistics noise power spectral density estimation", Signal Processing 86, 2006 (M(D), Table 5) · I. Cohen, "Noise spectrum estimation in adverse environments: improved minima controlled recursive averaging", IEEE Trans. Speech Audio Process. 11(5), 2003 · I. Cohen, omlsa.m, israelcohen.com/software · C. M. Nelke, P. A. Naylor, P. Vary, "Wind noise short term power spectrum estimation using pitch adaptive inverse binary masks", ICASSP 2015.

Notes

STFT via @audio/stft; pairs with @audio/vad's spp(). Also re-exported from @audio/denoise. MIT.

版本与发布记录

@audio/noise-estimate 共发布 7 个版本,首次发布于 2026/07/09;过去 12 个月发布了 7 个版本。

版本发布日期距今
2.3.0latest2026/10/061 个月前
2.2.02026/10/051 个月前
2.1.02026/09/301 个月前
2.0.02026/09/291 个月前
1.0.22026/09/271 个月前
1.0.12026/07/113 个月前

关于 @audio/noise-estimate 的常见问题

@audio/noise-estimate 是什么?

Noise PSD estimation — minimum statistics (Martin 2001), IMCRA (Cohen 2003), and quiet-segment profiling for spectral denoisers

如何安装 @audio/noise-estimate?

在项目目录运行 npm install @audio/noise-estimate,或使用 pnpm add / yarn add / bun add。

@audio/noise-estimate 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@audio/noise-estimate 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@audio/noise-estimate 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@audio/noise-estimate 可以商用吗?

@audio/noise-estimate 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@audio/noise-estimate 的下载量有多少?

根据 npm 官方下载统计,@audio/noise-estimate 在 2026/10/07 – 2026/11/05 这 30 天内被下载 1,825 次,日均约 61 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@audio/noise-estimate 还在维护吗?

最新版本 2.3.0 发布于 2026/10/06(1 个月前);至今共发布 7 个版本,其中过去 12 个月发布了 7 个;首次发布于 2026/07/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。