[feat](trx-backend-soapysdr): add adaptive wfm stereo blend
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -100,6 +100,12 @@ fn polyphase_resample(
|
|||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn smoothstep01(x: f32) -> f32 {
|
||||||
|
let x = x.clamp(0.0, 1.0);
|
||||||
|
x * x * (3.0 - 2.0 * x)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct OnePoleLowPass {
|
struct OnePoleLowPass {
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
@@ -545,13 +551,13 @@ impl WfmStereoDecoder {
|
|||||||
let pilot_abs = self.pilot_abs_lp.process(pilot_tone.abs());
|
let pilot_abs = self.pilot_abs_lp.process(pilot_tone.abs());
|
||||||
let pilot_coherence = (pilot_mag / (pilot_abs + 1e-4)).clamp(0.0, 1.0);
|
let pilot_coherence = (pilot_mag / (pilot_abs + 1e-4)).clamp(0.0, 1.0);
|
||||||
let pilot_lock = ((pilot_coherence - 0.4) / 0.2).clamp(0.0, 1.0);
|
let pilot_lock = ((pilot_coherence - 0.4) / 0.2).clamp(0.0, 1.0);
|
||||||
let stereo_blend = (pilot_mag * pilot_lock * 120.0).clamp(0.0, 1.0);
|
let stereo_drive = (pilot_mag * pilot_lock * 120.0).clamp(0.0, 1.0);
|
||||||
let detect_coeff = if stereo_blend > self.stereo_detect_level {
|
let detect_coeff = if stereo_drive > self.stereo_detect_level {
|
||||||
0.0008
|
0.0008
|
||||||
} else {
|
} else {
|
||||||
0.0002
|
0.0002
|
||||||
};
|
};
|
||||||
self.stereo_detect_level += detect_coeff * (stereo_blend - self.stereo_detect_level);
|
self.stereo_detect_level += detect_coeff * (stereo_drive - self.stereo_detect_level);
|
||||||
if self.stereo_detected {
|
if self.stereo_detected {
|
||||||
if self.stereo_detect_level < 0.35 {
|
if self.stereo_detect_level < 0.35 {
|
||||||
self.stereo_detected = false;
|
self.stereo_detected = false;
|
||||||
@@ -559,6 +565,8 @@ impl WfmStereoDecoder {
|
|||||||
} else if self.stereo_detect_level > 0.6 {
|
} else if self.stereo_detect_level > 0.6 {
|
||||||
self.stereo_detected = true;
|
self.stereo_detected = true;
|
||||||
}
|
}
|
||||||
|
let stereo_blend_target =
|
||||||
|
smoothstep01((self.stereo_detect_level - 0.18) / (0.92 - 0.18));
|
||||||
|
|
||||||
// --- RDS ---
|
// --- RDS ---
|
||||||
let rds_quality = (0.35 + pilot_mag * 20.0).clamp(0.35, 1.0);
|
let rds_quality = (0.35 + pilot_mag * 20.0).clamp(0.35, 1.0);
|
||||||
@@ -593,7 +601,7 @@ impl WfmStereoDecoder {
|
|||||||
let prev_phase = self.output_phase;
|
let prev_phase = self.output_phase;
|
||||||
self.output_phase += self.output_phase_inc;
|
self.output_phase += self.output_phase_inc;
|
||||||
if self.output_phase < 1.0 {
|
if self.output_phase < 1.0 {
|
||||||
self.prev_blend = stereo_blend;
|
self.prev_blend = stereo_blend_target;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self.output_phase -= 1.0;
|
self.output_phase -= 1.0;
|
||||||
@@ -605,12 +613,9 @@ impl WfmStereoDecoder {
|
|||||||
let sum_i = polyphase_resample(&self.sum_hist, &self.resample_bank, frac);
|
let sum_i = polyphase_resample(&self.sum_hist, &self.resample_bank, frac);
|
||||||
let diff_i = polyphase_resample(&self.diff_hist, &self.resample_bank, frac);
|
let diff_i = polyphase_resample(&self.diff_hist, &self.resample_bank, frac);
|
||||||
let diff_q = polyphase_resample(&self.diff_q_hist, &self.resample_bank, frac);
|
let diff_q = polyphase_resample(&self.diff_q_hist, &self.resample_bank, frac);
|
||||||
let blend_i = if self.stereo_detected {
|
let blend_i =
|
||||||
1.0
|
(self.prev_blend + frac * (stereo_blend_target - self.prev_blend)).clamp(0.0, 1.0);
|
||||||
} else {
|
self.prev_blend = stereo_blend_target;
|
||||||
(self.prev_blend + frac * (stereo_blend - self.prev_blend)).clamp(0.0, 1.0)
|
|
||||||
};
|
|
||||||
self.prev_blend = stereo_blend;
|
|
||||||
let (trim_sin, trim_cos) = STEREO_SEPARATION_PHASE_TRIM.sin_cos();
|
let (trim_sin, trim_cos) = STEREO_SEPARATION_PHASE_TRIM.sin_cos();
|
||||||
let diff_i = (diff_i * trim_cos + diff_q * trim_sin) * STEREO_SEPARATION_GAIN;
|
let diff_i = (diff_i * trim_cos + diff_q * trim_sin) * STEREO_SEPARATION_GAIN;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user