template<typename T, int MaxChannels = 8>
class dspark::Biquad< T, MaxChannels >
Biquad filter using Transposed Direct Form II (TDF-II) with thread-safe updates.
Implements a lock-free shadow buffering system (seqlock) to prevent torn reads when coefficients are updated by the UI thread concurrently with the audio thread. Per-channel states are stored compactly so adjacent channels share cache lines during block processing.
The filter core (coefficients, history and recursion) is always double precision, independent of the sample type: see the
Definition at line 555 of file Biquad.h.
template<typename T , int MaxChannels = 8>
Promotes any pending staged coefficients to active.
Real-time safe. Both processBlock() and processSample() invoke this automatically (the per-sample call is gated by a relaxed-load fast path so it is essentially free when there is no pending update).
Exposed publicly for the rare case where you have just called setCoeffs() on this same thread and want the change reflected immediately, e.g. for an offline / introspection getCoeffs() right after pushing new ones.
- Returns
- true if the active coefficients changed in this call.
Definition at line 631 of file Biquad.h.
template<typename T , int MaxChannels = 8>
Returns the active coefficient set currently in use by the DSP thread.
Intended for the thread that owns processing (or single-threaded / offline use). A GUI thread reading this concurrently with a promotion may observe a mid-update set; for drawing response curves, keep your own copy of the coefficients you computed.
Definition at line 665 of file Biquad.h.
template<typename T , int MaxChannels = 8>
Processes a full audio buffer in-place.
Thread-safe block processing. Absorbs asynchronous coefficient updates at the start of the block to ensure atomic parameter changes.
The inner loop runs on a local copy of the coefficients: with no per-sample dirty-flag check in sight, the compiler keeps b0..a2 and the filter state in registers for the whole block (roughly 1.5-2x faster than routing every sample through processSample()).
Channels beyond MaxChannels are left untouched (pass-through): only the first min(numChannels, MaxChannels) channels are filtered.
- Parameters
-
| buffer | Audio buffer to process in-place. |
Definition at line 750 of file Biquad.h.
template<typename T , int MaxChannels = 8>
| T dspark::Biquad< T, MaxChannels >::processSample |
( |
T |
input, |
|
|
int |
channel |
|
) |
| |
|
inlinenoexcept |
Processes a single sample for a specific channel.
Transposed Direct Form II implementation. Self-sufficient: any setCoeffs() update from another thread is picked up here on the very next sample with virtually zero overhead; the fast-path is a relaxed load (a plain MOV on x86) compiled into a single branchless check.
No external sequencing is required. The caller is free to mix processSample() and processBlock() calls in any order, and concurrent setCoeffs() from the GUI thread always becomes audible deterministically within at most a couple of samples (single sample on x86/ARM).
- Precondition
- channel must be in [0, MaxChannels). Enforced by assert in debug builds; out-of-range access in release builds is undefined behaviour.
- Parameters
-
| input | Input sample. |
| channel | Channel index (0-based). |
- Returns
- Filtered output sample.
Definition at line 694 of file Biquad.h.
template<typename T , int MaxChannels = 8>
| double dspark::Biquad< T, MaxChannels >::processSampleCore |
( |
double |
input, |
|
|
int |
channel |
|
) |
| |
|
inlinenoexcept |
One recursion step in the core's own precision (double).
Same filter, same state, no conversion at the boundary: a cascade calls this to keep the intermediate signal in the core precision instead of re-quantising it to T between stages (FilterEngine does). Identical contract to processSample() otherwise, including the lock-free pickup of pending coefficients.
- Precondition
- channel must be in [0, MaxChannels).
- Parameters
-
| input | Input sample. |
| channel | Channel index (0-based). |
- Returns
- Filtered output sample.
Definition at line 714 of file Biquad.h.
template<typename T , int MaxChannels = 8>
Sets the filter coefficients asynchronously.
Safely updates coefficients without locking. The audio thread will pick up the new coefficients safely on the next process call to avoid torn reads and filter blow-ups.
- Parameters
-
Definition at line 599 of file Biquad.h.