Crossover Filter Design & Multi-Driver Speaker Tuning#
The Sound Open Firmware (SOF) Crossover component provides high-precision digital frequency-splitting filters designed to partition full-bandwidth audio into discrete acoustic bands for multi-driver loudspeaker systems (such as subwoofers, woofers, midranges, squawkers, and tweeters). By separating frequencies before power amplification, the crossover filter enables active multi-amplification architectures, eliminates bulky and lossy passive analog crossover networks, drastically reduces intermodulation distortion, and protects delicate high-frequency transducers from damaging low-frequency excursion.
This guide details the mathematical foundations of SOF’s Linkwitz-Riley 4th-order (LR4) filters, the recursive filter tree architectures for 2-way, 3-way, and 4-way systems, the innovative all-pass phase-alignment merge mechanism, the fixed-point Q2.30 DSP implementation, Topology 2 multi-sink pipeline routing, offline GNU Octave calibration workflows, live runtime parameter injection via sof-ctl, and acoustic diagnostic troubleshooting.
Theoretical Foundations of Crossover Filters#
Active digital crossovers divide an input signal \(x(n)\) into \(N\) frequency bands such that the acoustic summation of all driver outputs reproduces the original input signal with minimal magnitude ripple, linear phase behavior, and zero polar lobing tilt in the listening window.
Butterworth vs. Linkwitz-Riley Topologies#
Standard Butterworth filters of order \(N\) exhibit maximally flat passbands with a \(-3.01\text{ dB}\) attenuation at their cutoff frequency \(\omega_c\):
When two complementary Butterworth filters (low-pass and high-pass) are summed in phase, their power response sums to unity, but their voltage magnitude response exhibits a \(+3\text{ dB}\) resonant peak at the crossover frequency:
This \(+3\text{ dB}\) peak produces audible acoustic boominess, coloration, and severe driver strain at the crossover boundary.
To eliminate magnitude peaking, Linkwitz and Riley demonstrated that cascading two identical Butterworth filters of order \(N/2\) in series creates an even-order filter whose cutoff attenuation is exactly \(-6.02\text{ dB}\):
When summed in phase, the combined magnitude response is perfectly flat across the entire audio spectrum:
Table 38 compares common crossover filter topologies.
Filter Type & Order |
Roll-Off Slope |
Cutoff Level (\(F_c\)) |
Summed Magnitude |
Phase at \(F_c\) |
Polar Lobe Tilt |
|---|---|---|---|---|---|
Butterworth 2nd (BW2) |
-12 dB/oct |
-3.01 dB |
Flat (if inverted) |
\(180^\circ\) shift |
Off-axis tilt |
Linkwitz-Riley 2nd (LR2) |
-12 dB/oct |
-6.02 dB |
Flat (if inverted) |
\(180^\circ\) shift |
On-axis symmetric |
Butterworth 3rd (BW3) |
-18 dB/oct |
-3.01 dB |
Flat magnitude |
\(90^\circ\) quadrature |
Asymmetric tilt |
Butterworth 4th (BW4) |
-24 dB/oct |
-3.01 dB |
+3.01 dB peak |
\(180^\circ\) shift |
Severe peaking |
Linkwitz-Riley 4th (LR4) |
-24 dB/oct |
-6.02 dB |
0.00 dB (Flat) |
In-Phase (\(0^\circ / 360^\circ\)) |
Zero tilt (On-axis) |
Mathematical Formulation of Linkwitz-Riley 4th-Order (LR4)#
The SOF Crossover engine exclusively implements Linkwitz-Riley 4th-order (LR4) filters because they provide three indispensable electro-acoustic properties:
Zero Magnitude Peaking: The summed voltage transfer function forms an all-pass network with an exact 0.00 dB magnitude response:
\[|H_{\text{LP,LR4}}(j\omega) + H_{\text{HP,LR4}}(j\omega)| = 1.00 \quad \forall \omega\]Phase Coherence & Zero Lobing Tilt: The low-pass and high-pass outputs are precisely in phase (\(\Delta\phi = 0^\circ\) or \(360^\circ\)) at all frequencies. As a consequence, the constructive acoustic interference lobe is directed exactly perpendicular to the speaker baffle (on-axis) without vertical acoustic tilt.
Steep Transducer Isolation (-24 dB/octave): An attenuation rate of \(-24\text{ dB/octave}\) (or \(-80\text{ dB/decade}\)) rapidly suppresses out-of-band energy, protecting fragile micro-tweeter voice coils from low-frequency excursion damage while mitigating cone breakup resonance modes in woofers.
In the continuous Laplace domain (\(s\)), an LR4 low-pass filter with angular cutoff frequency \(\omega_c = 2\pi F_c\) is defined as the square of a 2nd-order Butterworth filter:
Similarly, the complementary LR4 high-pass filter is:
Summing the two transfer functions yields:
Evaluating along the imaginary axis \(s = j\omega\):
The sum is an all-pass network with unity gain and a phase rotation of \(-360^\circ\) across the frequency spectrum.
Bilinear Transform & Digital Biquad Realization#
To execute the LR4 filter inside the SOF DSP audio processing pipeline at sampling frequency \(f_s\), the continuous transfer function is mapped to the discrete \(z\)-domain via the Bilinear Transform with frequency pre-warping:
To preserve the exact analog cutoff frequency \(F_c\) in the digital domain, the continuous cutoff is pre-warped:
Each 4th-order filter is factored into a cascade of two identical 2nd-order Direct-Form I (DF1) biquad sections:
For a 2nd-order Butterworth low-pass stage with resonance \(Q = 1/\sqrt{2} \approx 0.7071\), let normalized cutoff \(\theta = \frac{\pi F_c}{f_s}\):
The resulting discrete low-pass biquad coefficients are:
For the complementary high-pass biquad stage, let \(\alpha_{\text{HP}} = \frac{1}{4} (0.5 + \beta + \gamma)\):
Figure 251 Figure 263: Linkwitz-Riley LR4 (-24 dB/oct) Acoustic Magnitude and Phase Response. Note the exact -6.02 dB level at \(F_c\), the 0.00 dB flat acoustic summation across the spectrum, and the absence of the +3.01 dB peak characteristic of Butterworth 4th-order filters.#
Filter Tree Topologies & The Phase Asymmetry Solution#
SOF supports 2-way, 3-way, and 4-way crossover configurations. While 2-way and 4-way systems possess natural structural symmetry, 3-way systems present an inherent acoustic phase challenge that SOF resolves through an innovative all-pass merge block.
Figure 252 Figure 262: SOF Crossover Filter Tree Topologies. (1) Two-way symmetrical split; (2) Three-way split with all-pass LR4 phase-alignment merge block on the LOW branch; (3) Four-way symmetrical binary tree with natural 8-pole group delay parity.#
Two-Way Crossover Topology#
In a 2-way configuration (such as a separate woofer and tweeter), the input signal \(x(n)\) is split by a single LR4 filter pair at crossover frequency \(F_{c,\text{low}}\):
LOW Output (
assign_sink[0]): Filtered by LR4 LP0 (\(F_{c,\text{low}}\)), routing bass and lower-midrange energy to the woofer.HIGH Output (
assign_sink[1]): Filtered by LR4 HP0 (\(F_{c,\text{low}}\)), routing upper-midrange and treble energy to the tweeter.
Because both outputs traverse exactly one LR4 filter (consisting of two cascaded biquads, or 4 poles), both paths experience identical group delay and phase lag (\(-360^\circ\) rotation across the band). When acoustically radiated, the outputs sum with zero phase cancellation.
Three-Way Crossover & The Phase Alignment Problem#
In a traditional 3-way crossover (woofer, midrange, tweeter), the input is partitioned using two cutoff frequencies: \(F_{c,\text{low}}\) (e.g. 250 Hz) and \(F_{c,\text{high}}\) (e.g. 2500 Hz).
In an intuitive asymmetric tree:
The input \(x(n)\) is first split at \(F_{c,\text{low}}\) into a low-frequency signal \(z_1\) (via LP0) and a high-frequency signal \(z_2\) (via HP0).
The high signal \(z_2\) is then split at \(F_{c,\text{high}}\) into a midrange signal (via LP2) and a treble signal (via HP2).
The Phase Asymmetry Flaw#
Under this naive architecture:
The Midrange and Tweeter branches have traversed two sequential LR4 filters (LP0 followed by LP2/HP2), totaling 8 poles and experiencing a \(-720^\circ\) phase rotation.
The Woofer branch \(z_1\) has traversed only one LR4 filter (LP0), totaling 4 poles and experiencing only \(-360^\circ\) of phase rotation.
At the crossover boundary \(F_{c,\text{low}}\), the woofer output and the midrange output are out of phase by \(360^\circ\) relative to higher bands, creating severe group delay disparity, smearing transients, and causing deep destructive notches in the acoustic radiation pattern if listener alignment is slightly off-axis.
The SOF LR4 Merge Solution#
To eliminate this phase asymmetry, SOF introduces an All-Pass Phase-Equalization Merge Block on the LOW branch (implemented in crossover_generic_split_3way() in crossover_generic.c).
The low-frequency signal \(z_1\) is routed through a secondary pair of LR4 filters tuned to \(F_{c,\text{high}}\) (LP1 and HP1), and their outputs are algebraically summed back together before reaching the woofer sink:
Because the sum of an LR4 low-pass and high-pass filter is an all-pass network:
The magnitude spectrum of the woofer signal is completely unaffected (0.00 dB alteration). However, passing through the LP1/HP1 network injects an exact 4-pole phase lag and group delay matching the secondary filter stage of the midrange and tweeter paths!
As a result, all three outputs (LOW, MID, HIGH) traverse exactly 8 poles (4 biquads), achieving perfect group delay parity and phase alignment across all three drivers.
Four-Way Crossover Topology#
In a 4-way system (subwoofer, woofer, squawker/midrange, tweeter), SOF implements a symmetrical binary tree with three crossover frequencies: \(F_{c,\text{low}}\), \(F_{c,\text{mid}}\), and \(F_{c,\text{high}}\):
Root Split: Input \(x(n)\) is split at \(F_{c,\text{mid}}\) by LR4 LP1 and HP1 into low group \(z_1\) and high group \(z_2\).
Low-Band Split: \(z_1\) is split at \(F_{c,\text{low}}\) by LR4 LP0 and HP0 into
assign_sink[0](Subwoofer) andassign_sink[1](Woofer).High-Band Split: \(z_2\) is split at \(F_{c,\text{high}}\) by LR4 LP2 and HP2 into
assign_sink[2](Midrange) andassign_sink[3](Tweeter).
Every output path naturally traverses exactly two LR4 stages (8 poles, 4 biquads). No merge block is required, and all 4 paths maintain identical group delay.
Firmware Architecture & Fixed-Point Implementation#
The SOF Crossover component (src/audio/crossover/) operates as a multi-sink module adapter plugin.
Firmware Data Structures#
The user configuration blob is defined in include/user/crossover.h:
#define SOF_CROSSOVER_MAX_STREAMS 4
struct sof_crossover_config {
uint32_t size; /* Total blob size in bytes */
uint32_t num_sinks; /* Number of output streams (2, 3, or 4) */
uint32_t reserved[4]; /* Reserved for 64-bit alignment */
uint32_t assign_sink[SOF_CROSSOVER_MAX_STREAMS];/* Sink pipeline ID (IPC3) or output pin index (IPC4) */
struct sof_eq_iir_biquad coef[]; /* Cascaded LR4 biquad coefficients */
} __attribute__((packed));
Each biquad is defined by struct sof_eq_iir_biquad (from include/user/eq.h):
struct sof_eq_iir_biquad {
int32_t a2; /* Q2.30 - Recursive feedback coefficient y[n-2] */
int32_t a1; /* Q2.30 - Recursive feedback coefficient y[n-1] */
int32_t b2; /* Q2.30 - Feedforward coefficient x[n-2] */
int32_t b1; /* Q2.30 - Feedforward coefficient x[n-1] */
int32_t b0; /* Q2.30 - Feedforward coefficient x[n] */
int32_t output_shift; /* Right-shift count (negative indicates left shift) */
int32_t output_gain; /* Q2.14 - Linear output post-gain multiplier (16384 = unity 1.0) */
} __attribute__((packed));
Fixed-Point Q-Format Specifications (Table 39)#
To ensure deterministic real-time processing on fixed-point DSP architectures (such as Tensilica HiFi 3, HiFi 4, and HiFi 5), all coefficients are quantized according to Table 39.
Struct Field |
Q-Format |
Dynamic Range |
Resolution & Description |
|---|---|---|---|
|
Q32.0 (uint) |
\([0, 1024]\) |
Total payload size in bytes including headers |
|
Q32.0 (uint) |
\(2, 3, \text{or } 4\) |
Number of split frequency sinks enabled |
|
Q32.0 (uint) |
\([0, 3]\) |
Output pin index (IPC4) or pipeline ID (IPC3) |
|
Q2.30 (signed) |
\([-2.0, +1.999999998]\) |
Feedforward numerator biquad coefficients; \(\text{LSB} = 2^{-30} \approx 9.31 \times 10^{-10}\) |
|
Q2.30 (signed) |
\([-2.0, +1.999999998]\) |
Feedback denominator biquad coefficients (negated in firmware difference equation) |
|
Q32.0 (signed) |
\(0\) (nominal) |
Post-biquad bit shift count for headroom management |
|
Q2.14 (signed) |
\([0, 32767]\) |
Post-biquad linear scaling factor; \(16384 = 1.000\) (unity gain) |
Firmware Execution Engine#
Figure 253 Figure 265: SOF Crossover Firmware Execution Engine. Per-channel Direct-Form I biquad processing loop with 64-bit accumulators, saturation protection, and multi-sink buffer scatter.#
Each channel maintains an independent filter state struct:
struct crossover_state {
struct iir_state_df1 lowpass[CROSSOVER_MAX_LR4]; /* Low-pass filter delay lines */
struct iir_state_df1 highpass[CROSSOVER_MAX_LR4]; /* High-pass filter delay lines */
};
During each processing period:
Input samples are read from the upstream buffer in 32-bit Q1.31 format.
The dynamic split function pointer (
cd->crossover_split) routes the sample through the configured LR4 tree.In each LR4 biquad stage, the Direct-Form I difference equation is computed using 64-bit precision:
\[y(n) = \text{sat}_{32}\left( \left[ \sum_{k=0}^2 b_k x(n-k) - \sum_{k=1}^2 a_k y(n-k) \right] \gg 30 \right)\]The resulting split samples \(\text{out}[0 \dots N-1]\) are written to their respective downstream sink buffers (
bsinks[j]) with appropriate bit-depth scaling and rounding.Inactive or disconnected sinks are gracefully bypassed without pipeline stalls.
Topology 2 & IPC4 Multi-Sink Architecture#
In modern SOF systems running IPC4, the Crossover component is defined as an effect widget with 1 input pin and up to 4 output pins.
Topology 2 Widget Definition (crossover.conf)#
Class.Widget."crossover" {
DefineAttribute."index" { type "integer" }
DefineAttribute."instance" { type "integer" }
<include/components/widget-common.conf>
attributes {
!constructor [ "index" "instance" ]
!mandatory [
"num_input_pins"
"num_output_pins"
"num_input_audio_formats"
"num_output_audio_formats"
]
!immutable [ "uuid" "type" ]
unique "instance"
}
uuid "d1:9a:8c:94:6a:80:31:41:ad:6c:b2:bd:a9:e3:5a:9f"
type "effect"
no_pm "true"
num_input_pins 1
}
IPC4 Multi-Output Binding Pipeline#
Figure 264 shows a representative 2-way playback topology with independent power amplifier DAIs (SSP0 for Woofer and SSP2 for Tweeter).
Figure 254 Figure 264: Topology 2 Multi-Sink Pipeline Architecture and IPC4 Output Pin Binding. Wideband PCM playback is ingested by Pipeline 1, split into Woofer and Tweeter streams by crossover.1.1, and routed via Output Pins 0 and 1 to downstream DAI copiers SSP0 and SSP2.#
In cavs-nocodec-crossover.conf, the crossover widget declares two output pins bound to independent sink pipelines:
Object.Widget.crossover [
{
index 1
name "crossover.1.1"
num_input_audio_formats 1
Object.Base.input_audio_format.1 {
input_pin_index 0
in_bit_depth 32
in_valid_bit_depth 32
}
num_output_pins 2
num_output_audio_formats 2
Object.Base.output_audio_format {
1 {
output_pin_index 0
out_bit_depth 32
out_valid_bit_depth 32
}
2 {
output_pin_index 1
out_bit_depth 32
out_valid_bit_depth 32
}
}
Object.Base.output_pin_binding.1 {
output_pin_binding_name "dai-copier.SSP.NoCodec-0.playback"
}
Object.Base.output_pin_binding.2 {
output_pin_binding_name "dai-copier.SSP.NoCodec-2.playback"
}
Object.Control.bytes."1" {
name "crossover.1.1_bytes_control"
IncludeByKey.EFX_CROSSOVER_PARAMS {
"2way" "include/components/crossover/coef_2way_48000_200_0_1.conf"
"3way" "include/components/crossover/coef_3way_48000_200_1000_0_1_2.conf"
"4way" "include/components/crossover/coef_4way_48000_200_1000_3000_0_1_2_3.conf"
}
}
}
]
Note
In IPC4 firmware manifests (crossover.toml), init_config = 1 is required so that the kernel driver appends base_cfg_ext to the IPC initialization message. This extension supplies nb_output_pins and the pin index array, allowing the firmware to bind sink channels correctly.
Offline Filter Synthesis & Calibration Toolchain#
SOF provides an in-tree GNU Octave / MATLAB toolchain in src/audio/crossover/tune/ that automates the calculation of continuous analog Butterworth filters, bilinear transformation with pre-warping, fixed-point coefficient quantization, all-pass phase-merge insertion, and multi-target serialization.
Figure 255 Figure 266: End-to-End Crossover Tuning, Offline Synthesis, and Live Injection Toolchain. Complete toolchain from physical acoustic profiling to GNU Octave synthesis, multi-target packaging, and runtime parameter injection via sof-ctl.#
Octave Script Walkthrough#
The central synthesis driver is sof_example_crossover.m:
function sof_example_crossover()
cr.fs = 48e3; % Sample rate: 48 kHz
cr.fc_low = 2200; % Crossover frequency: 2200 Hz
cr.num_sinks = 2; % 2-way crossover
cr.sinks = [0 1]; % Output pin 0 (Woofer), Output pin 1 (Tweeter)
export_crossover(cr);
end
The synthesis pipeline executes the following stages:
Coefficient Synthesis (
sof_crossover_gen_coefs.m): Computes the analog 2nd-order Butterworth coefficients and applies the bilinear transform with frequency pre-warping:crossover = sof_crossover_gen_coefs(cr.fs, cr.fc_low);
Fixed-Point Quantization (
sof_crossover_coef_quant.m): Quantizes continuous coefficients into 32-bit Q2.30 integers and appends shift/gain values:crossover_bqs = sof_crossover_coef_quant(crossover.lp, crossover.hp);
Configuration Struct Assembly (
sof_crossover_generate_config.m): Interleaves low-pass and high-pass biquads into the canonical sequence:[LP0, HP0, LP1, HP1, LP2, HP2].Binary Blob Construction (
sof_crossover_build_blob.m): Packs thesof_abi_hdrand configuration struct into little-endian binary bytes.Multi-Target Artifact Export: Exports configuration data into three production targets:
Topology 2:
sof_tplg2_write(conf_path, blob, 'crossover_config', 'Exported Control Bytes')UCM2 Profile:
sof_ucm_blob_write(bin_path, blob)ALSA State:
sof_alsactl_write(txt_path, blob)
Frequency & Phase Plot Verification (
sof_crossover_plot_freq.m): Plots magnitude and unwrapped phase responses to visually confirm 0.00 dB acoustic summation.
Production Acoustic Tuning Presets#
Below are three validated production preset configurations designed for real-world acoustic hardware.
Preset 1: 2-Way Laptop Woofer/Tweeter Split#
Target Hardware: Ultra-thin laptop with separate bottom-firing micro-woofers and top-firing silk dome tweeters.
Acoustic Rationale: Micro-tweeters suffer non-linear distortion and thermal runaway if driven below 1800 Hz. The 2200 Hz crossover protects the tweeter while maintaining smooth off-axis dispersion.
Parameter |
Value |
Unit / Format |
Acoustic Justification |
|---|---|---|---|
|
48000 |
Hz |
Standard high-definition audio clock |
|
2 |
Integer |
2-way split (Woofer + Tweeter) |
|
2200 |
Hz |
\(> 2 \times F_s\) of tweeter (resonance \(\approx 1000\text{ Hz}\)) |
|
LR4 (-24 dB/oct) |
Architecture |
Cascaded DF1 biquads with -6.02 dB crossover point |
|
0 |
Pin Index |
Low band to Woofer amplifier (SSP0) |
|
1 |
Pin Index |
High band to Tweeter amplifier (SSP2) |
|
2 |
Sections |
LP0 (2 biquads) and HP0 (2 biquads) |
Preset 2: 3-Way Conference Speaker / Soundbar#
Target Hardware: Smart conference speakerphone or television soundbar with dedicated subwoofer, stereo midrange drivers, and dual high-frequency tweeters.
Acoustic Rationale: Low crossover at 250 Hz isolates bass vibrations from vocal clarity; high crossover at 2800 Hz keeps directional treble crisp. All-pass merge block preserves perfect speech intelligibility across the band.
Parameter |
Value |
Unit / Format |
Acoustic Justification |
|---|---|---|---|
|
48000 |
Hz |
Standard teleconferencing clock |
|
3 |
Integer |
3-way split (Bass + Vocal Mid + Treble) |
|
250 |
Hz |
Subwoofer/Woofer acoustic boundary |
|
2800 |
Hz |
Midrange/Tweeter acoustic boundary |
|
Enabled |
Architecture |
LP1/HP1 at 2800 Hz merged on LOW path (8-pole parity) |
|
0 |
Pin Index |
Subwoofer amplifier sink |
|
1 |
Pin Index |
Midrange driver amplifier sink |
|
2 |
Pin Index |
High-frequency tweeter amplifier sink |
Preset 3: 4-Way High-Fidelity Studio Monitor#
Target Hardware: Active 4-way reference studio monitor (Subwoofer + Mid-Bass Woofer + Dome Midrange + Ribbon Tweeter).
Acoustic Rationale: Full-range linear reproduction from 20 Hz to 20 kHz. Symmetrical binary tree provides identical 8-pole group delay across all four acoustic bands.
Parameter |
Value |
Unit / Format |
Acoustic Justification |
|---|---|---|---|
|
48000 |
Hz |
Studio reference clock |
|
4 |
Integer |
Subwoofer, Low-Mid, High-Mid, Tweeter |
|
100 |
Hz |
Sub-bass excursion boundary |
|
800 |
Hz |
Primary vocal fundamental boundary |
|
3500 |
Hz |
Ribbon tweeter protection boundary |
|
0, 1, 2, 3 |
Pin Indices |
Mapped to DAIs 0, 1, 2, 3 respectively |
|
Exactly 8 poles |
Verification |
Zero group delay skew between any driver pair |
Live Runtime Injection & Calibration Runbook#
The SOF Crossover component allows live, glitch-free coefficient updating over the network without stopping the audio stream or rebooting the device under test (DUT).
Step 1: Enumerate Active Crossover Byte Controls#
Query the ALSA mixer on the target DUT to locate the Crossover byte control:
# Connect to DUT over SSH and inspect controls
ssh root@<dut> "amixer -Dhw:0 controls | grep -i crossover"
Expected output:
numid=14,iface=MIXER,name='crossover.1.1_bytes_control'
Step 2: Synthesize New Coefficients in GNU Octave#
On the host development workstation, launch GNU Octave and synthesize a new crossover profile (e.g. testing an alternative 2500 Hz cutoff):
cd ~/work/sof/src/audio/crossover/tune/
cr.fs = 48e3;
cr.fc_low = 2500;
cr.num_sinks = 2;
cr.sinks = [0 1];
export_crossover(cr);
This generates ../../../../tools/ctl/ipc4/crossover/coef_2way.bin.
Step 3: Inject the Binary Blob via sof-ctl#
Transfer and inject the binary blob directly into the running DSP pipeline:
# Copy blob to DUT
scp tools/ctl/ipc4/crossover/coef_2way.bin root@<dut>:/tmp/crossover_new.bin
# Inject blob into ALSA control numid 14 using IPC4 Large Config Set
ssh root@<dut> "sof-ctl -Dhw:0 -i 4 -n 14 -p 0 -b -s /tmp/crossover_new.bin"
Step 4: Verify Active Coefficients & DSP Trace Logs#
Verify that the DSP processed and applied the new coefficients:
# Read back active coefficients from DSP memory
ssh root@<dut> "sof-ctl -Dhw:0 -i 4 -n 14 -p 0 -r -o /tmp/crossover_readback.bin"
# Verify byte-level integrity
ssh root@<dut> "cmp /tmp/crossover_new.bin /tmp/crossover_readback.bin && echo 'COEFFICIENTS MATCH'"
Inspect the firmware trace stream:
ssh root@<dut> "mtrace | grep -i crossover"
Expected DSP log output:
crossover crossover.1.1: crossover_init_coef_ch: num_sinks = 2
crossover crossover.1.1: LR4 LP0 b0=0x00a12b40 b1=0x01425680 b2=0x00a12b40 a1=0x831a2c00 a2=0x38b29000
crossover crossover.1.1: configuration applied successfully (no stream interruption)
Acoustic Diagnostics & Troubleshooting Matrix#
Table 43 provides diagnostic procedures for resolving acoustic anomalies and runtime configuration issues during crossover tuning.
Symptom / Artifact |
Root Cause |
Diagnostic Check |
Corrective Action |
|---|---|---|---|
Deep acoustic notch at \(F_c\) (\(-12\text{ to } -30\text{ dB}\)) |
Drivers wired with inverted acoustic polarity or off-axis phase cancellation |
Measure on-axis acoustic frequency sweep with measurement mic |
Invert electrical polarity of one driver or ensure LR4 filters are used (which are in-phase). |
Tweeter distortion / premature failure |
Crossover frequency \(F_c\) set too close to tweeter mechanical resonance \(F_s\) |
Impedance sweep showing resonance peak \(F_s\) |
Increase \(F_c\) such that \(F_c \ge 2 \times F_s\). Verify -24 dB/oct slope. |
Vocal smearing in 3-way system |
Phase asymmetry between Woofer and Midrange branches |
Group delay calculation in GNU Octave |
Verify all-pass merge block is enabled ( |
High-frequency harshness / breakup |
Woofer cone breakup frequencies leaking past crossover |
Measure individual woofer near-field frequency response |
Lower \(F_c\) or insert a notch filter in upstream Parametric EQ ( |
Audio glitch / zipper noise on parameter injection |
Instantaneous coefficient update causing state buffer discontinuity |
Check |
Ensure coefficient injection occurs with ramped gain or when signal is quiescent. |
DSP pipeline underflow / XRUN |
Downstream sink pipelines consuming samples at mismatched rates |
Inspect ALSA XRUN counters ( |
Ensure all output DAIs are synchronized to the same common hardware clock domain. |
Upstream Firmware References#
The SOF Crossover implementation and tuning scripts reside in the upstream repository:
DSP Processing Core: src/audio/crossover/crossover.c
Filter Kernels & Split Logic: src/audio/crossover/crossover_generic.c
IPC4 Adapter & Pin Initialization: src/audio/crossover/crossover_ipc4.c
User Configuration Header: src/include/user/crossover.h
Common Crossover Header: src/include/module/crossover/crossover_common.h
GNU Octave Tuning Scripts: src/audio/crossover/tune/
Topology 2 Component Definition: tools/topology/topology2/include/components/crossover.conf