[fix](trx-rs): add EMA smoothing to signal strength and fix freq input clobbering
EMA (α=0.4) smooths the carrier power estimate across DSP blocks. Custom PartialEq on VchanRdsEntry excludes signal_db so rapidly-changing levels do not trigger main state SSE updates that overwrite the frequency input. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -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<f32>,
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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::<f32>() * inv_n;
|
||||
let dc_q: f32 = mixed_q.iter().sum::<f32>() * 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(
|
||||
|
||||
Reference in New Issue
Block a user