use super::chebyshev::{chebps_10, chebps_11};
use crate::codecs::g729::impls::constants::{M, MP1, NC};
use crate::codecs::g729::impls::dsp::arith::{abs_s, add, extract_h, negate, sub};
use crate::codecs::g729::impls::dsp::arith32::{l_mac, l_msu, l_mult};
use crate::codecs::g729::impls::dsp::div::div_s;
use crate::codecs::g729::impls::dsp::shift::{l_shr, norm_s, shl, shr};
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16};
use crate::codecs::g729::impls::tables::annexa::GRID;
#[inline(always)]
fn w(v: i16) -> Word16 {
Word16(v)
}
pub(crate) fn az_lsp(a: &[i16; MP1], lsp: &mut [i16; M], old_lsp: &[i16; M]) {
let mut ctx = DspContext::default();
let mut f1 = [0i16; NC + 1];
let mut f2 = [0i16; NC + 1];
let mut ovf_coef = false;
f1[0] = 2048;
f2[0] = 2048;
for i in 0..NC {
ctx.overflow = false;
let mut t0 = l_mult(&mut ctx, w(a[i + 1]), w(16384));
t0 = l_mac(&mut ctx, t0, w(a[M - i]), w(16384));
let x = extract_h(t0).0;
if ctx.overflow {
ovf_coef = true;
}
ctx.overflow = false;
f1[i + 1] = sub(&mut ctx, w(x), w(f1[i])).0;
if ctx.overflow {
ovf_coef = true;
}
ctx.overflow = false;
let mut t0 = l_mult(&mut ctx, w(a[i + 1]), w(16384));
t0 = l_msu(&mut ctx, t0, w(a[M - i]), w(16384));
let x2 = extract_h(t0).0;
if ctx.overflow {
ovf_coef = true;
}
ctx.overflow = false;
f2[i + 1] = add(&mut ctx, w(x2), w(f2[i])).0;
if ctx.overflow {
ovf_coef = true;
}
}
if ovf_coef {
f1[0] = 1024;
f2[0] = 1024;
for i in 0..NC {
let mut t0 = l_mult(&mut ctx, w(a[i + 1]), w(8192));
t0 = l_mac(&mut ctx, t0, w(a[M - i]), w(8192));
let x = extract_h(t0).0;
f1[i + 1] = sub(&mut ctx, w(x), w(f1[i])).0;
let mut t0 = l_mult(&mut ctx, w(a[i + 1]), w(8192));
t0 = l_msu(&mut ctx, t0, w(a[M - i]), w(8192));
let x2 = extract_h(t0).0;
f2[i + 1] = add(&mut ctx, w(x2), w(f2[i])).0;
}
}
let mut nf = 0usize;
let mut ip = 0usize;
let mut coef_is_f1 = true;
let mut xlow = GRID[0];
let mut ylow = if ovf_coef {
chebps_10(xlow, &f1)
} else {
chebps_11(xlow, &f1)
};
let mut j = 0usize;
while nf < M && j < 50 {
j += 1;
let mut xhigh = xlow;
let mut yhigh = ylow;
xlow = GRID[j];
ylow = if coef_is_f1 {
if ovf_coef {
chebps_10(xlow, &f1)
} else {
chebps_11(xlow, &f1)
}
} else if ovf_coef {
chebps_10(xlow, &f2)
} else {
chebps_11(xlow, &f2)
};
let l_temp = l_mult(&mut ctx, w(ylow), w(yhigh));
if l_temp.0 <= 0 {
for _ in 0..2 {
let xl = shr(&mut ctx, w(xlow), 1).0;
let xh = shr(&mut ctx, w(xhigh), 1).0;
let xmid = add(&mut ctx, w(xl), w(xh)).0;
let ymid = if coef_is_f1 {
if ovf_coef {
chebps_10(xmid, &f1)
} else {
chebps_11(xmid, &f1)
}
} else if ovf_coef {
chebps_10(xmid, &f2)
} else {
chebps_11(xmid, &f2)
};
let l_temp2 = l_mult(&mut ctx, w(ylow), w(ymid));
if l_temp2.0 <= 0 {
yhigh = ymid;
xhigh = xmid;
} else {
ylow = ymid;
xlow = xmid;
}
}
let x = sub(&mut ctx, w(xhigh), w(xlow)).0;
let mut y = sub(&mut ctx, w(yhigh), w(ylow)).0;
let xint = if y == 0 {
xlow
} else {
let sign = y;
y = abs_s(&mut ctx, w(y)).0;
let exp = norm_s(w(y));
y = shl(&mut ctx, w(y), exp).0;
y = div_s(w(16383), w(y)).0;
let mut t0 = l_mult(&mut ctx, w(x), w(y));
let sh = sub(&mut ctx, w(20), w(exp)).0;
t0 = l_shr(&mut ctx, t0, sh);
let mut yy = crate::codecs::g729::impls::dsp::arith::extract_l(t0).0;
if sign < 0 {
yy = negate(&mut ctx, w(yy)).0;
}
let mut t0 = l_mult(&mut ctx, w(ylow), w(yy));
t0 = l_shr(&mut ctx, t0, 11);
sub(
&mut ctx,
w(xlow),
crate::codecs::g729::impls::dsp::arith::extract_l(t0),
)
.0
};
lsp[nf] = xint;
xlow = xint;
nf += 1;
ip ^= 1;
coef_is_f1 = ip == 0;
ylow = if coef_is_f1 {
if ovf_coef {
chebps_10(xlow, &f1)
} else {
chebps_11(xlow, &f1)
}
} else if ovf_coef {
chebps_10(xlow, &f2)
} else {
chebps_11(xlow, &f2)
};
}
}
if nf < M {
lsp.copy_from_slice(old_lsp);
}
}