diff --git a/src/trx-core/src/rig/state.rs b/src/trx-core/src/rig/state.rs index b4e88d7..b2b0efc 100644 --- a/src/trx-core/src/rig/state.rs +++ b/src/trx-core/src/rig/state.rs @@ -430,7 +430,11 @@ pub struct RdsData { } /// RDS metadata snapshot for a virtual channel. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +/// +/// `PartialEq` intentionally ignores `signal_db` so that rapidly-changing +/// signal levels do not cause the main state snapshot to diff on every poll +/// cycle (signal_db flows through the spectrum SSE instead). +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct VchanRdsEntry { /// Virtual channel UUID. pub id: Uuid, @@ -442,6 +446,12 @@ pub struct VchanRdsEntry { pub signal_db: Option, } +impl PartialEq for VchanRdsEntry { + fn eq(&self, other: &Self) -> bool { + self.id == other.id && self.rds == other.rds + } +} + /// Read-only projection of state shared with clients. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct RigSnapshot { 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 877c555..ab6ec55 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 @@ -675,12 +675,14 @@ impl ChannelDsp { // Carrier power: DC component of the mixed signal (narrow-band estimate // at the tuned frequency). Correlates with the spectrum FFT peak. + // EMA smoothing (α ≈ 0.4) for fast response with light jitter reduction. { + const SIGNAL_EMA_ALPHA: f32 = 0.4; let inv_n = 1.0 / n as f32; let dc_i: f32 = mixed_i.iter().sum::() * inv_n; let dc_q: f32 = mixed_q.iter().sum::() * inv_n; - let carrier_power = dc_i * dc_i + dc_q * dc_q; - self.last_signal_db = 10.0 * carrier_power.max(1e-12).log10(); + let carrier_db = 10.0 * (dc_i * dc_i + dc_q * dc_q).max(1e-12).log10(); + self.last_signal_db += SIGNAL_EMA_ALPHA * (carrier_db - self.last_signal_db); } self.lpf_iq.filter_block_into(