use crate::*;
const LSP_DELTA1: f32 = 0.01;
const E_MIN_DB: f32 = -10.0;
const E_MAX_DB: f32 = 40.0;
pub const E_BITS: i32 = 5;
pub const LSP_PRED_VQ_INDEXES: usize = 3;
pub fn lspd_bits(i: usize) -> i32 {
lsp_cbd[i].log2m
}
pub fn lsp_pred_vq_bits(i: usize) -> i32 {
lsp_cbjvm[i].log2m
}
pub fn autocorrelate(
Sn: &[f32], Rn: &mut [f32], Nsam: usize, order: usize, ) {
for j in 0..order + 1 {
Rn[j] = 0.0;
for i in 0..Nsam - j {
Rn[j] += Sn[i] * Sn[i + j];
}
}
}
pub fn levinson_durbin(
R: &[f32], lpcs: &mut [f32], order: usize, ) {
let mut a = vec![vec![0.0; order + 1]; order + 1];
let mut e = R[0];
for i in 1..order + 1 {
let mut sum = 0.0;
for j in 1..i {
sum += a[i - 1][j] * R[i - j];
}
let mut k = -1.0 * (R[i] + sum) / e; if k.abs() > 1.0 {
k = 0.0;
}
a[i][i] = k;
for j in 1..i {
a[i][j] = a[i - 1][j] + k * a[i - 1][i - j]; }
e *= 1.0 - k * k; }
for i in 1..order + 1 {
lpcs[i] = a[order][i];
}
lpcs[0] = 1.0;
}
fn cheb_poly_eva(
coef: &[f32], x: f32, order: usize, ) -> f32 {
let mut T = vec![0.0; order / 2 + 1];
T[0] = 1.0;
T[1] = x;
let mut toff = 0;
let mut uoff = 1;
let mut voff = 2;
for _i in 2..order / 2 + 1 {
T[voff] = (2.0 * x) * T[uoff] - T[toff]; toff += 1;
uoff += 1;
voff += 1;
}
let mut sum = 0.0; toff = 0;
for i in 0..order / 2 + 1 {
sum += coef[(order / 2) - i] * T[toff];
toff += 1;
}
return sum;
}
pub fn lpc_to_lsp(
a: &[f32], order: usize, freq: &mut [f32], nb: i32, delta: f32, ) -> i32 {
let mut roots = 0; let mut Q = vec![0.0; order + 1];
let mut P = vec![0.0; order + 1];
let m = order / 2;
let mut pxoff = 0; let mut qxoff = 0;
let mut poff = pxoff;
let mut qoff = qxoff;
P[pxoff] = 1.0;
pxoff += 1;
Q[qxoff] = 1.0;
qxoff += 1;
for i in 1..m + 1 {
P[pxoff] = a[i] + a[order + 1 - i] - P[poff];
pxoff += 1;
poff += 1;
Q[qxoff] = a[i] - a[order + 1 - i] + Q[qoff];
qxoff += 1;
qoff += 1;
}
pxoff = 0;
qxoff = 0;
for _i in 0..m {
P[pxoff] = 2.0 * P[pxoff];
Q[qxoff] = 2.0 * Q[qxoff];
pxoff += 1;
qxoff += 1;
}
let mut xr = 0.0; let mut xl = 1.0;
for j in 0..order {
let pt = if (j % 2) != 0 {
&Q[..]
} else {
&P[..]
};
let mut psuml = cheb_poly_eva(pt, xl, order); let mut flag = true;
while flag && (xr >= -1.0) {
xr = xl - delta; let psumr = cheb_poly_eva(pt, xr, order); let temp_psumr = psumr;
let temp_xr = xr;
if ((psumr * psuml) < 0.0) || (psumr == 0.0) {
roots += 1;
let mut xm = 0.0;
for _k in 0..nb + 1 {
xm = (xl + xr) / 2.0; let psumm = cheb_poly_eva(pt, xm, order);
if psumm * psuml > 0. {
psuml = psumm;
xl = xm;
} else {
xr = xm;
}
}
freq[j] = xm;
xl = xm;
flag = false; } else {
psuml = temp_psumr;
xl = temp_xr;
}
}
}
for i in 0..order {
freq[i] = freq[i].acos();
}
return roots;
}
pub fn encode_Wo(c2const: &C2const, Wo: f32, bits: i32) -> i32 {
let mut index = 1 << bits;
let Wo_levels = index;
let Wo_min = c2const.Wo_min;
let Wo_max = c2const.Wo_max;
let norm = (Wo - Wo_min) / (Wo_max - Wo_min);
index = (Wo_levels as f32 * norm + 0.5).floor() as i32;
if index < 0 {
index = 0;
}
if index > (Wo_levels - 1) {
index = Wo_levels - 1;
}
index
}
pub fn encode_WoE(model: &MODEL, mut e: f32, xq: &mut [f32]) -> i32 {
let mut err = [0.0, 0.0];
let mut w = [0.0, 0.0];
let codebook1 = ge_cb[0].cb;
let nb_entries = 1 << WO_E_BITS;
let ndim = ge_cb[0].k;
let ge_coeff = [0.8, 0.9];
if e < 0.0 {
e = 0.0;
}
let mut x = [0.0, 0.0];
x[0] = ((model.Wo / PI as f32) * 4000.0 / 50.0).log10() / 2.0_f32.log10();
x[1] = 10.0 * (1e-4 + e).log10();
compute_weights2(&x, xq, &mut w);
for i in 0..ndim {
err[i] = x[i] - ge_coeff[i] * xq[i];
}
let n1 = find_nearest_weighted(codebook1, nb_entries, &err, &w, ndim);
for i in 0..ndim {
xq[i] = ge_coeff[i] * xq[i] + codebook1[ndim * n1 + i];
err[i] -= codebook1[ndim * n1 + i];
}
n1 as i32
}
pub fn lsp_bits(i: usize) -> u32 {
lsp_cb[i].log2m as u32
}
fn compute_weights2(x: &[f32], xp: &[f32], w: &mut [f32]) {
w[0] = 30.0;
w[1] = 1.0;
if x[1] < 0.0 {
w[0] *= 0.6;
w[1] *= 0.3;
}
if x[1] < -10.0 {
w[0] *= 0.3;
w[1] *= 0.3;
}
if (x[0] - xp[0]).abs() < 0.2 {
w[0] *= 2.0;
w[1] *= 1.5;
} else if (x[0] - xp[0]).abs() > 0.5
{
w[0] *= 0.5;
}
if x[1] < xp[1] - 10.0 {
w[1] *= 0.5;
}
if x[1] < xp[1] - 20.0 {
w[1] *= 0.5;
}
w[0] *= w[0];
w[1] *= w[1];
}
fn compute_weights(x: &[f32], w: &mut [f32], ndim: usize) {
w[0] = f32::min(x[0], x[1] - x[0]);
for i in 1..ndim - 1 {
w[i] = f32::min(x[i] - x[i - 1], x[i + 1] - x[i]);
}
w[ndim - 1] = f32::min(x[ndim - 1] - x[ndim - 2], PI as f32 - x[ndim - 1]);
for i in 0..ndim {
w[i] = 1. / (0.01 + w[i]);
}
}
fn find_nearest(codebook: &[f32], nb_entries: usize, x: &mut [f32], ndim: usize) -> usize {
let mut min_dist = 1e15;
let mut nearest = 0;
for i in 0..nb_entries {
let mut dist = 0f32;
for j in 0..ndim {
dist += (x[j] - codebook[i * ndim + j]) * (x[j] - codebook[i * ndim + j]);
}
if dist < min_dist {
min_dist = dist;
nearest = i;
}
}
nearest
}
fn find_nearest_weighted(
codebook: &[f32],
nb_entries: usize,
x: &[f32],
w: &[f32],
ndim: usize,
) -> usize {
let mut min_dist = 1e15;
let mut nearest = 0;
for i in 0..nb_entries {
let mut dist = 0.0;
for j in 0..ndim {
dist += w[j] * (x[j] - codebook[i * ndim + j]) * (x[j] - codebook[i * ndim + j]);
}
if dist < min_dist {
min_dist = dist;
nearest = i;
}
}
nearest
}
pub fn encode_lsps_scalar(indexes: &mut [i32], lsp: &[f32], order: usize) {
let mut lsp_hz = vec![0.0; order];
let mut se = 0.0;
for i in 0..order {
lsp_hz[i] = (4000.0 / PI as f32) * lsp[i];
}
let mut wt = [1.0; 1];
for i in 0..order {
let k = lsp_cb[i].k;
indexes[i] = quantise(lsp_cb[i].cb, &lsp_hz[i..], &mut wt, k, &mut se) as i32;
}
}
pub fn decode_Wo(c2const: &C2const, index: i32, bits: i32) -> f32 {
let Wo_min = c2const.Wo_min;
let Wo_max = c2const.Wo_max;
let Wo_levels = 1 << bits;
let step = (Wo_max - Wo_min) / Wo_levels as f32;
Wo_min + step * index as f32
}
pub fn speech_to_uq_lsps(
lsp: &mut [f32],
ak: &mut [f32],
Sn: &[f32],
w: &[f32],
m_pitch: usize,
order: usize,
) -> f32 {
let mut Wn = vec![0.0; m_pitch];
let mut R = vec![0.0; order + 1];
let mut e = 0.0;
for i in 0..m_pitch {
Wn[i] = Sn[i] * w[i];
e += Wn[i] * Wn[i];
}
if e == 0.0 {
for i in 0..order {
lsp[i] = (PI as f32 / order as f32) * (i as f32);
}
return 0.0;
}
autocorrelate(&Wn, &mut R, m_pitch, order);
levinson_durbin(&R, ak, order);
let mut E = 0.0;
for i in 0..order + 1 {
E += ak[i] * R[i];
}
for i in 0..order + 1 {
ak[i] *= 0.994f32.powf(i as f32);
}
let roots = lpc_to_lsp(ak, order, lsp, 5, LSP_DELTA1);
if roots != order as i32 {
for i in 0..order {
lsp[i] = (PI as f32 / order as f32) * (i as f32);
}
}
return E;
}
pub fn encode_energy(e: f32, bits: i32) -> i32 {
let e_levels = 1 << bits;
let e = 10.0 * e.log10();
let norm = (e - E_MIN_DB) / (E_MAX_DB - E_MIN_DB);
let mut index = (e_levels as f32 * norm + 0.5).floor() as i32;
if index < 0 {
index = 0;
}
if index > (e_levels - 1) {
index = e_levels - 1;
}
return index;
}
pub fn decode_energy(index: i32, bits: i32) -> f32 {
let e_min = E_MIN_DB;
let e_max = E_MAX_DB;
let e_levels = 1 << bits;
let step = (e_max - e_min) / e_levels as f32;
let e = e_min + step * (index as f32);
10.0_f32.powf(e / 10.0)
}
pub fn encode_lspds_scalar(indexes: &mut [i32], lsp: &[f32], order: usize) {
let mut lsp_hz = vec![0.0; order];
let mut lsp__hz = vec![0.0; order];
let mut dlsp = vec![0.0; order];
let mut dlsp_ = vec![0.0; order];
let mut wt = vec![1.0; order];
for i in 0..order {
lsp_hz[i] = (4000.0 / PI as f32) * lsp[i];
}
wt[0] = 1.0;
for i in 0..order {
if i != 0 {
dlsp[i] = lsp_hz[i] - lsp__hz[i - 1];
} else {
dlsp[0] = lsp_hz[0];
}
let k = lsp_cbd[i].k;
let cb = lsp_cbd[i].cb;
let mut se = 0.0;
indexes[i] = quantise(cb, &mut dlsp[i..], &wt, k, &mut se) as i32;
dlsp_[i] = cb[indexes[i] as usize * k];
if i != 0 {
lsp__hz[i] = lsp__hz[i - 1] + dlsp_[i];
} else {
lsp__hz[0] = dlsp_[0];
}
}
}
fn quantise(
cb: &[f32], vec: &[f32], w: &[f32], k: usize, se: &mut f32, ) -> i64 {
let mut besti = 0; let mut beste = 1E32; for j in 0..cb.len() {
let mut e = 0.0; for i in 0..k {
let diff = cb[j * k + i] - vec[i];
e += diff * w[i] * diff * w[i];
}
if e < beste {
beste = e;
besti = j;
}
}
*se += beste;
besti as i64
}
pub fn interp_energy(prev_e: f32, next_e: f32) -> f32 {
(prev_e * next_e).sqrt() }
pub fn interp_energy2(prev_e: f32, next_e: f32, weight: f32) -> f32 {
10f32.powf((1.0 - weight) * prev_e.log10() + weight * next_e.log10())
}
pub fn aks_to_M2(
fftr_fwd_cfg: &mut codec2_fftr_cfg,
ak: &[f32], order: usize,
model: &mut MODEL, E: f32, snr: &mut f32, dump: i32, sim_pf: i32, pf: i32, bass_boost: i32, beta: f32,
gamma: f32, Aw: &mut [COMP], ) {
let r = TWO_PI / FFT_ENC as f32;
{
let mut a = [0.0; FFT_ENC];
for i in 0..order + 1 {
a[i] = ak[i];
}
codec2_fftr(fftr_fwd_cfg, &a, Aw);
}
let mut Pw = [0.0; FFT_ENC / 2];
for i in 0..FFT_ENC / 2 {
Pw[i] = 1.0 / (Aw[i].r * Aw[i].r + Aw[i].i * Aw[i].i + 1E-6);
}
if pf != 0 {
lpc_post_filter(
fftr_fwd_cfg,
&mut Pw,
ak,
order,
dump,
beta,
gamma,
bass_boost,
E,
);
} else {
for i in 0..FFT_ENC / 2 {
Pw[i] *= E;
}
}
let mut signal = 1E-30;
let mut noise = 1E-32;
for m in 1..model.L + 1 {
let am = ((m as f32 - 0.5) * model.Wo / r + 0.5) as usize;
let mut bm = ((m as f32 + 0.5) * model.Wo / r + 0.5) as usize;
if bm > FFT_ENC / 2 {
bm = FFT_ENC / 2;
}
let mut Em = 0.0_f32;
for i in am..bm {
Em += Pw[i];
}
let mut Am = Em.sqrt();
signal += model.A[m] * model.A[m];
noise += (model.A[m] - Am) * (model.A[m] - Am);
if sim_pf != 0 {
if Am > model.A[m] {
Am *= 0.7;
}
if Am < model.A[m] {
Am *= 1.4;
}
}
model.A[m] = Am;
}
*snr = 10.0 * (signal / noise).log10();
}
fn cconj(a: COMP) -> COMP {
COMP {
r: a.r,
i: 0.0 - a.i,
}
}
pub fn sample_phase(
model: &MODEL,
H: &mut [COMP],
A: &[COMP], ) {
let r = TWO_PI / (FFT_ENC as f32);
for m in 1..model.L + 1 {
let b = (m as f32 * model.Wo / r + 0.5) as usize;
H[m] = cconj(A[b]); }
}
pub fn phase_synth_zero_order(
n_samp: usize,
model: &mut MODEL,
ex_phase: &mut f32, H: &[COMP], ) {
let mut Ex = [COMP::new(); MAX_AMP + 1]; let mut A_ = [COMP::new(); MAX_AMP + 1];
*ex_phase += (model.Wo) * n_samp as f32;
*ex_phase -= TWO_PI * (*ex_phase / TWO_PI + 0.5).floor();
for m in 1..model.L + 1 {
if model.voiced != 0 {
Ex[m].r = (*ex_phase * m as f32).cos();
Ex[m].i = (*ex_phase * m as f32).sin();
} else {
let phi = TWO_PI * codec2_rand() / CODEC2_RAND_MAX;
Ex[m].r = phi.cos();
Ex[m].i = phi.sin();
}
A_[m].r = H[m].r * Ex[m].r - H[m].i * Ex[m].i;
A_[m].i = H[m].i * Ex[m].r + H[m].r * Ex[m].i;
let new_phi = A_[m].i.atan2(A_[m].r + 1E-12);
model.phi[m] = new_phi;
}
}
const CODEC2_RAND_MAX: f32 = 32767.0;
static next_rand: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(1);
fn codec2_rand() -> f32 {
let mut nextr = next_rand.load(std::sync::atomic::Ordering::Relaxed);
nextr = nextr.overflowing_mul(1103515245).0.overflowing_add(12345).0;
next_rand.store(nextr, std::sync::atomic::Ordering::Relaxed);
((nextr / 65536) % 32768) as f32
}
fn lpc_post_filter(
fftr_fwd_cfg: &mut codec2_fftr_cfg,
Pw: &mut [f32],
ak: &[f32],
order: usize,
_dump: i32,
beta: f32,
gamma: f32,
bass_boost: i32,
E: f32,
) {
let mut x = [0.0; FFT_ENC]; let mut Ww = [COMP::new(); FFT_ENC / 2 + 1]; let mut Rw = [0.0; FFT_ENC / 2 + 1];
x[0] = ak[0];
let mut coeff = gamma;
for i in 1..order + 1 {
x[i] = ak[i] * coeff;
coeff *= gamma;
}
codec2_fftr(fftr_fwd_cfg, &x, &mut Ww);
for i in 0..FFT_ENC / 2 {
Ww[i].r = Ww[i].r * Ww[i].r + Ww[i].i * Ww[i].i;
}
let mut max_Rw = 0.0;
let mut min_Rw = 1E32;
for i in 0..FFT_ENC / 2 {
Rw[i] = (Ww[i].r * Pw[i]).sqrt();
if Rw[i] > max_Rw {
max_Rw = Rw[i];
}
if Rw[i] < min_Rw {
min_Rw = Rw[i];
}
}
let mut e_before = 1E-4;
for i in 0..FFT_ENC / 2 {
e_before += Pw[i];
}
let mut e_after = 1E-4;
for i in 0..FFT_ENC / 2 {
let Pfw = Rw[i].powf(beta);
Pw[i] *= Pfw * Pfw;
e_after += Pw[i];
}
let mut gain = e_before / e_after;
gain *= E;
for i in 0..FFT_ENC / 2 {
Pw[i] *= gain;
}
if bass_boost != 0 {
for i in 0..FFT_ENC / 8 {
Pw[i] *= 1.4 * 1.4;
}
}
}
#[must_use]
pub fn interp_Wo(
interp: &MODEL, prev: &MODEL, next: &MODEL, Wo_min: f32,
) -> MODEL {
interp_Wo2(interp, prev, next, 0.5, Wo_min)
}
#[must_use]
pub fn interp_Wo2(
interp: &MODEL, prev: &MODEL, next: &MODEL, weight: f32,
Wo_min: f32,
) -> MODEL {
let mut interp = *interp;
if interp.voiced != 0 && prev.voiced == 0 && next.voiced == 0 {
interp.voiced = 0;
}
if interp.voiced != 0 {
if prev.voiced != 0 && next.voiced != 0 {
interp.Wo = (1.0 - weight) * prev.Wo + weight * next.Wo;
}
if prev.voiced == 0 && next.voiced != 0 {
interp.Wo = next.Wo;
}
if prev.voiced != 0 && next.voiced == 0 {
interp.Wo = prev.Wo;
}
} else {
interp.Wo = Wo_min;
}
interp.L = (PI / interp.Wo as f64) as usize;
interp
}
pub fn interpolate_lsp_ver2(
interp: &mut [f32],
prev: &[f32],
next: &[f32],
weight: f32,
order: usize,
) {
for i in 0..order {
interp[i] = (1.0 - weight) * prev[i] + weight * next[i];
}
}
pub fn apply_lpc_correction(model: &mut MODEL) {
if model.Wo < (PI as f32 * 150.0 / 4000.0) {
model.A[1] *= 0.032;
}
}
pub fn decode_lspds_scalar(lsp_: &mut [f32], indexes: &[usize], order: usize) {
let mut lsp__hz = vec![0.0; order];
let mut dlsp_ = vec![0.0; order];
for i in 0..order {
let k = lsp_cbd[i].k;
dlsp_[i] = lsp_cbd[i].cb[indexes[i] * k];
if i != 0 {
lsp__hz[i] = lsp__hz[i - 1] + dlsp_[i];
} else {
lsp__hz[0] = dlsp_[0];
}
lsp_[i] = (PI as f32 / 4000.0) * lsp__hz[i];
}
}
pub fn lsp_to_lpc(
lsp: &[f32],
ak: &mut [f32], order: usize, ) {
let mut freq = vec![0.0; order]; let mut Wp = vec![0.0; (order * 4) + 2];
for i in 0..order {
freq[i] = lsp[i].cos();
}
let pwoff = 0; let mut xin1 = 1.0;
let mut xin2 = 1.0;
for j in 0..order + 1 {
let mut n4off = 0;
for i in 0..(order / 2) {
let n1off = pwoff + (i * 4);
let n2off = n1off + 1;
let n3off = n2off + 1;
n4off = n3off + 1;
let xout1 = xin1 - 2.0 * (freq[2 * i]) * Wp[n1off] + Wp[n2off];
let xout2 = xin2 - 2.0 * (freq[2 * i + 1]) * Wp[n3off] + Wp[n4off];
Wp[n2off] = Wp[n1off];
Wp[n4off] = Wp[n3off];
Wp[n1off] = xin1;
Wp[n3off] = xin2;
xin1 = xout1;
xin2 = xout2;
}
let xout1 = xin1 + Wp[n4off + 1];
let xout2 = xin2 - Wp[n4off + 2];
ak[j] = (xout1 + xout2) * 0.5;
Wp[n4off + 1] = xin1;
Wp[n4off + 2] = xin2;
xin1 = 0.0;
xin2 = 0.0;
}
}
pub fn synthesise(
n_samp: usize,
fftr_inv_cfg: &mut codec2_fftr_cfg,
Sn_: &mut [f32], model: &MODEL, Pn: &[f32], shift: bool, ) {
let mut Sw_ = [COMP::new(); FFT_DEC / 2 + 1]; let mut sw_ = [0.0; FFT_DEC];
if shift {
for i in 0..n_samp - 1 {
Sn_[i] = Sn_[i + n_samp];
}
Sn_[n_samp - 1] = 0.0;
}
for i in 0..FFT_DEC / 2 + 1 {
Sw_[i].r = 0.0;
Sw_[i].i = 0.0;
}
for l in 1..model.L + 1 {
let mut b = (l as f32 * model.Wo * FFT_DEC as f32 / TWO_PI + 0.5) as usize;
if b > ((FFT_DEC / 2) - 1) {
b = (FFT_DEC / 2) - 1;
}
Sw_[b].r = model.A[l] * model.phi[l].cos();
Sw_[b].i = model.A[l] * model.phi[l].sin();
}
codec2_fftri(fftr_inv_cfg, &Sw_, &mut sw_);
for i in 0..n_samp - 1 {
Sn_[i] += sw_[FFT_DEC - n_samp + 1 + i] * Pn[i]; }
if shift {
let mut j = 0;
for i in n_samp - 1..2 * n_samp {
Sn_[i] = sw_[j] * Pn[i]; j += 1;
}
} else {
let mut j = 0;
for i in n_samp - 1..2 * n_samp {
Sn_[i] += sw_[j] * Pn[i]; j += 1;
}
}
}
const BG_THRESH: f32 = 40.0; const BG_BETA: f32 = 0.1; const BG_MARGIN: f32 = 6.0;
pub fn postfilter(model: &mut MODEL, bg_est: &mut f32) {
let mut e = 1E-12;
for m in 1..model.L + 1 {
e += model.A[m] * model.A[m];
}
e = 10.0 * (e / model.L as f32).log10();
if e < BG_THRESH && model.voiced != 0 {
*bg_est = *bg_est * (1.0 - BG_BETA) + e * BG_BETA;
}
let thresh = 10.0_f32.powf((*bg_est + BG_MARGIN) / 20.0);
if model.voiced != 0 {
for m in 1..model.L + 1 {
if model.A[m] < thresh {
model.phi[m] = (TWO_PI / CODEC2_RAND_MAX) * codec2_rand();
}
}
}
}
pub fn bw_expand_lsps(lsp: &mut [f32], order: usize, min_sep_low: f32, min_sep_high: f32) {
for i in 1..4 {
if (lsp[i] - lsp[i - 1]) < min_sep_low * (PI as f32 / 4000.0) {
lsp[i] = lsp[i - 1] + min_sep_low * (PI as f32 / 4000.0);
}
}
for i in 4..order {
if lsp[i] - lsp[i - 1] < min_sep_high * (PI as f32 / 4000.0) {
lsp[i] = lsp[i - 1] + min_sep_high * (PI as f32 / 4000.0);
}
}
}
pub fn check_lsp_order(lsp: &mut [f32], order: usize) -> i32 {
let mut swaps = 0;
let mut i = 1;
while i < order {
if lsp[i] < lsp[i - 1] {
swaps += 1;
let tmp = lsp[i - 1];
lsp[i - 1] = lsp[i] - 0.1;
lsp[i] = tmp + 0.1;
i = 1;
}
i += 1;
}
swaps
}
pub fn decode_lsps_scalar(lsp: &mut [f32], indexes: &[usize], order: usize) {
let mut lsp_hz = vec![0.0; order];
for i in 0..order {
let k = lsp_cb[i].k;
lsp_hz[i] = lsp_cb[i].cb[indexes[i] * k];
}
for i in 0..order {
lsp[i] = (PI as f32 / 4000.0) * lsp_hz[i];
}
}
pub fn encode_lsps_vq(indexes: &mut [usize], x: &mut [f32], xq: &mut [f32], order: usize) {
let mut err = vec![0f32; order];
let mut err2 = vec![0f32; order];
let mut err3 = vec![0f32; order];
let mut w = vec![0f32; order];
let mut w2 = vec![0f32; order];
let mut w3 = vec![0f32; order];
let codebook1 = lsp_cbjvm[0].cb;
let codebook2 = lsp_cbjvm[1].cb;
let codebook3 = lsp_cbjvm[2].cb;
w[0] = f32::min(x[0], x[1] - x[0]);
for i in 1..order - 1 {
w[i] = f32::min(x[i] - x[i - 1], x[i + 1] - x[i]);
}
w[order - 1] = f32::min(x[order - 1] - x[order - 2], PI as f32 - x[order - 1]);
compute_weights(x, &mut w, order);
let n1 = find_nearest(codebook1, lsp_cbjvm[0].m, x, order);
for i in 0..order {
xq[i] = codebook1[order * n1 + i];
err[i] = x[i] - xq[i];
}
for i in 0..order / 2 {
err2[i] = err[2 * i];
err3[i] = err[2 * i + 1];
w2[i] = w[2 * i];
w3[i] = w[2 * i + 1];
}
let n2 = find_nearest_weighted(codebook2, lsp_cbjvm[1].m, &mut err2, &w2, order / 2);
let n3 = find_nearest_weighted(codebook3, lsp_cbjvm[2].m, &mut err3, &w3, order / 2);
indexes[0] = n1;
indexes[1] = n2;
indexes[2] = n3;
}
pub fn decode_lsps_vq(indexes: &[usize], xq: &mut [f32], order: usize, stages: usize) {
let codebook1: &[f32] = lsp_cbjvm[0].cb;
let codebook2: &[f32] = lsp_cbjvm[1].cb;
let codebook3: &[f32] = lsp_cbjvm[2].cb;
let n1 = indexes[0];
let n2 = indexes[1];
let n3 = indexes[2];
for i in 0..order {
xq[i] = codebook1[order * n1 + i];
}
if stages != 1 {
for i in 0..order / 2 {
xq[2 * i] += codebook2[order * n2 / 2 + i];
xq[2 * i + 1] += codebook3[order * n3 / 2 + i];
}
}
}
pub fn decode_WoE(c2const: &C2const, model: &mut MODEL, e: &mut f32, xq: &mut [f32], n1: usize) {
let ge_coeff = [0.8, 0.9];
let ndim = ge_cb[0].k;
let Wo_min = c2const.Wo_min;
let Wo_max = c2const.Wo_max;
for i in 0..ndim {
xq[i] = ge_coeff[i] * xq[i] + ge_cb[0].cb[ndim * n1 + i];
}
model.Wo = 2.0_f32.powf(xq[0]) * (PI as f32 * 50.0) / 4000.0;
if model.Wo > Wo_max {
model.Wo = Wo_max
};
if model.Wo < Wo_min {
model.Wo = Wo_min
};
model.L = (PI / model.Wo as f64) as usize;
*e = 10.0_f32.powf(xq[1] / 10.0);
}