You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
let sos =butterworth(4, 1000, 44100) // 4th-order lowpass at 1 kHz
35
-
filter(data, { coefs: sos }) // apply to data in-place
36
-
```
37
-
38
30
```js
39
31
// Individual imports:
40
32
importnlmsfrom'digital-filter/adaptive/nlms.js'
41
33
42
-
// Cancel echo: feed far-end and microphone, get clean signal
34
+
// Cancel echo: feed far-end and microphone arrays, get clean signal
43
35
let params = { order:512, mu:0.5 }
44
36
nlms(farEnd, microphone, params)
45
37
let clean =params.error
@@ -49,16 +41,33 @@ let clean = params.error
49
41
> For audio-domain filters (weighting, EQ, synth, measurement) see [audio-filter](https://github.com/audiojs/audio-filter).
50
42
51
43
52
-
## Reading the plots
44
+
## Intro
45
+
46
+
**What is a filter?** Takes an array of samples, outputs an array of samples. `output[i] = (input[i] + input[i-1] + input[i-2]) / 3` is a filter – it smooths out fast changes. That's a lowpass.
47
+
48
+
**What is frequency response?** Every filter passes some frequencies and cuts others. The plots show how much each frequency is kept (magnitude, in dB) and how much it's delayed (phase, in degrees). 0dB = unchanged, –3dB = half power.
49
+
50
+
**What is IIR vs FIR?** IIR uses feedback (output depends on previous output). Few multiplies, low latency, but can't do linear phase and can blow up. FIR has no feedback – always stable, linear phase possible, but needs many taps (100–1000+) for a sharp cutoff, which can tax on performance.
51
+
52
+
**What is SOS?** Second-Order Sections – an IIR filter split into a chain of biquads (2nd-order, 5 coefficients each). A 4th-order Butterworth = 2 biquads. All design functions in this library return SOS arrays. This avoids the precision loss that happens with high-order polynomials in float64.
53
+
54
+
**How to read the plots?** Four panels per filter. Top-left: magnitude (dB vs Hz). Top-right: phase (degrees vs Hz). Bottom-left: group delay (samples vs Hz) – flat means no distortion. Bottom-right: impulse response. Dashed line = cutoff $f_c$.
55
+
56
+
**How to design and apply a filter?** Design functions return coefficients (SOS array or Float64Array). Pass them to `filter()` to process data in-place. State persists in `params` between calls for block processing.
57
+
58
+
```js
59
+
let sos =butterworth(4, 1000, 44100) // design: 4th-order lowpass at 1 kHz
60
+
filter(data, { coefs: sos }) // apply: modifies data in-place
53
61
54
-
Each filter shows four panels.
55
-
**Magnitude** (top-left) – how much of each frequency passes through, in dB. 0 dB = unchanged, –3 dB = half power (the conventional cutoff), –40 dB = 1%.
56
-
**Phase** (top-right) – how much each frequency is delayed in degrees. Constant slope = linear phase = waveform preserved. **Group delay** (bottom-left) – the derivative of phase; shows delay variation across frequency in samples. Flat = no distortion.
57
-
**Impulse response** (bottom-right) – the filter's output when fed a single 1-sample pulse; its "fingerprint."
62
+
// seamless processing
63
+
let params = { coefs:butterworth(4, 1000, 44100) }
64
+
filter(block1, params) // state preserved
65
+
filter(block2, params) // seamless continuation
66
+
```
58
67
59
-
The formulas describe the filter's frequency response. $|H(j\omega)|^2$ is the squared magnitude as a function of analog frequency $\omega$ – it defines the shape of the passband/stopband. $H(z)$ is the digital transfer function – what the code computes per sample. $h[n]$ is the impulse response – the FIR coefficients directly.
68
+
**How to read the plots?** Four panels per filter. Top-left: magnitude (dB vs Hz). Top-right: phase (degrees vs Hz). Bottom-left: group delay (samples vs Hz) – flat means no distortion. Bottom-right: impulse response. Dashed line = cutoff $f_c$.
60
69
61
-
The dashed vertical line marks the cutoff frequency $f_c$.
70
+
**How to read the formulas?** $|H(j\omega)|^2$: how the analog prototype shapes magnitude. $H(z)$: what the code computes per sample. $h[n]$: the impulse response / FIR coefficients.
62
71
63
72
64
73
## IIR
@@ -546,21 +555,15 @@ Analog prototype → digital SOS pipeline. `transform.polesSos(poles, fc, fs, ty
546
555
547
556
## FAQ
548
557
549
-
**What is a filter?** A system that takes samples in and produces samples out. It does something in time (averaging, delaying) that corresponds to something in frequency (passing, cutting, boosting). The **magnitude response** shows how much of each frequency passes through.
550
-
551
-
**What is the dB scale?** Logarithmic ratio. $\text{dB} = 20\log_{10}(\text{ratio})$. 0 dB = unchanged, –3 dB = half power (the conventional cutoff), –6 dB = half amplitude, –20 dB = 10%, –60 dB = 0.1%.
552
-
553
-
**What are phase and group delay?** Magnitude tells you *how much* passes, phase tells you *when* it arrives. If all frequencies are delayed equally the waveform is preserved (**linear phase**). **Group delay** measures the delay per frequency. Constant group delay = linear phase. FIR can have linear phase; IIR cannot.
554
-
555
-
**IIR vs FIR?** IIR uses feedback – efficient (5–20 multiplies), low latency, nonlinear phase, can be unstable. FIR has no feedback – always stable, linear phase possible, needs 100–1000+ taps. Use IIR for real-time, FIR for offline or when linear phase is required.
558
+
**What does the dB scale mean?** $\text{dB} = 20\log_{10}(\text{ratio})$. 0 dB = unchanged, –3 dB = half power, –6 dB = half amplitude, –20 dB = 10%, –60 dB = 0.1%.
556
559
557
-
**What are biquads and SOS?**The biquad is a 2nd-order filter with 5 coefficients. Every higher-order IIR is a cascade of biquads (**second-order sections**). Direct form above order ~6 loses precision with float64; SOS doesn't. This library returns SOS arrays by default.
560
+
**When does phase matter?**When waveform shape must be preserved: crossovers (drivers must sum correctly), biomedical (ECG/EEG morphology), communications (intersymbol interference). For EQ, phase is usually inaudible.
558
561
559
-
**What is the bilinear transform?** Maps analog filter prototypes to digital: $s = (2/T)(z-1)/(z+1)$. All IIR design functions prewarp automatically – the cutoff you specify is the cutoff you get.
562
+
**What is the bilinear transform?** Maps analog prototypes to digital: $s = (2/T)(z-1)/(z+1)$. All IIR design functions prewarp automatically – the cutoff you specify is the cutoff you get.
560
563
561
-
**When is a filter unstable?** When poles move outside the unit circle. Causes: coefficient quantization (use SOS, not direct form), careless parameter changes (Q → 0), feedback gain too high. Check with `isStable(sos)`. FIR is always stable.
564
+
**When can a filter become unstable?** When poles move outside the unit circle. Causes: coefficient quantization (use SOS, not direct form), Q approaching 0, feedback gain too high. Check with `isStable(sos)`. FIR is always stable.
562
565
563
-
**What is aliasing?**A digital system at sample rate $f_s$ can represent frequencies up to $f_s/2$ (Nyquist). Frequencies above Nyquist fold back as artifacts. `decimate` and `interpolate` handle anti-aliasing automatically.
566
+
**What is aliasing?**Frequencies above $f_s/2$ (Nyquist) fold back as artifacts. `decimate` and `interpolate` handle anti-aliasing automatically.
0 commit comments