#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![warn(trivial_numeric_casts)]
#[cfg(test)]
mod tests {
#[test]
fn encode_test() {
let mut c2 = crate::Codec2::new(crate::Codec2Mode::MODE_3200);
let spf = c2.samples_per_frame();
let mut samps = vec![0; spf * 2];
let bpf = c2.bits_per_frame();
println!(
"c2 is n_samp {:?} m_pitch {:?} Sn.len {:?} bpf {} spf {}",
c2.internal.n_samp,
c2.internal.m_pitch,
c2.internal.Sn.len(),
bpf,
spf
);
let mut outbuf = vec![0; (bpf + 7) / 8];
c2.encode(&mut outbuf, &samps);
assert_eq!(&outbuf[..], &[0xC0, 0, 0x6A, 0x43, 0x9C, 0xE4, 0x21, 8][..]);
let outbuforig = outbuf.clone();
println!("encoded {:X?}", outbuf);
c2.encode(&mut outbuf, &samps);
assert_eq!(&outbuf[..], &[0x81, 0, 9, 0x43, 0x9C, 0xE4, 0x21, 8][..]);
println!("encoded {:X?}", outbuf);
c2.encode(&mut outbuf, &samps);
assert_eq!(&outbuf[..], &[1, 0, 9, 0x43, 0x9C, 0xE4, 0x21, 8][..]);
println!("encoded {:X?}", outbuf);
c2.encode(&mut outbuf, &samps);
assert_eq!(&outbuf[..], &[1, 0, 9, 0x43, 0x9C, 0xE4, 0x21, 8][..]);
println!("encoded {:X?}", outbuf);
c2.decode(&mut samps, &outbuforig);
println!("decoded {:X?}", samps);
for samp in &samps {
assert!((*samp).abs() < 0x100);
}
}
}
mod kiss_fft;
mod nlp;
use nlp::FDMDV_OS_TAPS_16K;
mod quantise;
use crate::quantise::*;
mod codebook;
use crate::codebook::*;
mod codebookd;
use crate::codebookd::*;
mod codebookge;
use crate::codebookge::*;
mod codebookjvm;
use crate::codebookjvm::*;
const WO_BITS: i32 = 7;
const WO_E_BITS: u32 = 8;
const LSPD_SCALAR_INDEXES: usize = 10;
const LSP_SCALAR_INDEXES: usize = 10;
use std::f64::consts::PI;
const N_S: f32 = 0.01; const TW_S: f32 = 0.005; const MAX_AMP: usize = 160; const TWO_PI: f32 = 6.283185307; const FFT_ENC: usize = 512; const FFT_DEC: usize = 512; const V_THRESH: f32 = 6.0; const LPC_ORD: usize = 10; const M_PITCH_S: f32 = 0.0400; const P_MIN_S: f32 = 0.0025; const P_MAX_S: f32 = 0.0200; mod inner {
use crate::*;
#[derive(Clone, Debug)]
pub struct C2const {
pub Fs: i32, pub n_samp: usize, pub m_pitch: usize, pub p_min: i32, pub p_max: i32, pub Wo_min: f32,
pub Wo_max: f32,
pub nw: usize, pub tw: usize, }
impl C2const {
pub fn new(Fs: i32, framelength_s: f32) -> Self {
Self {
Fs: Fs,
n_samp: ((Fs as f32) * framelength_s).round() as usize,
p_min: ((Fs as f32) * P_MIN_S).floor() as i32,
p_max: ((Fs as f32) * P_MAX_S).floor() as i32,
m_pitch: ((Fs as f32) * M_PITCH_S).floor() as usize,
Wo_min: TWO_PI / ((Fs as f32) * P_MAX_S).floor(),
Wo_max: TWO_PI / ((Fs as f32) * P_MIN_S).floor(),
nw: 279,
tw: ((Fs as f32) * TW_S) as usize,
}
}
pub fn dft_speech(
&self,
fft_fwd_cfg: &codec2_fft_cfg,
Sw: &mut [COMP],
Sn: &[f32],
w: &[f32],
) {
let m_pitch = self.m_pitch;
let nw = self.nw;
for i in 0..FFT_ENC {
Sw[i].r = 0.0;
Sw[i].i = 0.0;
}
for i in 0..nw / 2 {
Sw[i].r = Sn[i + m_pitch / 2] * w[i + m_pitch / 2];
}
for i in 0..nw / 2 {
Sw[FFT_ENC - nw / 2 + i].r =
Sn[i + m_pitch / 2 - nw / 2] * w[i + m_pitch / 2 - nw / 2];
}
codec2_fft_inplace(fft_fwd_cfg, Sw);
}
}
#[derive(Clone, Debug)]
pub struct lsp_codebook {
pub k: usize, pub log2m: i32, pub m: usize, pub cb: &'static [f32], }
#[derive(Copy, Clone)]
pub struct kiss_fft_cpx {
pub r: kiss_fft_scalar,
pub i: kiss_fft_scalar,
}
impl kiss_fft_cpx {
pub fn new() -> Self {
Self { r: 0.0, i: 0.0 }
}
pub fn kf_cexp(phase: f64) -> Self {
Self {
r: phase.cos() as f32,
i: phase.sin() as f32,
}
}
}
impl std::fmt::Debug for kiss_fft_cpx {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{},{}", self.r, self.i))
}
}
pub type COMP = kiss_fft_cpx;
#[derive(Clone, Debug)]
pub struct kiss_fft_state {
pub nfft: usize,
pub inverse: i32,
pub factors: [usize; 2 * MAXFACTORS],
pub twiddles: Vec<kiss_fft_cpx>,
}
impl kiss_fft_state {
pub fn new(nfft: usize, inverse_fft: i32) -> Self {
let mut twiddles = Vec::with_capacity(nfft);
let mut factors = [0; 2 * MAXFACTORS];
for i in 0..nfft {
let mut phase = -2.0 * PI * (i as f64) / (nfft as f64);
if inverse_fft != 0 {
phase *= -1.0;
}
twiddles.push(kiss_fft_cpx::kf_cexp(phase));
}
let mut n = nfft;
let mut p = 4;
let floor_sqrt = (n as f64).sqrt().floor() as usize;
let mut idx = 0;
loop {
while (n % p) != 0 {
match p {
4 => p = 2,
2 => p = 3,
_ => p += 2,
}
if p > floor_sqrt {
p = n; }
}
n /= p;
factors[idx] = p;
idx += 1;
factors[idx] = n;
idx += 1;
if n <= 1 {
break;
} }
Self {
nfft: nfft,
inverse: inverse_fft,
factors: factors,
twiddles: twiddles,
}
}
}
#[derive(Clone, Debug)]
pub struct kiss_fftr_state {
pub substate: kiss_fft_cfg,
pub tmpbuf: Vec<kiss_fft_cpx>,
pub super_twiddles: Vec<kiss_fft_cpx>,
}
impl kiss_fftr_state {
pub fn new(mut nfft: usize, inverse_fft: i32) -> Self {
nfft = nfft / 2;
let mut res = Self {
substate: kiss_fft_state::new(nfft, inverse_fft),
tmpbuf: vec![kiss_fft_cpx::new(); nfft],
super_twiddles: vec![kiss_fft_cpx::new(); nfft / 2],
};
for i in 0..nfft / 2 {
let mut phase =
-3.14159265358979323846264338327 * ((i as f64 + 1.0) / nfft as f64 + 0.5);
if inverse_fft != 0 {
phase *= -1.0;
}
res.super_twiddles[i] = kiss_fft_cpx::kf_cexp(phase);
}
res
}
}
#[derive(Clone, Debug)]
pub struct NLP {
pub Fs: i32, pub m: usize,
pub w: [f32; PMAX_M / DEC], pub sq: [f32; PMAX_M], pub mem_x: f32,
pub mem_y: f32, pub mem_fir: [f32; NLP_NTAP], pub fft_cfg: codec2_fft_cfg, pub Sn16k: Vec<f32>, }
impl NLP {
pub fn new(c2const: &C2const) -> Self {
let (m, vsize) = if c2const.Fs == 16000 {
(
c2const.m_pitch / 2,
FDMDV_OS_TAPS_16K as usize + c2const.n_samp,
)
} else {
(c2const.m_pitch, 0)
};
let mut w = [0.0; PMAX_M / DEC];
for i in 0..m / DEC {
w[i] =
0.5 - 0.5 * (2.0 * PI as f32 * i as f32 / (m as f32 / DEC as f32 - 1.0)).cos();
}
Self {
Fs: c2const.Fs, m: m,
w: w, sq: [0.0; PMAX_M], mem_x: 0.0,
mem_y: 0.0, mem_fir: [0.0; NLP_NTAP], fft_cfg: kiss_fft_state::new(PE_FFT_SIZE, 0), Sn16k: vec![0.0; vsize], }
}
}
#[derive(Clone, Debug, Copy)]
pub struct MODEL {
pub Wo: f32, pub L: usize, pub A: [f32; MAX_AMP + 1], pub phi: [f32; MAX_AMP + 1], pub voiced: i32, }
impl MODEL {
pub fn new(p_max: f32) -> Self {
let wo = TWO_PI / p_max;
Self {
Wo: wo, L: (PI / wo as f64).floor() as usize, A: [0.0; MAX_AMP + 1], phi: [0.0; MAX_AMP + 1], voiced: 0, }
}
}
}
use inner::*;
type kiss_fft_scalar = f32;
type kiss_fft_cfg = kiss_fft_state;
const PE_FFT_SIZE: usize = 512;
const MAXFACTORS: usize = 32;
type codec2_fft_cfg = kiss_fft_state;
type codec2_fftr_cfg = kiss_fftr_state;
type kiss_fftr_cfg = kiss_fftr_state;
fn codec2_fft(cfg: &kiss_fft_cfg, fin: &[kiss_fft_cpx], fout: &mut [kiss_fft_cpx]) {
kiss_fft::kiss_fft(cfg, fin, fout);
}
fn codec2_fftr(cfg: &mut codec2_fftr_cfg, inp: &[f32], out: &mut [kiss_fft_cpx]) {
kiss_fft::kiss_fftr(cfg, inp, out);
}
fn codec2_fftri(cfg: &mut codec2_fftr_cfg, inp: &[kiss_fft_cpx], out: &mut [f32]) {
kiss_fft::kiss_fftri(cfg, inp, out);
}
fn codec2_fft_inplace(cfg: &codec2_fft_cfg, inout: &mut [kiss_fft_cpx]) {
let mut in_ = [kiss_fft_cpx::new(); 512];
if cfg.nfft <= 512 {
in_[..cfg.nfft].copy_from_slice(&inout[..cfg.nfft]);
kiss_fft::kiss_fft(cfg, &in_, inout);
} else {
kiss_fft::kiss_fft(cfg, &inout.to_vec(), inout);
}
}
const PMAX_M: usize = 320;
const DEC: usize = 5;
const NLP_NTAP: usize = 48;
const BPF_N: usize = 101;
const LPCPF_BETA: f32 = 0.2;
const LPCPF_GAMMA: f32 = 0.5;
#[derive(Clone, Debug)]
struct Codec2Internal {
mode: Codec2Mode,
c2const: C2const,
Fs: i32,
n_samp: usize,
m_pitch: usize,
fft_fwd_cfg: codec2_fft_cfg, fftr_fwd_cfg: codec2_fftr_cfg, w: Vec<f32>, W: [f32; FFT_ENC], Pn: Vec<f32>, bpf_buf: Vec<f32>, Sn: Vec<f32>, hpf_states: [f32; 2], nlp: NLP, gray: i32,
fftr_inv_cfg: codec2_fftr_cfg, Sn_: Vec<f32>, ex_phase: f32, bg_est: f32, prev_f0_enc: f32, prev_model_dec: MODEL, prev_lsps_dec: [f32; LPC_ORD], prev_e_dec: f32,
lpc_pf: i32, bass_boost: i32, beta: f32, gamma: f32,
xq_enc: [f32; 2], xq_dec: [f32; 2],
smoothing: i32, se: f32, nse: u32, post_filter_en: i32,
}
fn make_synthesis_window(c2const: &C2const, Pn: &mut [f32]) {
let n_samp = c2const.n_samp;
let tw = c2const.tw;
for i in 0..n_samp / 2 - tw {
Pn[i] = 0.0;
}
let mut win = 0.0;
for i in n_samp / 2 - tw..n_samp / 2 + tw {
Pn[i] = win;
win += 1.0 / (2.0 * tw as f32);
}
for i in n_samp / 2 + tw..3 * n_samp / 2 - tw {
Pn[i] = 1.0;
}
win = 1.0;
for i in 3 * n_samp / 2 - tw..3 * n_samp / 2 + tw {
Pn[i] = win;
win -= 1.0 / (2.0 * tw as f32);
}
for i in 3 * n_samp / 2 + tw..2 * n_samp {
Pn[i] = 0.0;
}
}
fn make_analysis_window(
c2const: &C2const,
fft_fwd_cfg: &codec2_fft_cfg,
w: &mut [f32],
W: &mut [f32],
) {
let mut wshift = [kiss_fft_cpx::new(); FFT_ENC];
let m_pitch = c2const.m_pitch;
let nw = c2const.nw;
let mut m = 0.0;
for i in 0..m_pitch / 2 - nw / 2 {
w[i] = 0.0;
}
let mut j = 0;
for i in m_pitch / 2 - nw / 2..m_pitch / 2 + nw / 2 {
w[i] = 0.5 - 0.5 * (TWO_PI * (j as f32) / ((nw as f32) - 1.0)).cos();
m += w[i] * w[i];
j += 1;
}
for i in m_pitch / 2 + nw / 2..m_pitch {
w[i] = 0.0;
}
m = 1.0 / (m * FFT_ENC as f32).sqrt();
for i in 0..m_pitch {
w[i] *= m;
}
let mut temp = [kiss_fft_cpx::new(); FFT_ENC];
for i in 0..FFT_ENC {
wshift[i].r = 0.0;
wshift[i].i = 0.0;
}
for i in 0..(nw / 2) {
wshift[i].r = w[i + (m_pitch) / 2];
}
let mut j = m_pitch / 2 - nw / 2;
for i in FFT_ENC - nw / 2..FFT_ENC {
wshift[i].r = w[j];
j += 1;
}
codec2_fft(fft_fwd_cfg, &wshift[..], &mut temp);
for i in 0..FFT_ENC / 2 {
W[i] = temp[i + FFT_ENC / 2].r;
W[i + FFT_ENC / 2] = temp[i].r;
}
}
const WordSize: usize = 8;
const IndexMask: usize = 0x7;
const ShiftRight: usize = 3;
fn pack(
bitArray: &mut [u8], bitIndex: &mut usize, field: i32, fieldWidth: u32, ) {
pack_natural_or_gray(bitArray, bitIndex, field, fieldWidth, 1);
}
fn pack_natural_or_gray(
bitArray: &mut [u8], bitIndex: &mut usize, mut field: i32, mut fieldWidth: u32, gray: u32, ) {
if gray > 0 {
field = (field >> 1) ^ field;
}
while fieldWidth != 0 {
let bI = *bitIndex;
let bitsLeft = (WordSize - (bI & IndexMask)) as u32;
let sliceWidth = if bitsLeft < fieldWidth {
bitsLeft
} else {
fieldWidth
};
let wordIndex = bI >> ShiftRight;
bitArray[wordIndex] |=
(((field >> (fieldWidth - sliceWidth)) << (bitsLeft - sliceWidth)) & 0xFF) as u8;
*bitIndex = bI + sliceWidth as usize;
fieldWidth -= sliceWidth;
}
}
fn unpack(
bitArray: &[u8], bitIndex: &mut u32, fieldWidth: u32, ) -> i32 {
unpack_natural_or_gray(bitArray, bitIndex, fieldWidth, 1)
}
fn unpack_natural_or_gray(
bitArray: &[u8], bitIndex: &mut u32, mut fieldWidth: u32, gray: u32, ) -> i32 {
let mut field = 0;
while fieldWidth != 0 {
let bI = *bitIndex;
let bitsLeft = WordSize as u32 - (bI & IndexMask as u32);
let sliceWidth = if bitsLeft < fieldWidth {
bitsLeft
} else {
fieldWidth
};
field |= ((bitArray[(bI >> ShiftRight) as usize] as usize >> (bitsLeft - sliceWidth))
& ((1 << sliceWidth) - 1))
<< (fieldWidth - sliceWidth);
*bitIndex = bI + sliceWidth;
fieldWidth -= sliceWidth;
}
if gray != 0 {
let mut t = field ^ (field >> 8);
t ^= t >> 4;
t ^= t >> 2;
t ^= t >> 1;
t as i32
} else {
field as i32
}
}
#[derive(Clone, Debug, Copy)]
#[non_exhaustive]
pub enum Codec2Mode {
MODE_3200,
MODE_2400,
MODE_1600,
MODE_1400,
MODE_1300,
MODE_1200,
}
use Codec2Mode::*;
#[derive(Clone, Debug)]
pub struct Codec2 {
internal: Codec2Internal,
}
impl Codec2 {
pub fn new(mode: Codec2Mode) -> Self {
let c2const = C2const::new(8000, N_S);
let n_samp = c2const.n_samp;
let m_pitch = c2const.m_pitch;
let mut c2 = Self {
internal: Codec2Internal {
mode: mode,
Fs: c2const.Fs,
n_samp: n_samp,
m_pitch: m_pitch,
fft_fwd_cfg: kiss_fft_state::new(FFT_ENC, 0), fftr_fwd_cfg: kiss_fftr_state::new(FFT_ENC, 0), w: vec![0.0; m_pitch], W: [0.0; FFT_ENC], Pn: vec![0.0; 2 * n_samp], bpf_buf: vec![0.0; BPF_N + 4 * n_samp], Sn: vec![1.0; m_pitch], hpf_states: [0.0; 2],
nlp: NLP::new(&c2const), gray: 1,
fftr_inv_cfg: kiss_fftr_state::new(FFT_DEC, 1), Sn_: vec![0.0; m_pitch], prev_f0_enc: 1.0 / P_MAX_S,
bg_est: 0.0,
ex_phase: 0.0,
prev_model_dec: MODEL::new(c2const.p_max as f32),
c2const: c2const,
prev_lsps_dec: [0.0; LPC_ORD],
prev_e_dec: 1.0,
lpc_pf: 1, bass_boost: 1, beta: LPCPF_BETA, gamma: LPCPF_GAMMA,
xq_enc: [0.0; 2], xq_dec: [0.0; 2],
smoothing: 0, se: 0.0,
nse: 0,
post_filter_en: 1,
},
};
for i in 0..LPC_ORD {
c2.internal.prev_lsps_dec[i] = (i as f64 * PI / (LPC_ORD as f64 + 1.0)) as f32;
}
make_analysis_window(
&c2.internal.c2const,
&c2.internal.fft_fwd_cfg,
&mut c2.internal.w,
&mut c2.internal.W,
);
make_synthesis_window(&c2.internal.c2const, &mut c2.internal.Pn);
c2
}
pub fn bits_per_frame(&self) -> usize {
match self.internal.mode {
MODE_3200 => 64,
MODE_2400 => 48,
MODE_1600 => 64,
MODE_1400 => 56,
MODE_1300 => 52,
MODE_1200 => 48,
}
}
pub fn samples_per_frame(&self) -> usize {
match self.internal.mode {
MODE_3200 | MODE_2400 => 160,
MODE_1600 | MODE_1400 | MODE_1300 | MODE_1200 => 320,
}
}
pub fn encode(&mut self, bits: &mut [u8], speech: &[i16]) {
match self.internal.mode {
MODE_3200 => self.codec2_encode_3200(bits, speech),
MODE_2400 => self.codec2_encode_2400(bits, speech),
MODE_1600 => self.codec2_encode_1600(bits, speech),
MODE_1400 => self.codec2_encode_1400(bits, speech),
MODE_1300 => self.codec2_encode_1300(bits, speech),
MODE_1200 => self.codec2_encode_1200(bits, speech),
}
}
pub fn decode(&mut self, speech: &mut [i16], bits: &[u8]) {
match self.internal.mode {
MODE_3200 => self.codec2_decode_3200(speech, bits),
MODE_2400 => self.codec2_decode_2400(speech, bits),
MODE_1600 => self.codec2_decode_1600(speech, bits),
MODE_1400 => self.codec2_decode_1400(speech, bits),
MODE_1300 => self.codec2_decode_1300(speech, bits, 0.0),
MODE_1200 => self.codec2_decode_1200(speech, bits),
}
}
fn codec2_encode_3200(&mut self, bits: &mut [u8], speech: &[i16]) {
let mut model = MODEL::new(self.internal.c2const.p_max as f32);
let mut ak = [0.0; LPC_ORD + 1]; let mut lsps = [0.0; LPC_ORD]; let mut lspd_indexes = [0; LPC_ORD];
let mut nbit = 0;
let nbyte = (self.bits_per_frame() + 7) / 8;
for i in 0..nbyte {
bits[i] = 0;
}
self.analyse_one_frame(&mut model, speech);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let Wo_index = encode_Wo(&self.internal.c2const, model.Wo, WO_BITS);
pack(bits, &mut nbit, Wo_index, WO_BITS as u32);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let e_index = encode_energy(e, E_BITS);
pack(bits, &mut nbit, e_index, E_BITS as u32);
encode_lspds_scalar(&mut lspd_indexes, &lsps, LPC_ORD);
for i in 0..LSPD_SCALAR_INDEXES {
pack(bits, &mut nbit, lspd_indexes[i], lspd_bits(i) as u32);
}
}
fn codec2_decode_3200(&mut self, speech: &mut [i16], bits: &[u8]) {
let mut ak = [[0.0; LPC_ORD + 1]; 2];
let mut nbit = 0;
let mut Aw = [COMP::new(); FFT_ENC];
let mut model = [MODEL::new(self.internal.c2const.p_max as f32); 2];
model[0].voiced = unpack(bits, &mut nbit, 1);
model[1].voiced = unpack(bits, &mut nbit, 1);
let Wo_index = unpack(bits, &mut nbit, WO_BITS as u32);
model[1].Wo = decode_Wo(&self.internal.c2const, Wo_index, WO_BITS);
model[1].L = (PI / model[1].Wo as f64) as usize;
let mut e = [0.0; 2];
let e_index = unpack(bits, &mut nbit, E_BITS as u32);
e[1] = decode_energy(e_index, E_BITS);
let mut lspd_indexes = [0; LPC_ORD];
for i in 0..LSPD_SCALAR_INDEXES {
lspd_indexes[i] = unpack(bits, &mut nbit, lspd_bits(i) as u32) as usize;
}
let mut lsps = [[0.0; LPC_ORD]; 2];
decode_lspds_scalar(&mut lsps[1][0..], &lspd_indexes, LPC_ORD);
model[0] = interp_Wo(
&model[0],
&self.internal.prev_model_dec,
&model[1],
self.internal.c2const.Wo_min,
);
e[0] = interp_energy(self.internal.prev_e_dec, e[1]);
let (lsps0, lsps1) = lsps.split_at_mut(1);
interpolate_lsp_ver2(
&mut lsps0[0][0..],
&self.internal.prev_lsps_dec,
&mut lsps1[0][0..],
0.5,
LPC_ORD,
);
for i in 0..2 {
lsp_to_lpc(&lsps[i][0..], &mut ak[i][0..], LPC_ORD);
let mut snr = 0.0;
aks_to_M2(
&mut self.internal.fftr_fwd_cfg,
&ak[i][..],
LPC_ORD,
&mut model[i],
e[i],
&mut snr,
0,
0,
self.internal.lpc_pf,
self.internal.bass_boost,
self.internal.beta,
self.internal.gamma,
&mut Aw,
);
apply_lpc_correction(&mut model[i]);
self.synthesise_one_frame(
&mut speech[self.internal.n_samp * i..],
&mut model[i],
&mut Aw,
1.0,
);
}
self.internal.prev_model_dec = model[1];
self.internal.prev_e_dec = e[1];
for i in 0..LPC_ORD {
self.internal.prev_lsps_dec[i] = lsps[1][i];
}
}
fn codec2_encode_2400(&mut self, bits: &mut [u8], speech: &[i16]) {
let mut model = MODEL::new(self.internal.c2const.p_max as f32);
let mut ak = [0.0; LPC_ORD + 1]; let mut lsps = [0.0; LPC_ORD]; let mut lsp_indexes = [0; LPC_ORD];
let mut nbit = 0;
for i in 0..(self.bits_per_frame() + 7) / 8 {
bits[i] = 0;
}
self.analyse_one_frame(&mut model, speech);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let WoE_index = encode_WoE(&model, e, &mut self.internal.xq_enc);
pack(bits, &mut nbit, WoE_index, WO_E_BITS);
encode_lsps_scalar(&mut lsp_indexes, &lsps, LPC_ORD);
for i in 0..LSP_SCALAR_INDEXES {
pack(bits, &mut nbit, lsp_indexes[i], lsp_bits(i));
}
let spare = 0;
pack(bits, &mut nbit, spare, 2);
}
fn codec2_decode_2400(&mut self, speech: &mut [i16], bits: &[u8]) {
let mut model = [MODEL::new(self.internal.c2const.p_max as f32); 2];
let mut lsp_indexes = [0; LPC_ORD];
let mut lsps = [[0.0; LPC_ORD]; 2];
let mut e = [0.0; 2];
let mut snr = 0.0;
let mut ak = [[0.0; LPC_ORD + 1]; 2];
let mut nbit = 0;
let mut Aw = [COMP::new(); FFT_ENC];
model[0].voiced = unpack(bits, &mut nbit, 1);
model[1].voiced = unpack(bits, &mut nbit, 1);
let WoE_index = unpack(bits, &mut nbit, WO_E_BITS) as usize;
decode_WoE(
&self.internal.c2const,
&mut model[1],
&mut e[1],
&mut self.internal.xq_dec,
WoE_index,
);
for i in 0..LSP_SCALAR_INDEXES {
lsp_indexes[i] = unpack(bits, &mut nbit, lsp_bits(i)) as usize;
}
decode_lsps_scalar(&mut lsps[1][0..], &lsp_indexes, LPC_ORD);
check_lsp_order(&mut lsps[1][0..], LPC_ORD);
bw_expand_lsps(&mut lsps[1][0..], LPC_ORD, 50.0, 100.0);
model[0] = interp_Wo(
&model[0],
&self.internal.prev_model_dec,
&model[1],
self.internal.c2const.Wo_min,
);
e[0] = interp_energy(self.internal.prev_e_dec, e[1]);
let (lsps0, lsps1) = lsps.split_at_mut(1);
interpolate_lsp_ver2(
&mut lsps0[0][0..],
&self.internal.prev_lsps_dec,
&mut lsps1[0][0..],
0.5,
LPC_ORD,
);
for i in 0..2 {
lsp_to_lpc(&lsps[i][0..], &mut ak[i][0..], LPC_ORD);
aks_to_M2(
&mut self.internal.fftr_fwd_cfg,
&ak[i][..],
LPC_ORD,
&mut model[i],
e[i],
&mut snr,
0,
0,
self.internal.lpc_pf,
self.internal.bass_boost,
self.internal.beta,
self.internal.gamma,
&mut Aw,
);
apply_lpc_correction(&mut model[i]);
self.synthesise_one_frame(
&mut speech[self.internal.n_samp * i..],
&mut model[i],
&mut Aw,
1.0,
);
}
self.internal.prev_model_dec = model[1];
self.internal.prev_e_dec = e[1];
for i in 0..LPC_ORD {
self.internal.prev_lsps_dec[i] = lsps[1][i];
}
}
fn codec2_encode_1600(&mut self, bits: &mut [u8], speech: &[i16]) {
let mut model = MODEL::new(self.internal.c2const.p_max as f32);
let mut ak = [0.0; LPC_ORD + 1]; let mut lsps = [0.0; LPC_ORD]; let mut lsp_indexes = [0; LPC_ORD];
let mut nbit = 0;
for i in 0..(self.bits_per_frame() + 7) / 8 {
bits[i] = 0;
}
self.analyse_one_frame(&mut model, speech);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let mut Wo_index = encode_Wo(&self.internal.c2const, model.Wo, WO_BITS);
pack(bits, &mut nbit, Wo_index, WO_BITS as u32);
let mut e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let mut e_index = encode_energy(e, E_BITS);
pack(bits, &mut nbit, e_index, E_BITS as u32);
self.analyse_one_frame(&mut model, &speech[2 * self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[3 * self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
Wo_index = encode_Wo(&self.internal.c2const, model.Wo, WO_BITS);
pack(bits, &mut nbit, Wo_index, WO_BITS as u32);
e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
e_index = encode_energy(e, E_BITS);
pack(bits, &mut nbit, e_index, E_BITS as u32);
encode_lsps_scalar(&mut lsp_indexes, &lsps, LPC_ORD);
for i in 0..LSP_SCALAR_INDEXES {
pack(bits, &mut nbit, lsp_indexes[i], lsp_bits(i));
}
assert_eq!(nbit, self.bits_per_frame());
}
fn codec2_decode_1600(&mut self, speech: &mut [i16], bits: &[u8]) {
let mut model = [MODEL::new(self.internal.c2const.p_max as f32); 4];
let mut lsp_indexes = [0; LPC_ORD];
let mut lsps = [[0.0; LPC_ORD]; 4];
let mut e = [0.0; 4];
let mut snr = 0.0;
let mut ak = [[0.0; LPC_ORD + 1]; 4];
let mut nbit = 0;
let mut Aw = [COMP::new(); FFT_ENC];
model[0].voiced = unpack(bits, &mut nbit, 1);
model[1].voiced = unpack(bits, &mut nbit, 1);
let Wo_index = unpack(bits, &mut nbit, WO_BITS as u32);
model[1].Wo = decode_Wo(&self.internal.c2const, Wo_index, WO_BITS);
model[1].L = (PI as f32 / model[1].Wo) as usize;
let mut e_index = unpack(bits, &mut nbit, E_BITS as u32);
e[1] = decode_energy(e_index, E_BITS);
model[2].voiced = unpack(bits, &mut nbit, 1);
model[3].voiced = unpack(bits, &mut nbit, 1);
let Wo_index = unpack(bits, &mut nbit, WO_BITS as u32);
model[3].Wo = decode_Wo(&self.internal.c2const, Wo_index, WO_BITS);
model[3].L = (PI as f32 / model[3].Wo) as usize;
e_index = unpack(bits, &mut nbit, E_BITS as u32);
e[3] = decode_energy(e_index, E_BITS);
for i in 0..LSP_SCALAR_INDEXES {
lsp_indexes[i] = unpack(bits, &mut nbit, lsp_bits(i)) as usize;
}
decode_lsps_scalar(&mut lsps[3][0..], &lsp_indexes, LPC_ORD);
check_lsp_order(&mut lsps[3][0..], LPC_ORD);
bw_expand_lsps(&mut lsps[3][0..], LPC_ORD, 50.0, 100.0);
model[0] = interp_Wo(
&model[0],
&self.internal.prev_model_dec,
&model[1],
self.internal.c2const.Wo_min,
);
e[0] = interp_energy(self.internal.prev_e_dec, e[1]);
model[2] = interp_Wo(
&model[2],
&model[1],
&model[3],
self.internal.c2const.Wo_min,
);
e[2] = interp_energy(e[1], e[3]);
for i in 0..3 {
let weight = 0.25 + i as f32 * 0.25;
let lsps3 = lsps[3];
interpolate_lsp_ver2(
&mut lsps[i][0..],
&self.internal.prev_lsps_dec,
&lsps3[0..],
weight,
LPC_ORD,
);
}
for i in 0..4 {
lsp_to_lpc(&lsps[i][0..], &mut ak[i][0..], LPC_ORD);
aks_to_M2(
&mut self.internal.fftr_fwd_cfg,
&ak[i][0..],
LPC_ORD,
&mut model[i],
e[i],
&mut snr,
0,
0,
self.internal.lpc_pf,
self.internal.bass_boost,
self.internal.beta,
self.internal.gamma,
&mut Aw,
);
apply_lpc_correction(&mut model[i]);
self.synthesise_one_frame(
&mut speech[self.internal.n_samp * i..],
&mut model[i],
&Aw,
1.0,
);
}
self.internal.prev_model_dec = model[3];
self.internal.prev_e_dec = e[3];
for i in 0..LPC_ORD {
self.internal.prev_lsps_dec[i] = lsps[3][i];
}
}
fn codec2_encode_1400(&mut self, bits: &mut [u8], speech: &[i16]) {
let mut model = MODEL::new(self.internal.c2const.p_max as f32);
let mut lsps = [0.0; LPC_ORD]; let mut ak = [0.0; LPC_ORD + 1]; let mut lsp_indexes = [0; LPC_ORD];
let mut nbit = 0;
let nbyte = (self.bits_per_frame() + 7) / 8;
for i in 0..nbyte {
bits[i] = 0;
}
self.analyse_one_frame(&mut model, speech);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let WoE_index = encode_WoE(&model, e, &mut self.internal.xq_enc);
pack(bits, &mut nbit, WoE_index, WO_E_BITS);
self.analyse_one_frame(&mut model, &speech[2 * self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[3 * self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let WoE_index = encode_WoE(&model, e, &mut self.internal.xq_enc);
pack(bits, &mut nbit, WoE_index, WO_E_BITS);
encode_lsps_scalar(&mut lsp_indexes, &lsps, LPC_ORD);
for i in 0..LSP_SCALAR_INDEXES {
pack(bits, &mut nbit, lsp_indexes[i], lsp_bits(i));
}
assert_eq!(nbit, self.bits_per_frame());
}
fn codec2_decode_1400(&mut self, speech: &mut [i16], bits: &[u8]) {
let mut model = [MODEL::new(self.internal.c2const.p_max as f32); 4];
let mut lsp_indexes = [0; LPC_ORD];
let mut lsps = [[0.0; LPC_ORD]; 4];
let mut e = [0.0; 4];
let mut snr = 0.0;
let mut ak = [[0.0; LPC_ORD + 1]; 4];
let mut nbit = 0;
let mut Aw = [COMP::new(); FFT_ENC];
model[0].voiced = unpack(bits, &mut nbit, 1);
model[1].voiced = unpack(bits, &mut nbit, 1);
let WoE_index = unpack(bits, &mut nbit, WO_E_BITS);
decode_WoE(
&self.internal.c2const,
&mut model[1],
&mut e[1],
&mut self.internal.xq_dec,
WoE_index as usize,
);
model[2].voiced = unpack(bits, &mut nbit, 1);
model[3].voiced = unpack(bits, &mut nbit, 1);
let WoE_index = unpack(bits, &mut nbit, WO_E_BITS);
decode_WoE(
&self.internal.c2const,
&mut model[3],
&mut e[3],
&mut self.internal.xq_dec,
WoE_index as usize,
);
for i in 0..LSP_SCALAR_INDEXES {
lsp_indexes[i] = unpack(bits, &mut nbit, lsp_bits(i)) as usize;
}
decode_lsps_scalar(&mut lsps[3][0..], &lsp_indexes, LPC_ORD);
check_lsp_order(&mut lsps[3][0..], LPC_ORD);
bw_expand_lsps(&mut lsps[3][0..], LPC_ORD, 50.0, 100.0);
model[0] = interp_Wo(
&model[0],
&self.internal.prev_model_dec,
&model[1],
self.internal.c2const.Wo_min,
);
e[0] = interp_energy(self.internal.prev_e_dec, e[1]);
model[2] = interp_Wo(
&model[2],
&model[1],
&model[3],
self.internal.c2const.Wo_min,
);
e[2] = interp_energy(e[1], e[3]);
for i in 0..3 {
let weight = 0.25 + i as f32 * 0.25;
let lsps3 = lsps[3];
interpolate_lsp_ver2(
&mut lsps[i][0..],
&self.internal.prev_lsps_dec,
&lsps3[0..],
weight,
LPC_ORD,
);
}
for i in 0..4 {
lsp_to_lpc(&lsps[i][0..], &mut ak[i][0..], LPC_ORD);
aks_to_M2(
&mut self.internal.fftr_fwd_cfg,
&ak[i][0..],
LPC_ORD,
&mut model[i],
e[i],
&mut snr,
0,
0,
self.internal.lpc_pf,
self.internal.bass_boost,
self.internal.beta,
self.internal.gamma,
&mut Aw,
);
apply_lpc_correction(&mut model[i]);
self.synthesise_one_frame(
&mut speech[self.internal.n_samp * i..],
&mut model[i],
&Aw,
1.0,
);
}
self.internal.prev_model_dec = model[3];
self.internal.prev_e_dec = e[3];
for i in 0..LPC_ORD {
self.internal.prev_lsps_dec[i] = lsps[3][i];
}
}
fn codec2_encode_1300(&mut self, bits: &mut [u8], speech: &[i16]) {
let mut model = MODEL::new(self.internal.c2const.p_max as f32);
let mut lsps = [0.0; LPC_ORD]; let mut ak = [0.0; LPC_ORD + 1]; let mut lsp_indexes = [0; LPC_ORD];
let mut nbit = 0;
let nbyte = (self.bits_per_frame() + 7) / 8;
for i in 0..nbyte {
bits[i] = 0;
}
self.analyse_one_frame(&mut model, speech);
pack_natural_or_gray(bits, &mut nbit, model.voiced, 1, self.internal.gray as u32);
self.analyse_one_frame(&mut model, &speech[self.internal.n_samp..]);
pack_natural_or_gray(bits, &mut nbit, model.voiced, 1, self.internal.gray as u32);
self.analyse_one_frame(&mut model, &speech[2 * self.internal.n_samp..]);
pack_natural_or_gray(bits, &mut nbit, model.voiced, 1, self.internal.gray as u32);
self.analyse_one_frame(&mut model, &speech[3 * self.internal.n_samp..]);
pack_natural_or_gray(bits, &mut nbit, model.voiced, 1, self.internal.gray as u32);
let Wo_index = encode_Wo(&self.internal.c2const, model.Wo, WO_BITS);
pack_natural_or_gray(
bits,
&mut nbit,
Wo_index,
WO_BITS as u32,
self.internal.gray as u32,
);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let e_index = encode_energy(e, E_BITS);
pack_natural_or_gray(
bits,
&mut nbit,
e_index,
E_BITS as u32,
self.internal.gray as u32,
);
encode_lsps_scalar(&mut lsp_indexes, &lsps, LPC_ORD);
for i in 0..LSP_SCALAR_INDEXES {
pack_natural_or_gray(
bits,
&mut nbit,
lsp_indexes[i],
lsp_bits(i),
self.internal.gray as u32,
);
}
assert_eq!(nbit, self.bits_per_frame());
}
fn codec2_decode_1300(&mut self, speech: &mut [i16], bits: &[u8], ber_est: f32) {
let mut model = [MODEL::new(self.internal.c2const.p_max as f32); 4];
let mut lsp_indexes = [0; LPC_ORD];
let mut lsps = [[0.0; LPC_ORD]; 4];
let mut e = [0.0; 4];
let mut snr = 0.0;
let mut ak = [[0.0; LPC_ORD + 1]; 4];
let mut nbit = 0;
let mut Aw = [COMP::new(); FFT_ENC];
model[0].voiced = unpack_natural_or_gray(bits, &mut nbit, 1, self.internal.gray as u32);
model[1].voiced = unpack_natural_or_gray(bits, &mut nbit, 1, self.internal.gray as u32);
model[2].voiced = unpack_natural_or_gray(bits, &mut nbit, 1, self.internal.gray as u32);
model[3].voiced = unpack_natural_or_gray(bits, &mut nbit, 1, self.internal.gray as u32);
let Wo_index =
unpack_natural_or_gray(bits, &mut nbit, WO_BITS as u32, self.internal.gray as u32);
model[3].Wo = decode_Wo(&self.internal.c2const, Wo_index, WO_BITS);
model[3].L = (PI as f32 / model[3].Wo) as usize;
let e_index =
unpack_natural_or_gray(bits, &mut nbit, E_BITS as u32, self.internal.gray as u32);
e[3] = decode_energy(e_index, E_BITS);
for i in 0..LSP_SCALAR_INDEXES {
lsp_indexes[i] =
unpack_natural_or_gray(bits, &mut nbit, lsp_bits(i), self.internal.gray as u32)
as usize;
}
decode_lsps_scalar(&mut lsps[3][0..], &lsp_indexes, LPC_ORD);
check_lsp_order(&mut lsps[3][0..], LPC_ORD);
bw_expand_lsps(&mut lsps[3][0..], LPC_ORD, 50.0, 100.0);
if ber_est > 0.15 {
model[0].voiced = 0;
model[1].voiced = 0;
model[2].voiced = 0;
model[3].voiced = 0;
e[3] = decode_energy(10, E_BITS);
bw_expand_lsps(&mut lsps[3][0..], LPC_ORD, 200.0, 200.0);
}
for i in 0..3 {
let weight = 0.25 + i as f32 * 0.25;
let lsps3 = lsps[3];
interpolate_lsp_ver2(
&mut lsps[i][0..],
&self.internal.prev_lsps_dec,
&lsps3[0..],
weight,
LPC_ORD,
);
model[i] = interp_Wo2(
&model[i],
&self.internal.prev_model_dec,
&model[3],
weight,
self.internal.c2const.Wo_min,
);
e[i] = interp_energy2(self.internal.prev_e_dec, e[3], weight);
}
for i in 0..4 {
lsp_to_lpc(&lsps[i][0..], &mut ak[i][0..], LPC_ORD);
aks_to_M2(
&mut self.internal.fftr_fwd_cfg,
&ak[i][0..],
LPC_ORD,
&mut model[i],
e[i],
&mut snr,
0,
0,
self.internal.lpc_pf,
self.internal.bass_boost,
self.internal.beta,
self.internal.gamma,
&mut Aw,
);
apply_lpc_correction(&mut model[i]);
self.synthesise_one_frame(
&mut speech[self.internal.n_samp * i..],
&mut model[i],
&Aw,
1.0,
);
}
self.internal.prev_model_dec = model[3];
self.internal.prev_e_dec = e[3];
for i in 0..LPC_ORD {
self.internal.prev_lsps_dec[i] = lsps[3][i];
}
}
fn codec2_encode_1200(&mut self, bits: &mut [u8], speech: &[i16]) {
let mut model = MODEL::new(self.internal.c2const.p_max as f32);
let mut lsps = [0.0; LPC_ORD]; let mut lsps_ = [0.0; LPC_ORD]; let mut ak = [0.0; LPC_ORD + 1]; let mut lsp_indexes = [0; LPC_ORD];
let spare = 0;
let mut nbit = 0;
let nbyte = (self.bits_per_frame() + 7) / 8;
for i in 0..nbyte {
bits[i] = 0;
}
self.analyse_one_frame(&mut model, speech);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let WoE_index = encode_WoE(&model, e, &mut self.internal.xq_enc);
pack(bits, &mut nbit, WoE_index, WO_E_BITS);
self.analyse_one_frame(&mut model, &speech[2 * self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
self.analyse_one_frame(&mut model, &speech[3 * self.internal.n_samp..]);
pack(bits, &mut nbit, model.voiced, 1);
let e = speech_to_uq_lsps(
&mut lsps,
&mut ak,
&self.internal.Sn,
&self.internal.w,
self.internal.m_pitch,
LPC_ORD,
);
let WoE_index = encode_WoE(&model, e, &mut self.internal.xq_enc);
pack(bits, &mut nbit, WoE_index, WO_E_BITS);
encode_lsps_vq(&mut lsp_indexes, &mut lsps, &mut lsps_, LPC_ORD);
for i in 0..LSP_PRED_VQ_INDEXES {
pack(
bits,
&mut nbit,
lsp_indexes[i] as i32,
lsp_pred_vq_bits(i) as u32,
);
}
pack(bits, &mut nbit, spare, 1);
assert_eq!(nbit, self.bits_per_frame());
}
fn codec2_decode_1200(&mut self, speech: &mut [i16], bits: &[u8]) {
let mut model = [MODEL::new(self.internal.c2const.p_max as f32); 4];
let mut lsp_indexes = [0; LPC_ORD];
let mut lsps = [[0.0; LPC_ORD]; 4];
let mut e = [0.0; 4];
let mut snr = 0.0;
let mut ak = [[0.0; LPC_ORD + 1]; 4];
let mut nbit = 0;
let mut Aw = [COMP::new(); FFT_ENC];
for i in 0..4 {
for j in 1..MAX_AMP {
model[i].A[j] = 0.0;
}
}
model[0].voiced = unpack(bits, &mut nbit, 1);
model[1].voiced = unpack(bits, &mut nbit, 1);
let WoE_index = unpack(bits, &mut nbit, WO_E_BITS);
decode_WoE(
&self.internal.c2const,
&mut model[1],
&mut e[1],
&mut self.internal.xq_dec,
WoE_index as usize,
);
model[2].voiced = unpack(bits, &mut nbit, 1);
model[3].voiced = unpack(bits, &mut nbit, 1);
let WoE_index = unpack(bits, &mut nbit, WO_E_BITS);
decode_WoE(
&self.internal.c2const,
&mut model[3],
&mut e[3],
&mut self.internal.xq_dec,
WoE_index as usize,
);
for i in 0..LSP_PRED_VQ_INDEXES {
lsp_indexes[i] = unpack(bits, &mut nbit, lsp_pred_vq_bits(i) as u32) as usize;
}
decode_lsps_vq(&lsp_indexes, &mut lsps[3][0..], LPC_ORD, 0);
check_lsp_order(&mut lsps[3][0..], LPC_ORD);
bw_expand_lsps(&mut lsps[3][0..], LPC_ORD, 50.0, 100.0);
model[0] = interp_Wo(
&model[0],
&self.internal.prev_model_dec,
&model[1],
self.internal.c2const.Wo_min,
);
e[0] = interp_energy(self.internal.prev_e_dec, e[1]);
model[2] = interp_Wo(
&model[2],
&model[1],
&model[3],
self.internal.c2const.Wo_min,
);
e[2] = interp_energy(e[1], e[3]);
for i in 0..3 {
let weight = 0.25 + i as f32 * 0.25;
let lsps3 = lsps[3];
interpolate_lsp_ver2(
&mut lsps[i][0..],
&self.internal.prev_lsps_dec,
&lsps3[0..],
weight,
LPC_ORD,
);
}
for i in 0..4 {
lsp_to_lpc(&lsps[i][0..], &mut ak[i][0..], LPC_ORD);
aks_to_M2(
&mut self.internal.fftr_fwd_cfg,
&ak[i][0..],
LPC_ORD,
&mut model[i],
e[i],
&mut snr,
0,
0,
self.internal.lpc_pf,
self.internal.bass_boost,
self.internal.beta,
self.internal.gamma,
&mut Aw,
);
apply_lpc_correction(&mut model[i]);
self.synthesise_one_frame(
&mut speech[self.internal.n_samp * i..],
&mut model[i],
&Aw,
1.0,
);
}
self.internal.prev_model_dec = model[3];
self.internal.prev_e_dec = e[3];
for i in 0..LPC_ORD {
self.internal.prev_lsps_dec[i] = lsps[3][i];
}
}
fn analyse_one_frame(&mut self, model: &mut MODEL, speech: &[i16]) {
let mut Sw = [COMP::new(); FFT_ENC];
let n_samp = self.internal.n_samp;
let m_pitch = self.internal.m_pitch;
for i in 0..m_pitch - n_samp {
self.internal.Sn[i] = self.internal.Sn[i + n_samp];
}
for i in 0..n_samp {
self.internal.Sn[i + m_pitch - n_samp] = speech[i].into();
}
self.internal.c2const.dft_speech(
&self.internal.fft_fwd_cfg,
&mut Sw,
&self.internal.Sn,
&self.internal.w,
);
let mut pitch = 0.0;
nlp::nlp(
&mut self.internal.nlp,
&self.internal.Sn,
n_samp,
&mut pitch,
&Sw,
&self.internal.W,
&mut self.internal.prev_f0_enc,
);
model.Wo = TWO_PI / pitch;
model.L = (PI / model.Wo as f64) as usize;
two_stage_pitch_refinement(&self.internal.c2const, model, &Sw);
estimate_amplitudes(model, &Sw, &self.internal.W, 0);
est_voicing_mbe(&self.internal.c2const, model, &Sw, &self.internal.W);
}
fn synthesise_one_frame(
&mut self,
speech: &mut [i16],
model: &mut MODEL,
Aw: &[COMP],
gain: f32,
) {
let mut H = [COMP::new(); MAX_AMP + 1];
sample_phase(model, &mut H, Aw);
phase_synth_zero_order(
self.internal.n_samp,
model,
&mut self.internal.ex_phase,
&mut H,
);
postfilter(model, &mut self.internal.bg_est);
synthesise(
self.internal.n_samp,
&mut self.internal.fftr_inv_cfg,
&mut self.internal.Sn_,
model,
&self.internal.Pn,
true,
);
for i in 0..self.internal.n_samp {
self.internal.Sn_[i] *= gain;
}
ear_protection(&mut self.internal.Sn_, self.internal.n_samp);
for i in 0..self.internal.n_samp {
if self.internal.Sn_[i] > 32767.0 {
speech[i] = 32767;
} else if self.internal.Sn_[i] < -32767.0 {
speech[i] = -32767;
} else {
speech[i] = self.internal.Sn_[i] as i16;
}
}
}
}
fn ear_protection(in_out: &mut [f32], n: usize) {
let mut max_sample = 0.0;
for i in 0..n {
if in_out[i] > max_sample {
max_sample = in_out[i];
}
}
let over = max_sample / 30000.0;
if over > 1.0 {
let gain = 1.0 / (over * over);
for i in 0..n {
in_out[i] *= gain;
}
}
}
fn est_voicing_mbe(c2const: &C2const, model: &mut MODEL, Sw: &[COMP], W: &[f32]) -> f32 {
let mut Am = COMP::new(); let mut Ew = COMP::new();
let l_1000hz = (model.L as f32 * 1000.0 / ((c2const.Fs / 2) as f32)) as usize;
let mut sig = 1E-4;
for l in 1..l_1000hz + 1 {
sig += model.A[l] * model.A[l];
}
let Wo = model.Wo;
let mut error = 1E-4;
for l in 1..l_1000hz + 1 {
Am.r = 0.0;
Am.i = 0.0;
let mut den = 0.0; let al = ((l as f32 - 0.5) * Wo * (FFT_ENC as f32) / TWO_PI).ceil() as usize;
let bl = ((l as f32 + 0.5) * Wo * (FFT_ENC as f32) / TWO_PI).ceil() as usize;
let offset =
(FFT_ENC as f32 / 2.0 - (l as f32) * Wo * (FFT_ENC as f32) / TWO_PI + 0.5) as usize;
for m in al..bl {
Am.r += Sw[m].r * W[offset + m];
Am.i += Sw[m].i * W[offset + m];
den += W[offset + m] * W[offset + m];
}
Am.r = Am.r / den;
Am.i = Am.i / den;
for m in al..bl {
Ew.r = Sw[m].r - Am.r * W[offset + m];
Ew.i = Sw[m].i - Am.i * W[offset + m];
error += Ew.r * Ew.r;
error += Ew.i * Ew.i;
}
}
let snr = 10.0 * (sig / error).log10();
if snr > V_THRESH {
model.voiced = 1;
} else {
model.voiced = 0;
}
let l_2000hz = (model.L as f32 * 2000.0 / (c2const.Fs as f32 / 2.0)) as usize;
let l_4000hz = (model.L as f32 * 4000.0 / (c2const.Fs as f32 / 2.0)) as usize;
let mut ehigh = 1E-4;
let mut elow = ehigh;
for l in 1..l_2000hz + 1 {
elow += model.A[l] * model.A[l];
}
for l in l_2000hz..l_4000hz + 1 {
ehigh += model.A[l] * model.A[l];
}
let eratio = 10.0 * (elow / ehigh).log10();
if model.voiced == 0 {
if eratio > 10.0 {
model.voiced = 1;
}
}
if model.voiced == 1 {
if eratio < -10.0 {
model.voiced = 0;
}
let sixty = 60.0 * TWO_PI / (c2const.Fs as f32);
if (eratio < -4.0) && (model.Wo <= sixty) {
model.voiced = 0;
}
}
return snr;
}
fn estimate_amplitudes(model: &mut MODEL, Sw: &[COMP], _W: &[f32], est_phase: i32) {
let r = TWO_PI / (FFT_ENC as f32);
let one_on_r = 1.0 / r;
for m in 1..model.L + 1 {
let mut den = 0.0; let am = ((m as f32 - 0.5) * model.Wo * one_on_r + 0.5) as usize;
let bm = ((m as f32 + 0.5) * model.Wo * one_on_r + 0.5) as usize;
for i in am..bm {
den += Sw[i].r * Sw[i].r + Sw[i].i * Sw[i].i;
}
model.A[m] = den.sqrt();
if est_phase != 0 {
let b = (m as f32 * model.Wo / r + 0.5) as usize;
model.phi[m] = Sw[b].i.atan2(Sw[b].r);
}
}
}
fn two_stage_pitch_refinement(c2const: &C2const, model: &mut MODEL, Sw: &[COMP]) {
let mut pmax = TWO_PI / model.Wo + 5.0;
let mut pmin = TWO_PI / model.Wo - 5.0;
let mut pstep = 1.0;
hs_pitch_refinement(model, Sw, pmin, pmax, pstep);
pmax = TWO_PI / model.Wo + 1.0;
pmin = TWO_PI / model.Wo - 1.0;
pstep = 0.25;
hs_pitch_refinement(model, Sw, pmin, pmax, pstep);
if model.Wo < TWO_PI / (c2const.p_max as f32) {
model.Wo = TWO_PI / (c2const.p_max as f32);
}
if model.Wo > TWO_PI / (c2const.p_min as f32) {
model.Wo = TWO_PI / (c2const.p_min as f32);
}
model.L = (PI / model.Wo as f64).floor() as usize;
if model.Wo * model.L as f32 >= 0.95 * PI as f32 {
model.L -= 1;
}
}
fn hs_pitch_refinement(model: &mut MODEL, Sw: &[COMP], pmin: f32, pmax: f32, pstep: f32) {
model.L = (PI / model.Wo as f64) as usize; let mut Wom = model.Wo; let mut Em = 0.0; let r = TWO_PI / FFT_ENC as f32; let one_on_r = 1.0 / r;
let mut p = pmin; while p <= pmax {
let mut E = 0.0; let Wo = TWO_PI / p;
for m in 1..model.L + 1 {
let b = (m as f32 * Wo * one_on_r + 0.5) as usize;
E += Sw[b].r * Sw[b].r + Sw[b].i * Sw[b].i;
}
if E > Em {
Em = E;
Wom = Wo;
}
p += pstep;
}
model.Wo = Wom;
}