use crate::silk_decode::SilkFrameDecoded;
use crate::silk_excitation::SilkFrameSize;
use crate::silk_frame::SignalType;
use crate::silk_gains::SILK_MAX_SUBFRAMES;
use crate::silk_lpc_synth::{lpc_synthesis_subframe, subframe_samples, LpcSynthState};
use crate::silk_ltp::LTP_FILTER_TAPS;
use crate::silk_ltp_synth::{
ltp_synth_commit_subframe, ltp_synthesis_subframe, LtpSynthState, LtpSynthSubframe,
};
use crate::toc::Bandwidth;
use crate::Error;
#[derive(Debug, Clone)]
pub struct SilkSynthState {
bandwidth: Bandwidth,
ltp: LtpSynthState,
lpc: LpcSynthState,
}
impl SilkSynthState {
pub fn new(bandwidth: Bandwidth) -> Result<Self, Error> {
Ok(Self {
bandwidth,
ltp: LtpSynthState::new(bandwidth)?,
lpc: LpcSynthState::new(bandwidth)?,
})
}
pub fn bandwidth(&self) -> Bandwidth {
self.bandwidth
}
pub fn reset(&mut self) {
self.ltp.reset();
self.lpc.reset();
}
pub fn ltp(&self) -> &LtpSynthState {
&self.ltp
}
pub fn lpc(&self) -> &LpcSynthState {
&self.lpc
}
}
fn a_q12_i16(a_q12: &[i32]) -> Vec<i16> {
a_q12
.iter()
.map(|&c| c.clamp(i16::MIN as i32, i16::MAX as i32) as i16)
.collect()
}
pub fn synthesize_silk_frame(
bandwidth: Bandwidth,
frame_size: SilkFrameSize,
decoded: &SilkFrameDecoded,
state: &mut SilkSynthState,
) -> Result<Vec<f32>, Error> {
if state.bandwidth != bandwidth {
return Err(Error::MalformedPacket);
}
let n = subframe_samples(bandwidth)?;
let num_subframes = match frame_size {
SilkFrameSize::TenMs => 2usize,
SilkFrameSize::TwentyMs => 4usize,
};
let gains_q16 = decoded.gains.dequant_q16();
if decoded.gains.len() != num_subframes {
return Err(Error::MalformedPacket);
}
let interp_split =
matches!(frame_size, SilkFrameSize::TwentyMs) && decoded.lpc_first_half.is_some();
let e_q23 = decoded.excitation.e_q23();
if e_q23.len() < n * num_subframes {
return Err(Error::MalformedPacket);
}
let e_q23 = &e_q23[..n * num_subframes];
let pitch_lags = decoded.ltp.pitch_lags();
let filter_taps = decoded.ltp.filter_taps_q7();
let ltp_scaling_q14 = decoded.ltp.ltp_scaling_q14();
let is_voiced = decoded.signal_type == SignalType::Voiced;
if is_voiced && (pitch_lags.len() != num_subframes || filter_taps.len() != num_subframes) {
return Err(Error::MalformedPacket);
}
state.ltp.start_frame();
let mut out = vec![0.0f32; n * num_subframes];
for s in 0..num_subframes {
let a_q12 = if interp_split && s < 2 {
decoded
.lpc_first_half
.as_ref()
.ok_or(Error::MalformedPacket)?
.a_q12()
} else {
decoded.lpc_second_half.a_q12()
};
let a_i16 = a_q12_i16(a_q12);
let (pitch_lag, b_q7) = if is_voiced {
(pitch_lags[s], filter_taps[s])
} else {
(1i32, [0i8; LTP_FILTER_TAPS])
};
let lsf_interp_used = interp_split;
let j = s * n;
let e_sub = &e_q23[j..j + n];
let mut res = vec![0.0f32; n];
let cfg = LtpSynthSubframe {
bandwidth,
signal_type: decoded.signal_type,
frame_size,
subframe_index: s as u8,
gain_q16: gains_q16[s],
pitch_lag,
b_q7,
ltp_scaling_q14,
a_q12: &a_i16,
lsf_interp_used,
};
ltp_synthesis_subframe(&state.ltp, cfg, e_sub, &mut res)?;
let mut out_sub = vec![0.0f32; n];
let lpc_unclamped = lpc_synthesis_subframe(
bandwidth,
&mut state.lpc,
&res,
gains_q16[s],
&a_i16,
&mut out_sub,
)?;
ltp_synth_commit_subframe(&mut state.ltp, &out_sub, &lpc_unclamped)?;
out[j..j + n].copy_from_slice(&out_sub);
}
Ok(out)
}
pub fn synthesize_silk_frames(
bandwidth: Bandwidth,
frame_size: SilkFrameSize,
decoded: &[SilkFrameDecoded],
state: &mut SilkSynthState,
) -> Result<Vec<f32>, Error> {
let n = subframe_samples(bandwidth)?;
let per_frame = n * match frame_size {
SilkFrameSize::TenMs => 2usize,
SilkFrameSize::TwentyMs => 4usize,
};
let mut out = Vec::with_capacity(per_frame * decoded.len());
for frame in decoded {
let frame_out = synthesize_silk_frame(bandwidth, frame_size, frame, state)?;
out.extend_from_slice(&frame_out);
}
Ok(out)
}
pub fn silk_frame_internal_samples(
bandwidth: Bandwidth,
frame_size: SilkFrameSize,
) -> Result<usize, Error> {
let n = subframe_samples(bandwidth)?;
let num_subframes = match frame_size {
SilkFrameSize::TenMs => 2usize,
SilkFrameSize::TwentyMs => 4usize,
};
debug_assert!(num_subframes <= SILK_MAX_SUBFRAMES);
Ok(n * num_subframes)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::range_decoder::RangeDecoder;
use crate::silk_decode::{decode_silk_frame, SilkFrameConfig};
fn fresh_cfg(bandwidth: Bandwidth, frame_size: SilkFrameSize, voiced: bool) -> SilkFrameConfig {
SilkFrameConfig {
bandwidth,
frame_size,
voice_active: voiced,
first_subframe_independent: true,
previous_log_gain: None,
previous_primary_lag: None,
ltp_scaling_present: true,
lsf_interp_after_reset: true,
previous_nlsf_q15: None,
previous_nlsf_len: 0,
stereo: None,
}
}
#[test]
fn state_new_routes_and_rejects() {
for bw in [Bandwidth::Nb, Bandwidth::Mb, Bandwidth::Wb] {
let s = SilkSynthState::new(bw).unwrap();
assert_eq!(s.bandwidth(), bw);
}
assert!(SilkSynthState::new(Bandwidth::Swb).is_err());
assert!(SilkSynthState::new(Bandwidth::Fb).is_err());
}
#[test]
fn internal_sample_counts() {
assert_eq!(
silk_frame_internal_samples(Bandwidth::Nb, SilkFrameSize::TenMs).unwrap(),
80
);
assert_eq!(
silk_frame_internal_samples(Bandwidth::Nb, SilkFrameSize::TwentyMs).unwrap(),
160
);
assert_eq!(
silk_frame_internal_samples(Bandwidth::Mb, SilkFrameSize::TwentyMs).unwrap(),
240
);
assert_eq!(
silk_frame_internal_samples(Bandwidth::Wb, SilkFrameSize::TwentyMs).unwrap(),
320
);
assert_eq!(
silk_frame_internal_samples(Bandwidth::Wb, SilkFrameSize::TenMs).unwrap(),
160
);
}
#[test]
fn rejects_bandwidth_mismatch() {
let buf = [0x33u8; 96];
let mut rd = RangeDecoder::new(&buf);
let cfg = fresh_cfg(Bandwidth::Nb, SilkFrameSize::TwentyMs, false);
if let Ok(decoded) = decode_silk_frame(&mut rd, cfg) {
let mut state = SilkSynthState::new(Bandwidth::Wb).unwrap();
assert!(matches!(
synthesize_silk_frame(Bandwidth::Nb, SilkFrameSize::TwentyMs, &decoded, &mut state),
Err(Error::MalformedPacket)
));
}
}
#[test]
fn synthesize_produces_in_range_samples() {
let buf: Vec<u8> = (0..160u16)
.map(|i| (i.wrapping_mul(67).wrapping_add(5) & 0xff) as u8)
.collect();
for (bw, expected) in [
(Bandwidth::Nb, 160usize),
(Bandwidth::Mb, 240),
(Bandwidth::Wb, 320),
] {
for voiced in [false, true] {
let mut rd = RangeDecoder::new(&buf);
let cfg = fresh_cfg(bw, SilkFrameSize::TwentyMs, voiced);
if let Ok(decoded) = decode_silk_frame(&mut rd, cfg) {
let mut state = SilkSynthState::new(bw).unwrap();
let out =
synthesize_silk_frame(bw, SilkFrameSize::TwentyMs, &decoded, &mut state)
.unwrap();
assert_eq!(out.len(), expected, "bw={bw:?} voiced={voiced}");
for (i, &v) in out.iter().enumerate() {
assert!(v.is_finite(), "non-finite at {i}: {v}");
assert!(
(-1.0..=1.0).contains(&v),
"out[{i}]={v} outside nominal range (bw={bw:?})"
);
}
}
}
}
}
#[test]
fn ten_ms_two_subframes() {
let buf: Vec<u8> = (0..96u16)
.map(|i| (i.wrapping_mul(43).wrapping_add(9) & 0xff) as u8)
.collect();
let mut rd = RangeDecoder::new(&buf);
let cfg = fresh_cfg(Bandwidth::Wb, SilkFrameSize::TenMs, false);
if let Ok(decoded) = decode_silk_frame(&mut rd, cfg) {
assert!(decoded.lpc_first_half.is_none());
let mut state = SilkSynthState::new(Bandwidth::Wb).unwrap();
let out =
synthesize_silk_frame(Bandwidth::Wb, SilkFrameSize::TenMs, &decoded, &mut state)
.unwrap();
assert_eq!(out.len(), 160); }
}
#[test]
fn synthesis_is_deterministic() {
let buf: Vec<u8> = (0..160u16)
.map(|i| (i.wrapping_mul(89).wrapping_add(1) & 0xff) as u8)
.collect();
let mut rd = RangeDecoder::new(&buf);
let cfg = fresh_cfg(Bandwidth::Nb, SilkFrameSize::TwentyMs, true);
if let Ok(decoded) = decode_silk_frame(&mut rd, cfg) {
let mut s1 = SilkSynthState::new(Bandwidth::Nb).unwrap();
let mut s2 = SilkSynthState::new(Bandwidth::Nb).unwrap();
let o1 =
synthesize_silk_frame(Bandwidth::Nb, SilkFrameSize::TwentyMs, &decoded, &mut s1)
.unwrap();
let o2 =
synthesize_silk_frame(Bandwidth::Nb, SilkFrameSize::TwentyMs, &decoded, &mut s2)
.unwrap();
assert_eq!(o1, o2);
}
}
#[test]
fn multi_frame_concatenates() {
let buf: Vec<u8> = (0..160u16)
.map(|i| (i.wrapping_mul(31).wrapping_add(7) & 0xff) as u8)
.collect();
let mut rd = RangeDecoder::new(&buf);
let cfg = fresh_cfg(Bandwidth::Nb, SilkFrameSize::TwentyMs, false);
if let Ok(decoded) = decode_silk_frame(&mut rd, cfg) {
let frames = [decoded.clone(), decoded.clone()];
let mut state = SilkSynthState::new(Bandwidth::Nb).unwrap();
let out =
synthesize_silk_frames(Bandwidth::Nb, SilkFrameSize::TwentyMs, &frames, &mut state)
.unwrap();
assert_eq!(out.len(), 320); }
}
#[test]
fn reset_clears_histories() {
let buf: Vec<u8> = (0..160u16)
.map(|i| (i.wrapping_mul(53).wrapping_add(2) & 0xff) as u8)
.collect();
let mut rd = RangeDecoder::new(&buf);
let cfg = fresh_cfg(Bandwidth::Wb, SilkFrameSize::TwentyMs, true);
if let Ok(decoded) = decode_silk_frame(&mut rd, cfg) {
let mut state = SilkSynthState::new(Bandwidth::Wb).unwrap();
synthesize_silk_frame(Bandwidth::Wb, SilkFrameSize::TwentyMs, &decoded, &mut state)
.unwrap();
state.reset();
assert!(state.lpc().history().iter().all(|&x| x == 0.0));
assert!(state.ltp().out_history().iter().all(|&x| x == 0.0));
assert!(state.ltp().lpc_history().iter().all(|&x| x == 0.0));
}
}
}