From a6c3a85c8d33ebd9fc46eca87d8d2656237c5811 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sun, 1 Mar 2026 01:31:34 +0100 Subject: [PATCH] [fix](trx-backend-soapysdr): match wfm sum/diff filter cutoffs at 18 kHz Raise both AUDIO_BW_HZ and STEREO_DIFF_BW_HZ to 18 kHz so the L+R and L-R filter paths have identical group delay across the full audio band. The previous mismatch (15.8 vs 14.5 kHz) caused frequency-dependent phase errors in the stereo matrix that degraded real-world separation. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stan Grams --- .../trx-backend/trx-backend-soapysdr/src/demod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs index 6084c83..c3f899a 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs @@ -11,14 +11,14 @@ const RDS_BPF_Q: f32 = 10.0; /// Pilot tone frequency (Hz). const PILOT_HZ: f32 = 19_000.0; /// Audio bandwidth for WFM (Hz). -/// 15.8 kHz leaves more guard band below the 19 kHz pilot and reduces -/// top-end artifacts on strong signals while still preserving the useful -/// broadcast audio range. -const AUDIO_BW_HZ: f32 = 15_800.0; +/// 18 kHz matches the diff path cutoff so both have identical group delay, +/// which is required for good stereo separation. The 19 kHz pilot is +/// removed by the notch filter on the mono path. +const AUDIO_BW_HZ: f32 = 18_000.0; /// Stereo L-R subchannel bandwidth for WFM (Hz). -/// Keep this a bit lower than the mono path because the recovered difference -/// signal is noisier and more prone to high-frequency artifacts. -const STEREO_DIFF_BW_HZ: f32 = 14_500.0; +/// Wider than the mono path to preserve high-frequency stereo detail; the +/// 19 kHz pilot is already removed by the coherent demodulation step. +const STEREO_DIFF_BW_HZ: f32 = 18_000.0; /// Q values for a proper 4th-order Butterworth cascade (two 2nd-order stages). /// Stage 1: Q = 1 / (2 cos(π/8)) const BW4_Q1: f32 = 0.5412;