Band Splitter
Tier: Core | ComponentType: 22 | Params: 7
Multiband signal splitter using chained Linkwitz-Riley 4th-order crossover filters. Supports up to 8 bands with per-band gain, solo, and guaranteed flat recombination.
Overview
BandSplitter divides an audio signal into multiple frequency bands using a cascade of CrossoverFilter instances. Each crossover splits its input into a lowpass and highpass output at a specified frequency, using Linkwitz-Riley 4th-order (LR4) topology. Chaining \(N-1\) crossovers produces \(N\) bands.
The key property of LR4 crossovers is allpass summation: when the lowpass and highpass outputs are summed, the result is a perfect allpass filter (flat magnitude, linear phase rotation). This guarantees that recombining all bands produces a flat frequency response — no comb filtering, no cancellation, no level bumps at crossover frequencies.
Each band has independent gain control (in dB) and a solo function that mutes all other bands. In the TestHarness Signal Chain mode, BandSplitter nodes act as multiband processing hubs — the signal splits into frequency bands, each band passes through its own sub-chain of effects, then bands recombine.
File Locations
| Path | |
|---|---|
| Header | Sources/FolioDSP/include/FolioDSP/Core/BandSplitter.h |
| Implementation | Sources/FolioDSP/src/Core/BandSplitter.cpp |
| Tests | Tests/FolioDSPTests/BandSplitterTests.swift |
| Bridge | Sources/FolioDSPBridge/src/FolioDSPBridge.mm (BandSplitterBridge) |
Parameters
| Index | Name | Description | Min | Max | Default Min | Default Max | Default | Unit |
|---|---|---|---|---|---|---|---|---|
| 0 | Crossover 1 | First crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 200.0 | Hz |
| 1 | Crossover 2 | Second crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 2000.0 | Hz |
| 2 | Crossover 3 | Third crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 8000.0 | Hz |
| 3 | Crossover 4 | Fourth crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 12000.0 | Hz |
| 4 | Crossover 5 | Fifth crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 15000.0 | Hz |
| 5 | Crossover 6 | Sixth crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 18000.0 | Hz |
| 6 | Crossover 7 | Seventh crossover frequency | 10.0 | 22050.0 | 20.0 | 20000.0 | 20000.0 | Hz |
Processing Algorithm
The split() function divides the input into bands, applies per-band processing, and tracks levels for visualization.
1. Crossover Cascade
For \(N\) bands, \(N-1\) crossover filters are chained. Each CrossoverFilter uses two cascaded Butterworth biquad sections to achieve LR4 (24 dB/octave) slopes:
The lowpass output of each crossover becomes a band, and the highpass output feeds the next crossover. The final highpass becomes the highest band.
2. LR4 Crossover Properties
Each CrossoverFilter implements a Linkwitz-Riley 4th-order crossover — two cascaded 2nd-order Butterworth filters:
At the crossover frequency:
The slope is 24 dB/octave, providing sharp band separation.
3. Per-Band Gain
Each band has an independent gain control in decibels, converted to linear:
where \(g_i\) is the gain in dB for band \(i\).
4. Solo
When solo is active (set to a specific band index), all other bands are zeroed:
Solo is disabled when set to 0xFF (255).
5. Level Tracking
Per-band levels are tracked via exponential smoothing for display:
6. Recombination
To recombine the bands into a single output, simply sum all bands:
The LR4 allpass property guarantees this sum is flat when all gains are at 0 dB and no solo is active.
Core Equations
Snapshot Fields
| Field | Type | Range | Unit | Description |
|---|---|---|---|---|
| Num Bands | Float | 1–8 | Current number of frequency bands | |
| Crossovers | Float[7] | 10–22050 | Hz | Active crossover frequencies |
| Band Levels | Float[8] | 0–1 | Smoothed amplitude level per band | |
| Band Gains | Float[8] | -60–60 | dB | Gain setting per band |
| Band Solo | Uint8 | 0–8 | Solo'd band index (0xFF = no solo) |
Implementation Notes
- Crossover ordering is the caller's responsibility. Crossover frequencies should be in ascending order for meaningful band separation. The component does not sort or validate ordering.
- Maximum 8 bands (7 crossovers). The
MAX_BANDSandMAX_CROSSOVERSconstants enforce this limit. All band arrays are fixed-size C arrays, not dynamically allocated. - Level tracking uses a simple exponential smoother with coefficient 0.01, giving a display-rate response suitable for bar-graph visualization.
- Multiband processing in the TestHarness: the audio callback splits the signal, processes each band through its sub-chain, then recombines. Band outputs use a stack-allocated 8-float tuple for real-time safety.
combine()is a separate method that sums a band array. It does not apply gain or solo — those are applied duringsplit().- No
process()method in the traditional sense — BandSplitter usessplit()to separate andcombine()to recombine. ThesetParameter/getParameterinterface only exposes crossover frequencies; band gains and solo are set via dedicated methods. - All crossover frequency parameters use
ParamSmoother(smoothed = true) for zipper-free adjustment. - All parameters use
std::atomic<float>for lock-free thread safety. - Snapshot emission is decimated to ~60 fps (every 735 samples at 44.1 kHz).
Equation Summary
split -> [lo..hi] -> per-band -> recombine