use crate::g729::basic_operations::*;
use crate::g729::ld8k::*;
use crate::g729::utils::{count_leading_zeros, unsigned_count_leading_zeros};
const KL0: Word32 = -135003;
const KL1: Word32 = 378194;
const KL2: Word32 = -252129;
const KL3: Word32 = 74705;
pub fn g729_log2_q0q16(x: Word32) -> Word32 {
let leading_zeros = count_leading_zeros(x);
let ret_value = shl32(sub16(30, leading_zeros as Word16) as Word32, 16);
let acc = vshr32(x, 16 - leading_zeros as i32) as Word16;
let acc32 = add32(
KL0,
mult16_32_q15(
acc,
add32(KL1, mult16_32_q15(acc, add32(KL2, mult16_32_q15(acc, KL3)))),
),
);
add32(ret_value, acc32)
}
const E0: Word16 = 16384;
const E1: Word16 = 11356;
const E2: Word16 = 3726;
const E3: Word16 = 1301;
pub fn g729_exp2_q11q16(x: Word16) -> Word32 {
let integer = shr16(x, 11);
if integer > 14 {
return 0x7fffffff;
} else {
if integer < -15 {
return 0;
}
}
let mut frac = shl16(x - shl16(integer, 11), 3);
frac = add16(
E0,
mult16_16_q14(
frac,
add16(
E1,
mult16_16_q14(frac, add16(E2, mult16_16_q14(E3, frac) as Word16) as Word16)
as Word16,
) as Word16,
) as Word16,
);
vshr32(extend32(frac), -(integer as i32) - 2)
}
const C0: Word16 = 3634;
const C1: Word16 = 21173;
const C2: Word16 = -12627;
const C3: Word16 = 4204;
pub fn g729_sqrt_q0q7(x: UWord32) -> Word32 {
if x == 0 {
return 0;
}
let k = (19 - unsigned_count_leading_zeros(x) as i32) >> 1;
let x_scaled = vshr32(x as Word32, k * 2);
let x16 = x_scaled as Word16;
let mut rt = add16(
C0,
mult16_16_q14(
x16,
add16(
C1,
mult16_16_q14(x16, add16(C2, mult16_16_q14(x16, C3) as Word16) as Word16) as Word16,
) as Word16,
) as Word16,
) as Word32;
rt = vshr32(rt, -k);
rt
}
pub fn g729_inv_sqrt_q0q31(x: Word32) -> Word32 {
if x == 1 {
return MAXINT32;
}
div32_32_q24(g729_sqrt_q0q7(x as UWord32), x) as Word32
}
const KCOS1: Word32 = 32768;
const KCOS2: Word32 = -16384;
const KCOS3: Word32 = 1365;
const KCOS4: Word32 = -46;
const KSIN1: Word32 = 32768;
const KSIN2: Word32 = -5461;
const KSIN3: Word32 = 273;
const KSIN4: Word32 = -7;
pub fn g729_cos_q13q15(mut x: Word16) -> Word16 {
let x2: Word16;
let mut x_scaled: Word16;
if x < 12868 {
if x < 6434 {
x2 = mult16_16_p11(x, x) as Word16;
saturate(
add32(
KCOS1,
mult16_16_p15(
x2,
add32(
KCOS2,
mult16_16_p15(
x2,
add32(KCOS3, mult16_16_p15(KCOS4 as Word16, x2)) as Word16,
),
) as Word16,
),
),
MAXINT16 as Word32,
) as Word16
} else {
x = sub16(12868, x);
x2 = mult16_16_p11(x, x) as Word16;
mult16_16_p13(
x,
add32(
KSIN1,
mult16_16_p15(
x2,
add32(
KSIN2,
mult16_16_p15(
x2,
add32(KSIN3, mult16_16_p15(KSIN4 as Word16, x2)) as Word16,
),
) as Word16,
),
) as Word16,
) as Word16
}
} else {
x_scaled = sub16(25736, x);
if x < 19302 {
x_scaled = sub16(12868, x_scaled);
x2 = mult16_16_p11(x_scaled, x_scaled) as Word16;
mult16_16_p13(
neg16(x_scaled),
add32(
KSIN1,
mult16_16_p15(
x2,
add32(
KSIN2,
mult16_16_p15(
x2,
add32(KSIN3, mult16_16_p15(KSIN4 as Word16, x2)) as Word16,
),
) as Word16,
),
) as Word16,
) as Word16
} else {
x2 = mult16_16_p11(x_scaled, x_scaled) as Word16;
sub32(
-KCOS1,
mult16_16_p15(
x2,
add32(
KCOS2,
mult16_16_p15(
x2,
add32(KCOS3, mult16_16_p15(KCOS4 as Word16, x2)) as Word16,
),
) as Word16,
),
) as Word16
}
}
}
const KPI6: Word32 = 17157;
const KTAN_PI6: Word32 = 18919;
const KTAN_PI12: Word32 = 8780;
const ATAN_B: Word16 = 8453;
const ATAN_C: Word16 = 19373;
pub fn g729_atan_q15q13(mut x: Word32) -> Word16 {
let mut angle: Word32;
let x2: Word16;
let mut high_segment = false;
let mut sign = false;
let mut complement = false;
if x < 0 {
x = neg32(x);
sign = true;
}
if x > ONE_IN_Q15 {
complement = true;
x = div32(ONE_IN_Q30, x);
}
if x > KTAN_PI12 {
high_segment = true;
x = div32(
sshl(sub32(x, KTAN_PI6), 15),
add32(mult16_32_q15(KTAN_PI6 as Word16, x), ONE_IN_Q15),
);
}
x2 = mult16_16_q15(x as Word16, x as Word16) as Word16;
let num = (x as Word32) * add32(ONE_IN_Q15, mult16_16_q15(ATAN_B, x2));
let den = add32(ONE_IN_Q15, mult16_16_q15(ATAN_C, x2));
angle = div32(num, den);
if high_segment {
angle += KPI6;
}
if complement {
angle = sub32(HALF_PI_Q15_32, angle);
}
angle = pshr(angle, 2);
if sign {
neg16(angle as Word16)
} else {
angle as Word16
}
}
pub fn g729_asin_q15q13(x: Word16) -> Word16 {
let xx = mult16_16(x, x);
let sub = sub32(ONE_IN_Q30, xx);
let sqrt = g729_sqrt_q0q7(sub as UWord32);
let denom = pshr(sqrt, 7);
let num = sshl(x as Word32, 15);
let div = div32(num, denom);
let atan = g729_atan_q15q13(div);
atan
}
pub fn g729_acos_q15q13(x: Word16) -> Word16 {
let asin = g729_asin_q15q13(x);
sub16(HALF_PI_Q13, asin)
}