Skip to content

Commit 71811c0

Browse files
committed
Update readme.md
1 parent df2ccbd commit 71811c0

1 file changed

Lines changed: 92 additions & 15 deletions

File tree

readme.md

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -281,59 +281,136 @@ Smoothing and denoising. All operate in-place: `fn(data, params) → data`.
281281

282282
### `onePole(data, params)`
283283

284-
Exponential moving average – the simplest IIR smoother. One multiply per sample, no overshoot. Difference equation: $y[n] = (1-a)\,x[n] + a\,y[n-1]$ where $a = e^{-2\pi f_c/f_s}$. Transfer function: $H(z) = (1-a)/(1-az^{-1})$. Params: `fc`, `fs`.
285-
**–6 dB/oct · 1 multiply · IIR (infinite settling)**
284+
Exponential moving average – the simplest IIR smoother. One multiply per sample, no overshoot. Params: `fc`, `fs`.
285+
**–6 dB/oct · 1 multiply · IIR**
286+
287+
```js
288+
onePole(data, { fc: 100, fs: 44100 })
289+
```
286290

287291
<img src="plot/one-pole.svg">
288292

293+
<details><summary>Reference</summary>
294+
295+
$y[n] = (1-a)\,x[n] + a\,y[n-1]$, $a = e^{-2\pi f_c/f_s}$, $H(z) = (1-a)/(1-az^{-1})$
296+
297+
**Use when**: smoothing control signals, sensor data, parameter changes. **Not for**: sharp cutoff (use butterworth), preserving peaks (use savitzkyGolay).
298+
**scipy**: `scipy.signal.lfilter([1-a], [1, -a])`. **MATLAB**: `filter(1-a, [1 -a], x)`.
299+
</details>
300+
289301
### `movingAverage(data, params)`
290302

291-
Boxcar average of last N samples. $h[n] = 1/N$ for $n = 0..N-1$, $H(z) = (1 - z^{-N})/(N(1 - z^{-1}))$. Excellent for removing periodic noise when N matches the period. Params: `memory`.
292-
**Linear phase · FIR · N multiplies · nulls at multiples of fs/N**
303+
Boxcar average of last N samples. Excellent for removing periodic noise when N matches the period. Params: `memory`.
304+
**Linear phase · FIR · nulls at multiples of fs/N**
305+
306+
```js
307+
movingAverage(data, { memory: 8 })
308+
```
293309

294310
<img src="plot/moving-average.svg">
295311

312+
<details><summary>Reference</summary>
313+
314+
$h[n] = 1/N$ for $n = 0..N-1$, $H(z) = (1 - z^{-N})/(N(1 - z^{-1}))$
315+
316+
**Use when**: periodic noise removal, simple averaging. **Not for**: preserving peaks (use savitzkyGolay), frequency-selective filtering.
317+
</details>
318+
296319
### `leakyIntegrator(data, params)`
297320

298-
Exponential decay accumulator. $y[n] = \lambda\,y[n-1] + (1-\lambda)\,x[n]$. Same as onePole but parameterized by decay factor $\lambda$ (0–1) instead of cutoff frequency. Params: `lambda`.
321+
Exponential decay accumulator. Same as onePole but parameterized by decay factor instead of cutoff. Params: `lambda` (0–1).
299322
**1 multiply · IIR**
300323

324+
```js
325+
leakyIntegrator(data, { lambda: 0.95 })
326+
```
327+
301328
<img src="plot/leaky-integrator.svg">
302329

303-
### `median(data, params)`
330+
<details><summary>Reference</summary>
331+
332+
$y[n] = \lambda\,y[n-1] + (1-\lambda)\,x[n]$
304333

305-
Nonlinear – replaces each sample with the median of its neighborhood. Removes impulse noise (clicks, pops, outliers) while preserving edges and steps. Used in click removal, sensor outlier rejection, image denoising. Params: `size`.
306-
**Nonlinear · no formula · preserves edges · O(N log N) per sample**
334+
**Use when**: running average, DC estimation, simple smoothing by decay factor.
335+
</details>
307336

308337
### `savitzkyGolay(data, params)`
309338

310-
Polynomial fit to sliding window – smooths noise while preserving peak height, width, and shape. The standard in spectroscopy, chromatography, and any measurement where peak distortion matters. Also computes smooth derivatives. Savitzky & Golay (1964).[^sg] Params: `windowSize`, `degree`, `derivative`.
339+
Polynomial fit to sliding window – smooths noise while preserving peak height, width, and shape. Also computes smooth derivatives. Savitzky & Golay (1964).[^sg] Params: `windowSize`, `degree`, `derivative`.
311340
**FIR · linear phase · preserves moments up to degree**
312341

