use crate::g729::basic_operations::*;
use crate::g729::ld8k::*;
pub const NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL: usize = 51;
static COS_W0_PI: [Word16; NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL] = [
32760, 32703, 32509, 32187, 31738, 31164, 30466, 29649, 28714, 27666, 26509, 25248, 23886,
22431, 20887, 19260, 17557, 15786, 13951, 12062, 10125, 8149, 6140, 4106, 2057, 0, -2057,
-4106, -6140, -8149, -10125, -12062, -13951, -15786, -17557, -19260, -20887, -22431, -23886,
-25248, -26509, -27666, -28714, -29649, -30466, -31164, -31738, -32187, -32509, -32703, -32760,
];
fn chebyshev_polynomial(x: Word16, f: &[Word32]) -> Word32 {
let mut bk: Word32;
let mut bk1 = add32(shl(x as Word32, 1), f[1]);
let mut bk2 = ONE_IN_Q15 as Word32;
for k in (1..=3).rev() {
bk = sub32(add32(shl(mult16_32_q15(x, bk1), 1), f[5 - k]), bk2);
bk2 = bk1;
bk1 = bk;
}
sub32(add32(mult16_32_q15(x, bk1), shr(f[5], 1)), bk2)
}
pub fn lp2lsp_conversion(lp_coefficients: &[Word16], lsp_coefficients: &mut [Word16]) -> bool {
let mut f1 = [0 as Word32; 6];
let mut f2 = [0 as Word32; 6];
let mut number_of_root_found = 0;
let mut previous_cx: Word32;
let mut cx: Word32;
f1[0] = ONE_IN_Q12 as Word32;
f2[0] = ONE_IN_Q12 as Word32;
for i in 0..5 {
f1[i + 1] = add32(
lp_coefficients[i] as Word32,
sub32(lp_coefficients[9 - i] as Word32, f1[i]),
);
f2[i + 1] = add32(
f2[i],
sub32(
lp_coefficients[i] as Word32,
lp_coefficients[9 - i] as Word32,
),
);
}
for i in 1..6 {
f1[i] = shl(f1[i], 3);
f2[i] = shl(f2[i], 3);
}
let mut use_f1 = true;
previous_cx = chebyshev_polynomial(COS_W0_PI[0], &f1);
for i in 1..NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL {
cx = chebyshev_polynomial(COS_W0_PI[i], if use_f1 { &f1 } else { &f2 });
if ((previous_cx ^ cx) & 0x10000000) != 0 {
let mut x_low = COS_W0_PI[i - 1];
let mut x_high = COS_W0_PI[i];
let mut x_mean: Word16;
for _j in 0..2 {
let middle_cx: Word32;
x_mean = shr(add32(x_low as Word32, x_high as Word32), 1) as Word16;
middle_cx = chebyshev_polynomial(x_mean, if use_f1 { &f1 } else { &f2 });
if ((previous_cx ^ middle_cx) & 0x10000000) != 0 {
x_high = x_mean;
cx = middle_cx;
} else {
x_low = x_mean;
previous_cx = middle_cx;
}
}
use_f1 = !use_f1;
x_mean = sub32(
x_low as Word32,
mult16_32_q15(
sub32(x_high as Word32, x_low as Word32) as Word16,
div32(
shl(saturate(previous_cx, MAXINT17), 14),
shr(sub32(cx, previous_cx), 1),
),
),
) as Word16;
previous_cx = chebyshev_polynomial(x_mean, if use_f1 { &f1 } else { &f2 });
lsp_coefficients[number_of_root_found] = x_mean;
number_of_root_found += 1;
if number_of_root_found == NB_LSP_COEFF {
break;
}
}
}
if number_of_root_found != NB_LSP_COEFF {
return false;
}
true
}