[fix](trx-server): fix VDES channel routing and IQ sample rate

Subscribe to the first sdr.channels[] entry configured as VDES or
MARINE instead of always using channel 0.  The ChannelDsp IQ tap only
emits samples when its own mode is VDES/MARINE, so the two must agree.

Fix vdes_sr to mirror channel.rs pipeline_rates(): use
audio_sample_rate.max(96_000) as the target rather than the hardcoded
96_000.  The two diverge when audio_sample_rate > 96_000, causing the
VdesDecoder to use the wrong symbol-to-sample ratio.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-07 10:14:09 +01:00
parent a1bcf6f8bf
commit 53199642ea
2 changed files with 17 additions and 4 deletions
+1 -1
View File
@@ -1041,7 +1041,7 @@ pub async fn run_ais_decoder(
}
}
/// Run the VDES decoder task. Only processes PCM when rig mode is VDES or MARINE.
/// Run the VDES decoder task. Only processes IQ when rig mode is VDES or MARINE.
pub async fn run_vdes_decoder(
sample_rate: u32,
mut iq_rx: broadcast::Receiver<Vec<Complex<f32>>>,
+16 -3
View File
@@ -355,7 +355,14 @@ fn build_sdr_rig_from_instance(rig_cfg: &RigInstanceConfig) -> SdrRigBuildResult
sdr_rig.subscribe_pcm_channel(ais_channel_base_idx),
sdr_rig.subscribe_pcm_channel(ais_channel_base_idx + 1),
);
let vdes_iq = sdr_rig.subscribe_iq_channel(0);
// Subscribe to the first channel configured as VDES or MARINE so that the
// IQ tap in ChannelDsp actually fires. Fall back to channel 0 when no
// explicit VDES channel has been configured.
let vdes_channel_idx = channels
.iter()
.position(|(_, mode, _, _)| matches!(mode, trx_core::rig::state::RigMode::VDES | trx_core::rig::state::RigMode::MARINE))
.unwrap_or(0);
let vdes_iq = sdr_rig.subscribe_iq_channel(vdes_channel_idx);
Ok((
Box::new(sdr_rig) as Box<dyn trx_core::rig::RigCat>,
pcm_rx,
@@ -643,8 +650,14 @@ fn spawn_rig_audio_stack(
let vdes_decode_tx = decode_tx.clone();
let vdes_shutdown_rx = shutdown_rx.clone();
let vdes_histories = histories.clone();
let vdes_sr =
(rig_cfg.sdr.sample_rate / (rig_cfg.sdr.sample_rate / 96_000).max(1)).max(1);
// Mirror channel.rs pipeline_rates: target = audio_sr.max(96_000),
// decim = sdr_sr / target, actual IQ rate = sdr_sr / decim.
let vdes_sr = {
let sdr_sr = rig_cfg.sdr.sample_rate;
let target = rig_cfg.audio.sample_rate.max(96_000);
let decim = (sdr_sr / target.max(1)).max(1);
(sdr_sr / decim).max(1)
};
handles.push(tokio::spawn(async move {
tokio::select! {
_ = audio::run_vdes_decoder(vdes_sr, vdes_iq_rx, vdes_state_rx, vdes_decode_tx, vdes_histories) => {}