313342
[^sg]: A. Savitzky, M.J.E. Golay, "Smoothing and Differentiation of Data," *Analytical Chemistry*, 1964.
314343

344+
```js
345+
savitzkyGolay(data, { windowSize: 11, degree: 3 })
346+
savitzkyGolay(data, { windowSize: 11, degree: 3, derivative: 1 }) // smooth 1st derivative
347+
```
348+
315349
<img src="plot/savitzky-golay.svg">
316350

351+
<details><summary>Reference</summary>
352+
353+
**Use when**: spectroscopy, chromatography, any measurement where peak distortion matters. **Not for**: frequency-selective filtering, causal/online processing.
354+
**scipy**: `scipy.signal.savgol_filter`. **MATLAB**: `sgolayfilt`.
355+
</details>
356+
317357
### `gaussianIir(data, params)`
318358

319-
Recursive Gaussian approximation (Young-van Vliet). O(1) cost regardless of kernel size – when sigma=100, FIR needs 600+ taps; this uses 6 multiplies. Forward-backward pass for zero phase. Params: `sigma`.
359+
Recursive Gaussian approximation (Young-van Vliet). O(1) cost regardless of kernel size – when sigma=100, FIR needs 600+ taps; this uses 6 multiplies. Forward-backward for zero phase. Params: `sigma`.
320360
**IIR · zero phase (offline) · O(1) per sample**
321361

362+
```js
363+
gaussianIir(data, { sigma: 10 })
364+
```
365+
322366
<img src="plot/gaussian-iir.svg">
323367

368+
<details><summary>Reference</summary>
369+
370+
**Use when**: large-kernel Gaussian smoothing. **Not for**: exact Gaussian (this is an approximation), causal filtering.
371+
</details>
372+
373+
### `dynamicSmoothing(data, params)`
374+
375+
Self-adjusting SVF – cutoff adapts to signal speed. Like oneEuro but at audio rate, for smoothing parameter changes without zipper noise. Params: `minFc`, `maxFc`, `sensitivity`, `fs`.
376+
**Adaptive · 2nd-order SVF**
377+
378+
```js
379+
dynamicSmoothing(data, { minFc: 1, maxFc: 5000, sensitivity: 1, fs: 44100 })
380+
```
381+
382+
<img src="plot/dynamic-smoothing.svg">
383+
384+
### `median(data, params)`
385+
386+
Nonlinear – replaces each sample with the median of its neighborhood. Removes impulse noise (clicks, pops, outliers) while preserving edges and steps. Params: `size`.
387+
**Nonlinear · preserves edges · O(N log N) per sample**
388+
389+
```js
390+
median(data, { size: 5 })
391+
```
392+
393+
<details><summary>Reference</summary>
394+
395+
**Use when**: impulse noise (clicks, pops, sensor outliers), edge-preserving denoising. **Not for**: frequency-selective filtering (no defined frequency response).
396+
**scipy**: `scipy.signal.medfilt`. **MATLAB**: `medfilt1`.
397+
</details>
398+
324399
### `oneEuro(data, params)`
325400

326-
Adaptive lowpass – cutoff increases with signal speed. Smooth at rest, responsive when moving. Used for mouse/touch/gaze input, sensor fusion. Casiez et al. (2012).[^euro] Params: `minCutoff`, `beta`, `dCutoff`, `fs`.
401+
Adaptive lowpass – cutoff increases with signal speed. Smooth at rest, responsive when moving. Casiez et al. (2012).[^euro] Params: `minCutoff`, `beta`, `dCutoff`, `fs`.
327402
**Adaptive · 1st-order IIR with time-varying cutoff**
328403

329404
[^euro]: G. Casiez et al., "1€ Filter," *CHI*, 2012.
330405

331-
### `dynamicSmoothing(data, params)`
406+
```js
407+
oneEuro(data, { minCutoff: 1, beta: 0.007, fs: 60 })
408+
```
332409

333-
Self-adjusting SVF – cutoff adapts to signal speed. Like oneEuro but at audio rate, for smoothing parameter changes without zipper noise. Params: `minFc`, `maxFc`, `sensitivity`, `fs`.
334-
**Adaptive · 2nd-order SVF with time-varying cutoff**
410+
<details><summary>Reference</summary>
335411

336-
<img src="plot/dynamic-smoothing.svg">
412+
**Use when**: mouse/touch/gaze input, sensor fusion, any UI with jitter. **Not for**: audio-rate processing (use dynamicSmoothing).
413+
</details>
337414

338415

339416
## Adaptive

0 commit comments

Comments
 (0)