use crate::codecs::mbe_baseline::{
synthesize_frame_ambe_plus as baseline_synthesize_ambe_plus,
synthesize_repeat_ambe_plus as baseline_synthesize_repeat, FRAME_SAMPLES,
};
use crate::mbe_params::MbeParams;
pub use crate::codecs::mbe_baseline::SynthState;
pub const SAMPLES_PER_FRAME: usize = FRAME_SAMPLES;
pub fn synthesize_frame(
params: &MbeParams,
state: &mut SynthState,
) -> [i16; SAMPLES_PER_FRAME] {
let err = state.err;
let gamma_w = state.gamma_w;
baseline_synthesize_ambe_plus(params, &err, gamma_w, state)
}
pub fn synthesize_tone(
params: &MbeParams,
state: &mut SynthState,
) -> [i16; SAMPLES_PER_FRAME] {
synthesize_frame(params, state)
}
pub fn synthesize_repeat(state: &mut SynthState) -> [i16; SAMPLES_PER_FRAME] {
baseline_synthesize_repeat(state)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mbe_params::L_MIN;
fn silence_params() -> MbeParams {
let voiced = vec![false; L_MIN as usize];
let amps = vec![0.0_f32; L_MIN as usize];
MbeParams::new(
2.0 * core::f32::consts::PI / 50.0,
L_MIN,
&voiced,
&s,
)
.unwrap()
}
#[test]
fn synthesize_frame_returns_expected_sample_count() {
let params = silence_params();
let mut state = SynthState::new();
let pcm = synthesize_frame(¶ms, &mut state);
assert_eq!(pcm.len(), SAMPLES_PER_FRAME);
}
#[test]
fn synthesize_frame_matches_baseline_ambe_plus_path() {
let params = silence_params();
let mut a = SynthState::new();
let mut b = SynthState::new();
let out_codec = synthesize_frame(¶ms, &mut a);
let err = b.err;
let gamma_w = b.gamma_w;
let out_direct = baseline_synthesize_ambe_plus(¶ms, &err, gamma_w, &mut b);
assert_eq!(out_codec, out_direct);
}
#[test]
fn synthesize_tone_returns_expected_sample_count() {
let params = silence_params();
let mut state = SynthState::new();
let pcm = synthesize_tone(¶ms, &mut state);
assert_eq!(pcm.len(), SAMPLES_PER_FRAME);
}
#[test]
fn synthesize_repeat_on_cold_start_emits_silence() {
let mut state = SynthState::new();
let pcm = synthesize_repeat(&mut state);
assert_eq!(pcm.len(), SAMPLES_PER_FRAME);
let energy: i64 = pcm.iter().map(|&s| i64::from(s).pow(2)).sum();
assert!(energy < 1_000_000, "cold-start repeat should be near-silent, got energy {energy}");
}
#[test]
fn synthesize_repeat_after_voice_does_not_reset_state() {
let params = silence_params();
let mut state = SynthState::new();
let _ = synthesize_frame(¶ms, &mut state);
let s_e_after_voice = state.s_e;
let _ = synthesize_repeat(&mut state);
assert!(state.s_e.is_finite());
assert!(state.s_e > 0.0);
assert!(
state.s_e != crate::codecs::mbe_baseline::INIT_S_E
|| s_e_after_voice != crate::codecs::mbe_baseline::INIT_S_E,
"state should have evolved from cold start"
);
}
}