From 815efdb1ae6456b4e6ade37c21e2af658cebc075 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sun, 1 Mar 2026 01:48:16 +0100 Subject: [PATCH] [fix](trx-backend-soapysdr): match sum/diff filters and simplify stereo blend - Set STEREO_DIFF_BW_HZ = AUDIO_BW_HZ so both filter paths have identical group delay (improves multitone separation by ~10 dB). - Zero out STEREO_SEPARATION_PHASE_TRIM (unnecessary with matched filters). - Replace gradual blend ramp with binary blend: full stereo at pilot lock, mono when unlocked. The hysteresis thresholds already handle noisy signals. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stan Grams --- .../trx-backend/trx-backend-soapysdr/src/demod.rs | 13 ++++++------- 1 file changed, 6 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 fd0c82c..19974fc 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 @@ -15,9 +15,9 @@ const PILOT_HZ: f32 = 19_000.0; /// artifacts on strong signals while preserving the useful broadcast range. const AUDIO_BW_HZ: f32 = 15_800.0; /// Stereo L-R subchannel bandwidth for WFM (Hz). -/// 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; +/// Must match AUDIO_BW_HZ so the sum and diff filter paths have identical +/// group delay, which is critical for stereo separation across all frequencies. +const STEREO_DIFF_BW_HZ: f32 = AUDIO_BW_HZ; /// 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; @@ -28,7 +28,7 @@ const PILOT_NOTCH_Q: f32 = 5.0; /// Narrow 19 kHz band-pass used to derive zero-crossings for switching stereo demod. const PILOT_BPF_Q: f32 = 20.0; /// Fixed phase trim on the recovered L-R channel to compensate pilot-path delay. -const STEREO_SEPARATION_PHASE_TRIM: f32 = 0.015; +const STEREO_SEPARATION_PHASE_TRIM: f32 = 0.0; /// Fixed gain trim on the recovered L-R channel. const STEREO_SEPARATION_GAIN: f32 = 1.000; /// Extra headroom in the stereo matrix to reduce stereo-only clipping/IMD on @@ -812,10 +812,9 @@ impl WfmStereoDecoder { self.stereo_detected = true; } let stereo_blend_target = if self.stereo_detected { - let width = smoothstep01((self.stereo_detect_level - 0.30) / (0.70 - 0.30)); - 0.75 + 0.25 * width + 1.0 } else { - 0.35 * smoothstep01((self.stereo_detect_level - 0.10) / (0.30 - 0.10)) + 0.0 }; // --- RDS ---