From 672f962a27ec198e687898ff49ac6f274df3f6cd Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sun, 19 Apr 2026 23:14:59 +0200 Subject: [PATCH] [fix](trx-backend-soapysdr): increase WFM S-meter attack time constant to 50 ms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With block-rate correction the 2 ms IARU attack τ saturated α to ~1.0, making the meter track raw block power with no smoothing. 50 ms gives ~3-frame settling at 30 Hz refresh — responsive but visually stable. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stan Grams --- .../trx-backend-soapysdr/src/dsp/channel.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs index 68e2df6..3b288d5 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs @@ -308,16 +308,19 @@ pub struct ChannelDsp { impl ChannelDsp { /// Compute asymmetric IIR coefficients for S-meter envelope tracking. /// - /// Attack: ~2 ms time constant (fast response to signal increase). + /// Attack: ~50 ms time constant (responsive but visually stable). /// Decay: ~300 ms time constant (slow fall for stable reading). - /// This matches the IARU Region 1 Technical Recommendation R.1 for - /// S-meter behaviour in professional receivers. + /// + /// Note: these alphas are applied once per decimated *block*, not per + /// sample, with block-rate correction (`1 − (1−α)^N`). The 50 ms + /// attack gives ~3-frame settling at 30 Hz meter refresh — fast + /// enough to follow signal changes, smooth enough to avoid jitter. fn smeter_alphas(channel_sample_rate: u32) -> (f32, f32) { if channel_sample_rate == 0 { return (0.3, 0.01); } let sr = channel_sample_rate as f32; - let attack = (1.0 - (-1.0 / (sr * 0.002)).exp()).min(1.0); // τ = 2 ms + let attack = (1.0 - (-1.0 / (sr * 0.050)).exp()).min(1.0); // τ = 50 ms let decay = (1.0 - (-1.0 / (sr * 0.300)).exp()).min(1.0); // τ = 300 ms (attack, decay) }