use crate::pitch::pitch_xcorr;
pub fn lpc(lpc: &mut [f32], ac: &[f32], p: usize) {
let mut error = ac[0];
if error <= 1e-10 {
for x in lpc.iter_mut() {
*x = 0.0;
}
return;
}
for i in 0..p {
let mut rr = 0.0f32;
for j in 0..i {
rr += lpc[j] * ac[i - j];
}
rr += ac[i + 1];
let r = -rr / error;
lpc[i] = r;
for j in 0..i.div_ceil(2) {
let tmp1 = lpc[j];
let tmp2 = lpc[i - 1 - j];
lpc[j] = tmp1 + r * tmp2;
lpc[i - 1 - j] = tmp2 + r * tmp1;
}
error = error - r * r * error;
if error <= 0.001 * ac[0] {
break;
}
}
}
pub fn autocorr(
x: &[f32],
ac: &mut [f32],
window: Option<&[f32]>,
overlap: usize,
lag: usize,
n: usize,
) {
let xx_vec;
let xx: &[f32] = if let Some(win) = window {
if x.len() < n {
return;
}
xx_vec = {
let mut v = x[0..n].to_vec();
for i in 0..overlap {
v[i] *= win[i];
v[n - 1 - i] *= win[i];
}
v
};
&xx_vec
} else {
&x[0..n]
};
let fast_n = n - lag;
pitch_xcorr(xx, xx, ac, fast_n, lag + 1);
for k in 0..=lag {
let mut d = 0.0f32;
for i in (k + fast_n)..n {
d += xx[i] * xx[i - k];
}
ac[k] += d;
}
}
pub fn celt_fir(x: &[f32], num: &[f32], y: &mut [f32], n: usize, ord: usize) {
for i in 0..n {
let mut sum = x[i];
for j in 0..ord {
if i > j {
sum += num[j] * x[i - j - 1];
}
}
y[i] = sum;
}
}
pub fn celt_iir(x: &[f32], den: &[f32], y: &mut [f32], n: usize, ord: usize, mem: &mut [f32]) {
for i in 0..n {
let mut sum = x[i];
for j in 0..ord {
sum -= den[j] * mem[j];
}
for j in (1..ord).rev() {
mem[j] = mem[j - 1];
}
mem[0] = sum;
y[i] = sum;
}
}