use super::resampler_rom::{
RESAMPLER_FRAC_FIR_12, RESAMPLER_ORDER_FIR_12, RESAMPLER_UP2_HQ_0, RESAMPLER_UP2_HQ_1,
};
pub(super) fn up2_hq(state_q10: &mut [i32; 6], output: &mut [i16], input: &[i16], len: usize) {
for k in 0..len {
let in32 = (input[k] as i32) << 10;
let mut y = in32 - state_q10[0];
let mut x = smulwb(y, RESAMPLER_UP2_HQ_0[0] as i32);
let mut out32_1 = state_q10[0] + x;
state_q10[0] = in32 + x;
y = out32_1 - state_q10[1];
x = smulwb(y, RESAMPLER_UP2_HQ_0[1] as i32);
let out32_2 = state_q10[1] + x;
state_q10[1] = out32_1 + x;
y = out32_2 - state_q10[2];
x = smlawb(y, y, RESAMPLER_UP2_HQ_0[2] as i32);
out32_1 = state_q10[2] + x;
state_q10[2] = out32_2 + x;
output[2 * k] = sat16(rshift_round(out32_1, 10));
y = in32 - state_q10[3];
x = smulwb(y, RESAMPLER_UP2_HQ_1[0] as i32);
out32_1 = state_q10[3] + x;
state_q10[3] = in32 + x;
y = out32_1 - state_q10[4];
x = smulwb(y, RESAMPLER_UP2_HQ_1[1] as i32);
let out32_2 = state_q10[4] + x;
state_q10[4] = out32_1 + x;
y = out32_2 - state_q10[5];
x = smlawb(y, y, RESAMPLER_UP2_HQ_1[2] as i32);
out32_1 = state_q10[5] + x;
state_q10[5] = out32_2 + x;
output[2 * k + 1] = sat16(rshift_round(out32_1, 10));
}
}
pub(super) fn iir_fir_interpol(
output: &mut [i16],
buffer: &[i16],
max_index_q16: i32,
index_increment_q16: i32,
) -> usize {
let mut out_idx = 0usize;
let mut index_q16 = 0i32;
while index_q16 < max_index_q16 {
let table_index = smulwb(index_q16 & 0xFFFF, 12) as usize;
let buf_index = (index_q16 >> 16) as usize;
let buf_ptr = &buffer[buf_index..];
let mut res_q15 = smulbb(
buf_ptr[0] as i32,
RESAMPLER_FRAC_FIR_12[table_index][0] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[1] as i32,
RESAMPLER_FRAC_FIR_12[table_index][1] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[2] as i32,
RESAMPLER_FRAC_FIR_12[table_index][2] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[3] as i32,
RESAMPLER_FRAC_FIR_12[table_index][3] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[4] as i32,
RESAMPLER_FRAC_FIR_12[11 - table_index][3] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[5] as i32,
RESAMPLER_FRAC_FIR_12[11 - table_index][2] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[6] as i32,
RESAMPLER_FRAC_FIR_12[11 - table_index][1] as i32,
);
res_q15 = smlabb(
res_q15,
buf_ptr[7] as i32,
RESAMPLER_FRAC_FIR_12[11 - table_index][0] as i32,
);
output[out_idx] = sat16(rshift_round(res_q15, 15));
out_idx += 1;
index_q16 += index_increment_q16;
}
out_idx
}
pub(super) const fn fir_history_len() -> usize {
RESAMPLER_ORDER_FIR_12
}
fn smulwb(a32: i32, b32: i32) -> i32 {
let b16 = b32 as i16 as i32;
let high = (a32 >> 16) * b16;
let low = ((a32 & 0xFFFF) * b16) >> 16;
high.wrapping_add(low)
}
fn smlabb(a32: i32, b32: i32, c32: i32) -> i32 {
a32 + (b32 as i16 as i32) * (c32 as i16 as i32)
}
fn smlawb(a32: i32, b32: i32, c32: i32) -> i32 {
a32.wrapping_add(smulwb(b32, c32))
}
fn smulbb(a32: i32, b32: i32) -> i32 {
(a32 as i16 as i32) * (b32 as i16 as i32)
}
fn sat16(value: i32) -> i16 {
value.clamp(i16::MIN as i32, i16::MAX as i32) as i16
}
fn rshift_round(value: i32, shift: usize) -> i32 {
if shift == 1 {
(value >> 1) + (value & 1)
} else {
((value >> (shift - 1)) + 1) >> 1
}
}