[style](trx-rs): cargo fmt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -475,8 +475,7 @@ impl Candidate {
|
|||||||
};
|
};
|
||||||
let max_order = if self.score >= 2 { 3u8 } else { 2 };
|
let max_order = if self.score >= 2 { 3u8 } else { 2 };
|
||||||
// Tech 3/7/8: use soft-decision decoder instead of hard decode.
|
// Tech 3/7/8: use soft-decision decoder instead of hard decode.
|
||||||
let Some((data, kind)) =
|
let Some((data, kind)) = decode_block_soft(word, &self.block_soft, max_cost, max_order)
|
||||||
decode_block_soft(word, &self.block_soft, max_cost, max_order)
|
|
||||||
else {
|
else {
|
||||||
self.drop_lock(word);
|
self.drop_lock(word);
|
||||||
return None;
|
return None;
|
||||||
@@ -1120,8 +1119,7 @@ fn decode_block_soft(
|
|||||||
}
|
}
|
||||||
if let Some(kind) = offset_to_kind(syn12 ^ bit_syn[k3]) {
|
if let Some(kind) = offset_to_kind(syn12 ^ bit_syn[k3]) {
|
||||||
best_cost = triple_cost;
|
best_cost = triple_cost;
|
||||||
let flip =
|
let flip = (1u32 << (25 - k1)) ^ (1u32 << (25 - k2)) ^ (1u32 << (25 - k3));
|
||||||
(1u32 << (25 - k1)) ^ (1u32 << (25 - k2)) ^ (1u32 << (25 - k3));
|
|
||||||
best_result = Some((((word ^ flip) >> 10) as u16, kind));
|
best_result = Some((((word ^ flip) >> 10) as u16, kind));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1299,7 +1297,8 @@ mod tests {
|
|||||||
// Mark the corrupted bit as low confidence (realistic: a genuine
|
// Mark the corrupted bit as low confidence (realistic: a genuine
|
||||||
// error has low |biphase_I|).
|
// error has low |biphase_I|).
|
||||||
soft[15] = 0.05;
|
soft[15] = 0.05;
|
||||||
let (data, kind) = decode_block_soft(corrupted, &soft, OSD_MAX_FLIP_COST, 3).expect("should recover");
|
let (data, kind) =
|
||||||
|
decode_block_soft(corrupted, &soft, OSD_MAX_FLIP_COST, 3).expect("should recover");
|
||||||
assert_eq!(data, 0xABCD);
|
assert_eq!(data, 0xABCD);
|
||||||
assert_eq!(kind, BlockKind::A);
|
assert_eq!(kind, BlockKind::A);
|
||||||
}
|
}
|
||||||
@@ -1315,7 +1314,8 @@ mod tests {
|
|||||||
let mut soft = [1.0f32; 26];
|
let mut soft = [1.0f32; 26];
|
||||||
soft[0] = 0.05;
|
soft[0] = 0.05;
|
||||||
soft[1] = 0.05;
|
soft[1] = 0.05;
|
||||||
let (data, kind) = decode_block_soft(corrupted, &soft, OSD_MAX_FLIP_COST, 3).expect("OSD(2) should correct");
|
let (data, kind) = decode_block_soft(corrupted, &soft, OSD_MAX_FLIP_COST, 3)
|
||||||
|
.expect("OSD(2) should correct");
|
||||||
assert_eq!(data, 0x1234);
|
assert_eq!(data, 0x1234);
|
||||||
assert_eq!(kind, BlockKind::B);
|
assert_eq!(kind, BlockKind::B);
|
||||||
}
|
}
|
||||||
@@ -1337,7 +1337,8 @@ mod tests {
|
|||||||
let corrupted = word ^ (1 << (25 - 2)); // flip bit k=2
|
let corrupted = word ^ (1 << (25 - 2)); // flip bit k=2
|
||||||
let mut soft = [1.0f32; 26];
|
let mut soft = [1.0f32; 26];
|
||||||
soft[2] = 0.01; // least confident → cheapest to flip
|
soft[2] = 0.01; // least confident → cheapest to flip
|
||||||
let (data, kind) = decode_block_soft(corrupted, &soft, OSD_MAX_FLIP_COST, 3).expect("should recover");
|
let (data, kind) =
|
||||||
|
decode_block_soft(corrupted, &soft, OSD_MAX_FLIP_COST, 3).expect("should recover");
|
||||||
assert_eq!(data, 0xBEEF);
|
assert_eq!(data, 0xBEEF);
|
||||||
assert_eq!(kind, BlockKind::D);
|
assert_eq!(kind, BlockKind::D);
|
||||||
}
|
}
|
||||||
@@ -1784,14 +1785,17 @@ mod tests {
|
|||||||
soft[1] = 0.05;
|
soft[1] = 0.05;
|
||||||
|
|
||||||
// Verify each corrupted block individually recovers via OSD(2).
|
// Verify each corrupted block individually recovers via OSD(2).
|
||||||
let (d_b, k_b) = decode_block_soft(corrupt_b, &soft, OSD_MAX_FLIP_COST, 3).expect("block B should recover");
|
let (d_b, k_b) = decode_block_soft(corrupt_b, &soft, OSD_MAX_FLIP_COST, 3)
|
||||||
|
.expect("block B should recover");
|
||||||
assert_eq!((d_b, k_b), (block_b_data, BlockKind::B));
|
assert_eq!((d_b, k_b), (block_b_data, BlockKind::B));
|
||||||
|
|
||||||
// C' check
|
// C' check
|
||||||
let (d_c, _k_c) = decode_block_soft(corrupt_c, &soft, OSD_MAX_FLIP_COST, 3).expect("block C' should recover");
|
let (d_c, _k_c) = decode_block_soft(corrupt_c, &soft, OSD_MAX_FLIP_COST, 3)
|
||||||
|
.expect("block C' should recover");
|
||||||
assert_eq!(d_c, 0x4865);
|
assert_eq!(d_c, 0x4865);
|
||||||
|
|
||||||
let (d_d, k_d) = decode_block_soft(corrupt_d, &soft, OSD_MAX_FLIP_COST, 3).expect("block D should recover");
|
let (d_d, k_d) = decode_block_soft(corrupt_d, &soft, OSD_MAX_FLIP_COST, 3)
|
||||||
|
.expect("block D should recover");
|
||||||
assert_eq!(k_d, BlockKind::D);
|
assert_eq!(k_d, BlockKind::D);
|
||||||
assert_eq!(d_d, u16::from_be_bytes(*b"Hi"));
|
assert_eq!(d_d, u16::from_be_bytes(*b"Hi"));
|
||||||
|
|
||||||
|
|||||||
@@ -708,7 +708,11 @@ impl WfmStereoDecoder {
|
|||||||
}
|
}
|
||||||
let mean_mag = sum_mag / n;
|
let mean_mag = sum_mag / n;
|
||||||
let var = (sum_mag_sq / n - mean_mag * mean_mag).max(0.0);
|
let var = (sum_mag_sq / n - mean_mag * mean_mag).max(0.0);
|
||||||
let cv = if mean_mag > 1e-8 { var.sqrt() / mean_mag } else { 0.0 };
|
let cv = if mean_mag > 1e-8 {
|
||||||
|
var.sqrt() / mean_mag
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
// Map CV to 0–100. Empirically, CV > 0.35 is heavy ACI.
|
// Map CV to 0–100. Empirically, CV > 0.35 is heavy ACI.
|
||||||
let raw_aci = (cv * 100.0 / 0.35).clamp(0.0, 100.0);
|
let raw_aci = (cv * 100.0 / 0.35).clamp(0.0, 100.0);
|
||||||
let alpha = 0.08_f32;
|
let alpha = 0.08_f32;
|
||||||
@@ -718,7 +722,8 @@ impl WfmStereoDecoder {
|
|||||||
// Tech 9: apply CMA blind equalizer to IQ samples before FM demodulation.
|
// Tech 9: apply CMA blind equalizer to IQ samples before FM demodulation.
|
||||||
// The constant-modulus property of FM drives tap adaptation without a
|
// The constant-modulus property of FM drives tap adaptation without a
|
||||||
// training sequence, suppressing adjacent-channel interference.
|
// training sequence, suppressing adjacent-channel interference.
|
||||||
let mut equalized: Vec<Complex<f32>> = samples.iter().map(|&s| self.cma.process(s)).collect();
|
let mut equalized: Vec<Complex<f32>> =
|
||||||
|
samples.iter().map(|&s| self.cma.process(s)).collect();
|
||||||
|
|
||||||
// Hard-limit to unit magnitude after CMA (preserves phase for FM demod
|
// Hard-limit to unit magnitude after CMA (preserves phase for FM demod
|
||||||
// while preventing clipping artefacts).
|
// while preventing clipping artefacts).
|
||||||
@@ -1462,7 +1467,12 @@ mod tests {
|
|||||||
let iq = fm_modulate(&composite, 2.1, 75_000.0, fs);
|
let iq = fm_modulate(&composite, 2.1, 75_000.0, fs);
|
||||||
|
|
||||||
let mut decoder = WfmStereoDecoder::new(
|
let mut decoder = WfmStereoDecoder::new(
|
||||||
composite_rate, audio_rate, 2, true, 50, WfmDenoiseLevel::Auto,
|
composite_rate,
|
||||||
|
audio_rate,
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
50,
|
||||||
|
WfmDenoiseLevel::Auto,
|
||||||
);
|
);
|
||||||
let _ = decoder.process_iq(&iq);
|
let _ = decoder.process_iq(&iq);
|
||||||
|
|
||||||
@@ -1503,7 +1513,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut decoder = WfmStereoDecoder::new(
|
let mut decoder = WfmStereoDecoder::new(
|
||||||
composite_rate, audio_rate, 2, true, 50, WfmDenoiseLevel::Auto,
|
composite_rate,
|
||||||
|
audio_rate,
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
50,
|
||||||
|
WfmDenoiseLevel::Auto,
|
||||||
);
|
);
|
||||||
let _ = decoder.process_iq(&iq);
|
let _ = decoder.process_iq(&iq);
|
||||||
|
|
||||||
@@ -1525,7 +1540,12 @@ mod tests {
|
|||||||
let iq = fm_modulate(&composite, 2.1, 75_000.0, fs);
|
let iq = fm_modulate(&composite, 2.1, 75_000.0, fs);
|
||||||
|
|
||||||
let mut decoder = WfmStereoDecoder::new(
|
let mut decoder = WfmStereoDecoder::new(
|
||||||
composite_rate, audio_rate, 2, true, 50, WfmDenoiseLevel::Auto,
|
composite_rate,
|
||||||
|
audio_rate,
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
50,
|
||||||
|
WfmDenoiseLevel::Auto,
|
||||||
);
|
);
|
||||||
let _ = decoder.process_iq(&iq);
|
let _ = decoder.process_iq(&iq);
|
||||||
|
|
||||||
@@ -1570,7 +1590,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut decoder = WfmStereoDecoder::new(
|
let mut decoder = WfmStereoDecoder::new(
|
||||||
composite_rate, audio_rate, 2, true, 50, WfmDenoiseLevel::Auto,
|
composite_rate,
|
||||||
|
audio_rate,
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
50,
|
||||||
|
WfmDenoiseLevel::Auto,
|
||||||
);
|
);
|
||||||
let _ = decoder.process_iq(&iq);
|
let _ = decoder.process_iq(&iq);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user