|
DSPark 1.6.1
Header-only audio DSP framework in pure C++20 — zero dependencies
|
Removes DC offset from audio signals with configurable filter order. More...
#include "../Core/DspMath.h"#include "../Core/Biquad.h"#include "../Core/AudioSpec.h"#include "../Core/AudioBuffer.h"#include "../Core/StateBlob.h"#include <algorithm>#include <array>#include <atomic>#include <cassert>#include <cmath>#include <cstddef>#include <cstdint>#include <numbers>#include <vector>

Go to the source code of this file.
Classes | |
| class | dspark::DCBlocker< T > |
| DC blocking filter with configurable Butterworth order (1-10). More... | |
| struct | dspark::DCBlocker< T >::OnePoleState |
| struct | dspark::DCBlocker< T >::SectionState |
| struct | dspark::DCBlocker< T >::Section |
| Second-order section: b0 * (1 - z^-1)^2 / (1 + a1 z^-1 + a2 z^-2). More... | |
Namespaces | |
| namespace | dspark |
| Main namespace for the DSPark framework. | |
Removes DC offset from audio signals with configurable filter order.
Order 1 uses a lightweight 1-pole high-pass filter (2 multiplies, 2 additions per sample). Orders 2-10 use cascaded Butterworth biquad high-pass stages with predefined Q values for maximally-flat passband response.
Numerical design (why the core is double regardless of the sample type): a DC blocker parks its poles a hair inside the unit circle - 1 - |z| is about pi*fc/(Q*fs), i.e. 1.2e-4 at 5 Hz / 192 kHz and 2.9e-5 at 768 kHz. The denominator evaluated at DC, 1 + a1 + a2 = (2 - 2*cos w0)/a0, is then a cancellation of terms of size 2 landing on 2.7e-8, well under the float resolution of the terms it is made of (1.2e-7). Measured on the float cascade this replaced, at 5 Hz: that sum rounded to 4.77e-7 at 44.1 kHz (6 % off) and to EXACTLY 0 at 192 kHz and 768 kHz, which puts a realised pole right ON the unit circle - from there every rounding error of the recursion is integrated forever instead of decaying and the "DC blocker" sources DC of its own: -0.72 measured at 768 kHz order 2 on a DC-free -6 dBFS tone (output peaking at 1.42), and a realised DC gain of -53.7 at order 4. In double the same cancellation carries an absolute error of about 2e-16, so the poles land within 1e-8 (relative) of the design instead of on the unit circle. Scalar double throughput matches float on x86-64 and ARM64, so the whole filter core runs in double and only the buffer I/O is T
The DC zero is structural on top of that: the numerator of both topologies is applied as a difference of the input history ((1 - z^-1) for the 1-pole, (1 - z^-1)^2 for the biquads, which is the exact RBJ high-pass numerator since b1 = -2*b0 and b2 = b0). A constant input therefore drives the recursion with an exact zero in IEEE arithmetic, whatever the coefficients round to, so steady DC always decays to true zero.
Dependencies: Core/DspMath.h, Core/Biquad.h, Core/AudioSpec.h, Core/AudioBuffer.h, Core/StateBlob.h.
Threading: prepare() belongs to the setup thread; the processing calls and reset() to the audio thread. setOrder()/setCutoff() are safe from any thread (atomics, applied lazily at the top of the next processing call); non-finite cutoffs are ignored. getState()/setState() are setup/UI thread.
Definition in file DCBlocker.h.