use crate::LPC_ORDER as ORDER;
use crate::bitstream::{self, Params};
use crate::codebook;
use crate::excitation;
use crate::fixed::{acc, hi, sat, shift};
use crate::gain::{self, GainState};
use crate::lsp::{self, LsfState};
use crate::pitch::{self, Lag, SUBFRAME};
use crate::postfilter;
use crate::synth;
use crate::ulaw;
pub use crate::FRAME;
pub const EXC_HISTORY: usize = crate::EXCITATION_HISTORY;
pub use crate::HALF;
pub use crate::ltp::RES_HISTORY;
#[derive(Clone)]
pub struct Decoder {
pub(crate) lsf: LsfState,
pub(crate) gain: GainState,
pub(crate) prev_lsp: [i16; ORDER],
pub(crate) synth_mem: [i16; ORDER],
pub(crate) exc: [i16; EXC_HISTORY + HALF],
pub(crate) speech: [i16; ORDER + HALF],
pub(crate) short_term_filter: postfilter::ShortTermFilter,
pub(crate) output_filter: crate::postfilter::OutputFilter,
pub(crate) reference_lag: i16,
pub(crate) last_half_lag: i16,
pub(crate) residual: [i16; RES_HISTORY + SUBFRAME],
pub(crate) sharpen_fixed: i16,
pub(crate) sharpen_voiced: i16,
pub(crate) conceal_lag: i16,
pub(crate) prev_lag: i16,
pub(crate) voiced: i16,
pub(crate) no_interp: i16,
pub(crate) rng: u32,
}
impl Default for Decoder {
fn default() -> Self {
let mut prev_lsp = [0i16; ORDER];
prev_lsp.copy_from_slice(&crate::tables::LSP_MEAN[..ORDER]);
Decoder {
lsf: LsfState::default(),
gain: GainState::default(),
prev_lsp,
synth_mem: [0; ORDER],
exc: [0; EXC_HISTORY + HALF],
speech: [0; ORDER + HALF],
short_term_filter: postfilter::ShortTermFilter::default(),
output_filter: crate::postfilter::OutputFilter::default(),
reference_lag: 60,
last_half_lag: 60,
residual: [0; RES_HISTORY + SUBFRAME],
sharpen_fixed: 3277,
sharpen_voiced: 3277,
conceal_lag: 60,
prev_lag: 60,
voiced: 60,
no_interp: 0,
rng: 21845,
}
}
}
const SHARPEN_MIN: i16 = 3277;
const SHARPEN_MAX: i16 = 13017;
const RNG_MULTIPLIER: u16 = 31821;
const RNG_INCREMENT: i16 = 13849;
fn excitation_sample(
suppressed: bool,
voiced: bool,
innovation: i16,
adaptive: i16,
gains: gain::Gains,
) -> i16 {
if !suppressed {
return excitation::mixed_sample(adaptive, innovation, gains.pitch, gains.code);
}
let value = if voiced {
sat(acc(shift(
acc((gains.pitch as i64) * (adaptive as i64) * 2),
1,
) + (1 << 15)))
} else {
sat(acc(shift(
acc((gains.code as i64) * (innovation as i64) * 2),
2,
) + (1 << 15)))
};
hi(value)
}
impl Decoder {
pub fn new() -> Self {
Self::default()
}
pub fn decode(&mut self, frame: &[u8; bitstream::FRAME_BYTES]) -> Option<[u8; FRAME]> {
let linear = self.decode_linear(frame)?;
let mut out = [0u8; FRAME];
ulaw::frame_from_linear(&linear, &mut out);
Some(out)
}
pub fn decode_linear(&mut self, frame: &[u8; bitstream::FRAME_BYTES]) -> Option<[i16; FRAME]> {
let words = bitstream::canonicalize(frame);
if bitstream::is_reset(&words) {
*self = Decoder::default();
return None;
}
let params = bitstream::unpack(&words);
Some(self.decode_params(¶ms))
}
fn decode_output_half(
&mut self,
params: &Params,
half: usize,
half_lsp: &[i16; ORDER],
output: &mut [i16],
) {
let subframe_lsp = self.decode_half(params, half, half_lsp);
self.voiced = 0;
for (sub, lsp) in subframe_lsp.iter().enumerate() {
let at = sub * SUBFRAME;
let lag = self.postfilter_subframe(lsp, at, &mut output[at..at + SUBFRAME]);
if lag != 0 {
self.voiced = lag;
}
}
let tail = ORDER + HALF - ORDER;
self.speech.copy_within(tail..tail + ORDER, 0);
self.output_filter.run(output);
}
pub fn decode_params(&mut self, params: &Params) -> [i16; FRAME] {
let (first_half_lsp, second_half_lsp) = self.decode_spectrum(params);
let mut linear = [0i16; FRAME];
for (half, half_lsp) in [first_half_lsp, second_half_lsp].iter().enumerate() {
let at = half * HALF;
self.decode_output_half(params, half, half_lsp, &mut linear[at..at + HALF]);
}
linear
}
#[doc(hidden)]
pub fn dump_spectrum(&mut self, params: &Params) -> ([i16; ORDER], [i16; ORDER]) {
self.decode_spectrum(params)
}
#[doc(hidden)]
pub fn dump_state(&self) -> String {
format!(
"voiced={} gains={:?} erasures={} lag={} rng={:08x}\nEXC {:?}\nSPEECH {:?}",
self.voiced,
self.gain.gains,
self.gain.erasures,
self.conceal_lag,
self.rng,
&self.exc[..],
&self.speech[..],
)
}
#[doc(hidden)]
pub fn dump_half(&mut self, params: &Params, half: usize, lsp: &[i16; ORDER]) {
self.decode_half(params, half, lsp);
}
fn decode_spectrum(&mut self, params: &Params) -> ([i16; ORDER], [i16; ORDER]) {
let lsf = if params.suppress {
lsp::decode_suppressed(&mut self.lsf)
} else {
let idx = lsp::LsfIndices::unpack(params.field[0], params.field[1]);
lsp::decode(&mut self.lsf, idx)
};
self.lsf.prev_lsf = lsf;
let current = lsp::lsf_to_lsp(&lsf);
let mut mid = lsp::midpoint(&self.prev_lsp, ¤t);
let reflection = lsp::reflection_coefficients(&lsp::lsp_to_lpc(¤t));
let (flag, force_current) = lsp::interpolation_control(&reflection, self.no_interp != 0);
if force_current {
mid = current;
}
self.no_interp = flag as i16;
(mid, current)
}
fn decode_half(
&mut self,
params: &Params,
half: usize,
half_lsp: &[i16; ORDER],
) -> [[i16; ORDER]; 2] {
let (lsp_a, lsp_b, lpc_a, lpc_b) = lsp::interpolate_pair(&self.prev_lsp, half_lsp);
self.prev_lsp = *half_lsp;
let subframe_lsp = [lsp_a, lsp_b];
let subframe_lpc = [lpc_a, lpc_b];
for (sub, subframe_lpc) in subframe_lpc.iter().enumerate() {
self.decode_subframe(params, half, sub, subframe_lpc);
}
self.exc.copy_within(HALF.., 0);
self.last_half_lag = self.prev_lag;
subframe_lsp
}
fn decode_lag(&mut self, suppressed: bool, sub: usize, field: i16) -> Lag {
let lag = if suppressed {
let lag = Lag {
integer: self.conceal_lag,
frac: 0,
};
self.conceal_lag = (self.conceal_lag + 1).min(143);
lag
} else if sub == 0 {
let lag = pitch::decode_absolute(field);
self.conceal_lag = lag.integer;
lag
} else {
let lag = pitch::decode_relative(field, self.prev_lag);
self.conceal_lag = lag.integer;
lag
};
if sub == 0 {
self.reference_lag = lag.integer;
}
self.prev_lag = lag.integer;
lag
}
fn update_sharpening(&mut self, lpc: &[i16; ORDER + 1], lag: &Lag) {
let reflection = lsp::reflection_coefficients(lpc);
(self.sharpen_fixed, self.sharpen_voiced) = excitation::interpolation_gains(
reflection[0],
self.sharpen_fixed,
lag.integer,
self.last_half_lag,
);
}
fn decode_fixed_codebook(
&mut self,
suppressed: bool,
field: i16,
lag: &Lag,
) -> [i16; SUBFRAME] {
let code_index = if suppressed {
self.next_random()
} else {
field as u16
};
let innovation = codebook::decode(code_index);
let mut code = innovation.code;
if lag.integer < SUBFRAME as i16 {
let sharpen = if innovation.class == 5 || (1..3).contains(&innovation.class) {
self.sharpen_voiced
} else {
self.sharpen_fixed
};
pitch::sharpen(&mut code, lag, sharpen);
}
code
}
fn decode_gains(
&mut self,
suppressed: bool,
field: i16,
code: &[i16; SUBFRAME],
) -> gain::Gains {
let gains = if suppressed {
gain::decode_suppressed(&mut self.gain)
} else {
gain::decode(&mut self.gain, field, code)
};
self.sharpen_fixed = gains.pitch.clamp(SHARPEN_MIN, SHARPEN_MAX);
gains
}
fn synthesise_subframe(&mut self, sub: usize, at: usize, lpc: &[i16; ORDER + 1]) {
let mut out = [0i16; SUBFRAME];
let Decoder { exc, synth_mem, .. } = self;
synth::synthesis(lpc, &exc[at..at + SUBFRAME], &mut out, synth_mem);
let dst = ORDER + sub * SUBFRAME;
self.speech[dst..dst + SUBFRAME].copy_from_slice(&out);
}
fn decode_subframe(
&mut self,
params: &Params,
half: usize,
sub: usize,
lpc: &[i16; ORDER + 1],
) {
let at = EXC_HISTORY + sub * SUBFRAME;
let field = params.subframe(half, sub);
let lag = self.decode_lag(params.suppress, sub, field.lag);
pitch::predict(&mut self.exc, at, &lag);
self.update_sharpening(lpc, &lag);
let code = self.decode_fixed_codebook(params.suppress, field.code, &lag);
let gains = self.decode_gains(params.suppress, field.gain, &code);
self.combine_excitation(params.suppress, at, &code, gains);
self.synthesise_subframe(sub, at, lpc);
}
fn combine_excitation(
&mut self,
suppressed: bool,
at: usize,
code: &[i16; SUBFRAME],
gains: gain::Gains,
) {
let voiced = self.voiced != 0;
for (&innovation, excitation) in code.iter().zip(self.exc[at..at + SUBFRAME].iter_mut()) {
*excitation = excitation_sample(suppressed, voiced, innovation, *excitation, gains);
}
}
fn update_postfilter_residual(&mut self, numerator: &[i16; ORDER + 1], at: usize) {
let speech = &self.speech[at..at + ORDER + SUBFRAME];
let mut residual = [0i16; SUBFRAME];
postfilter::inverse_filter(numerator, speech, &mut residual);
self.residual[RES_HISTORY..].copy_from_slice(&residual);
}
fn postfilter_subframe(
&mut self,
subframe_lsp: &[i16; ORDER],
at: usize,
out: &mut [i16],
) -> i16 {
let coefficients = postfilter::Coefficients::new(subframe_lsp);
self.update_postfilter_residual(&coefficients.numerator, at);
let mut filtered = [0i16; SUBFRAME];
let lag = crate::ltp::filter(&self.residual, self.reference_lag, &mut filtered);
let Decoder {
speech,
short_term_filter,
..
} = self;
let speech_block = &speech[ORDER + at..ORDER + at + SUBFRAME];
let compensated = short_term_filter.filter(&coefficients, speech_block, filtered);
out.copy_from_slice(&compensated);
self.residual.copy_within(SUBFRAME.., 0);
lag
}
fn next_random(&mut self) -> u16 {
let upper = ((self.rng >> 16) as u16 as i64) * (RNG_MULTIPLIER as i64) * 2;
let lower = ((self.rng as u16) as i64) * (RNG_MULTIPLIER as i64) * 2;
let mixed = acc(shift(acc(upper), 15) + shift(lower, -1) + (RNG_INCREMENT as i64));
self.rng = mixed as u32;
self.rng as u16
}
}