use crate::core_types::{
FrameParams, FRAME_SAMPLES, SUPERFRAME_FRAMES,
SUPERFRAME_SAMPLES, SUPERFRAME_BYTES_600, NUM_LSF, NUM_BANDS,
};
use crate::bitstream::unpack_superframe;
use crate::quantize::dequantize_superframe;
use crate::voicing::{NoiseGen, mixed_excitation};
use crate::synthesis::SynthesisFrameProcessor;
pub struct Decoder {
synth: SynthesisFrameProcessor,
prev_anchor_lsf: [f32; NUM_LSF],
noise: NoiseGen,
pulse_phase: f32,
initialized: bool,
}
impl Decoder {
pub fn new() -> Self {
Self {
synth: SynthesisFrameProcessor::new(),
prev_anchor_lsf: crate::core_types::default_lsf(),
noise: NoiseGen::new(12345),
pulse_phase: 0.0,
initialized: false,
}
}
pub fn decode(
&mut self,
bitstream: &[u8; SUPERFRAME_BYTES_600],
output: &mut [f32; SUPERFRAME_SAMPLES],
) {
let (quantized, _bits_read) = unpack_superframe(bitstream);
let frames = dequantize_superframe(&quantized, &self.prev_anchor_lsf);
self.prev_anchor_lsf = frames[SUPERFRAME_FRAMES - 1].lsf;
for f in 0..SUPERFRAME_FRAMES {
let start = f * FRAME_SAMPLES;
let end = start + FRAME_SAMPLES;
self.synthesize_frame(
&frames[f],
&mut output[start..end],
f == 0 && !self.initialized,
);
}
self.initialized = true;
}
fn synthesize_frame(
&mut self,
params: &FrameParams,
output: &mut [f32],
first_frame: bool,
) {
let n = output.len().min(FRAME_SAMPLES);
let mut excitation = [0.0f32; FRAME_SAMPLES];
let mut voicing = [0.0f32; NUM_BANDS];
voicing.copy_from_slice(¶ms.bandpass_voicing);
mixed_excitation(
params.pitch,
&voicing,
params.jitter,
&mut excitation[..n],
&mut self.pulse_phase,
&mut self.noise,
);
if first_frame {
self.synth.process_frame_no_interp(params, &excitation[..n], &mut output[..n]);
} else {
self.synth.process_frame(params, &excitation[..n], &mut output[..n]);
}
}
pub fn reset(&mut self) {
self.synth.reset();
self.prev_anchor_lsf = crate::core_types::default_lsf();
self.noise = NoiseGen::new(12345);
self.pulse_phase = 0.0;
self.initialized = false;
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
pub fn prev_anchor_lsf(&self) -> &[f32; NUM_LSF] {
&self.prev_anchor_lsf
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core_types::{SAMPLE_RATE, SuperFrameQuantized};
use crate::bitstream::pack_superframe;
use crate::quantize;
fn pack_known(sq: &SuperFrameQuantized) -> [u8; SUPERFRAME_BYTES_600] {
let mut buf = [0u8; SUPERFRAME_BYTES_600];
pack_superframe(sq, &mut buf);
buf
}
#[test]
fn test_decode_output_length() {
let mut dec = Decoder::new();
let bitstream = [0u8; SUPERFRAME_BYTES_600];
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&bitstream, &mut output);
assert!(
output.iter().all(|x| x.is_finite()),
"All output samples must be finite"
);
}
#[test]
fn test_decode_zeros_quiet() {
let mut dec = Decoder::new();
let bitstream = [0u8; SUPERFRAME_BYTES_600];
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&bitstream, &mut output);
let rms = (output.iter().map(|x| x * x).sum::<f32>() / SUPERFRAME_SAMPLES as f32).sqrt();
assert!(
rms < 1.0,
"Zero bitstream should produce quiet output, rms={}",
rms
);
}
#[test]
fn test_decode_nonzero_bitstream() {
let sq = SuperFrameQuantized {
lsf_indices: [4, 4, 4, 4, 2, 2, 2, 2, 2, 2],
pitch_index: 30, gain_index: 20, voicing_bits: 0b0111, jitter_bit: 0,
};
let bitstream = pack_known(&sq);
let mut dec = Decoder::new();
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&bitstream, &mut output);
let energy: f32 = output.iter().map(|x| x * x).sum::<f32>() / SUPERFRAME_SAMPLES as f32;
assert!(
energy > 1e-8,
"Voiced frame with gain should produce energy, got {}",
energy
);
assert!(
output.iter().all(|x| x.is_finite()),
"Output must be finite"
);
}
#[test]
fn test_decode_state_updates() {
let mut dec = Decoder::new();
assert!(!dec.is_initialized());
let bitstream = [0u8; SUPERFRAME_BYTES_600];
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&bitstream, &mut output);
assert!(dec.is_initialized());
let lsf = dec.prev_anchor_lsf();
for i in 1..NUM_LSF {
assert!(
lsf[i] > lsf[i - 1],
"Anchor LSFs should be ordered after decode"
);
}
}
#[test]
fn test_decode_reset() {
let mut dec = Decoder::new();
let bitstream = [0u8; SUPERFRAME_BYTES_600];
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&bitstream, &mut output);
assert!(dec.is_initialized());
dec.reset();
assert!(!dec.is_initialized());
}
#[test]
fn test_decode_multi_superframe() {
let mut dec = Decoder::new();
let sq = SuperFrameQuantized {
lsf_indices: [3, 3, 3, 3, 1, 1, 1, 1, 1, 1],
pitch_index: 25,
gain_index: 15,
voicing_bits: 0b0101, jitter_bit: 0,
};
let bitstream = pack_known(&sq);
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
for i in 0..5 {
dec.decode(&bitstream, &mut output);
assert!(
output.iter().all(|x| x.is_finite()),
"Output not finite at superframe {}",
i
);
let peak = output.iter().fold(0.0f32, |m, &s| m.max(s.abs()));
assert!(
peak < 100.0,
"Output blowing up at superframe {}: peak={}",
i, peak
);
}
}
#[test]
fn test_decode_deterministic() {
let sq = SuperFrameQuantized {
lsf_indices: [5, 3, 6, 2, 3, 1, 2, 3, 1, 2],
pitch_index: 35,
gain_index: 18,
voicing_bits: 0b0011,
jitter_bit: 1,
};
let bitstream = pack_known(&sq);
let mut dec1 = Decoder::new();
let mut dec2 = Decoder::new();
let mut out1 = [0.0f32; SUPERFRAME_SAMPLES];
let mut out2 = [0.0f32; SUPERFRAME_SAMPLES];
dec1.decode(&bitstream, &mut out1);
dec2.decode(&bitstream, &mut out2);
for i in 0..SUPERFRAME_SAMPLES {
assert!(
(out1[i] - out2[i]).abs() < 1e-6,
"Determinism failed at sample [{}]: {} vs {}",
i, out1[i], out2[i]
);
}
}
#[test]
fn test_voiced_vs_unvoiced_differ() {
let sq_voiced = SuperFrameQuantized {
lsf_indices: [4, 4, 4, 4, 2, 2, 2, 2, 2, 2],
pitch_index: 30,
gain_index: 20,
voicing_bits: 0b0111, jitter_bit: 0,
};
let sq_unvoiced = SuperFrameQuantized {
lsf_indices: [4, 4, 4, 4, 2, 2, 2, 2, 2, 2],
pitch_index: 30,
gain_index: 20,
voicing_bits: 0b0000, jitter_bit: 0,
};
let mut dec = Decoder::new();
let mut out_v = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&pack_known(&sq_voiced), &mut out_v);
dec.reset();
let mut out_uv = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&pack_known(&sq_unvoiced), &mut out_uv);
let diff: f32 = out_v.iter().zip(out_uv.iter())
.map(|(a, b)| (a - b).abs())
.sum::<f32>() / SUPERFRAME_SAMPLES as f32;
assert!(
diff > 1e-6,
"Voiced and unvoiced should produce different output, avg_diff={}",
diff
);
}
#[test]
fn test_different_bitstreams_differ() {
let sq1 = SuperFrameQuantized {
lsf_indices: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
pitch_index: 10,
gain_index: 10,
voicing_bits: 0b0111,
jitter_bit: 0,
};
let sq2 = SuperFrameQuantized {
lsf_indices: [6, 6, 6, 6, 3, 3, 3, 3, 3, 3],
pitch_index: 50,
gain_index: 25,
voicing_bits: 0b0000,
jitter_bit: 1,
};
let mut dec = Decoder::new();
let mut out1 = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&pack_known(&sq1), &mut out1);
dec.reset();
let mut out2 = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&pack_known(&sq2), &mut out2);
assert_ne!(
out1.as_slice(), out2.as_slice(),
"Different bitstreams should produce different output"
);
}
}