#![forbid(unsafe_code)]
mod ar2;
mod down_fir;
mod iir_fir;
mod rom;
mod up2_hq;
mod down2;
mod down2_3;
use down_fir::{silk_resampler_private_down_FIR, ResamplerDownFirParams, ResamplerDownFirState};
use iir_fir::{silk_resampler_private_IIR_FIR, ResamplerIirFirState};
use rom::{
silk_Resampler_1_2_COEFS, silk_Resampler_1_3_COEFS, silk_Resampler_1_4_COEFS,
silk_Resampler_1_6_COEFS, silk_Resampler_2_3_COEFS, silk_Resampler_3_4_COEFS,
RESAMPLER_DOWN_ORDER_FIR0, RESAMPLER_DOWN_ORDER_FIR1, RESAMPLER_DOWN_ORDER_FIR2,
};
use std::cmp::Ordering;
use up2_hq::{silk_resampler_private_up2_HQ, ResamplerUp2HqState};
pub use down2::silk_resampler_down2;
pub use down2_3::silk_resampler_down2_3;
const RESAMPLER_MAX_BATCH_SIZE_MS: i32 = 10;
const RESAMPLER_MAX_FS_KHZ: usize = 48;
const RESAMPLER_MAX_BATCH_SIZE_IN: usize =
RESAMPLER_MAX_BATCH_SIZE_MS as usize * RESAMPLER_MAX_FS_KHZ;
#[rustfmt::skip]
static delay_matrix_enc: [[i8; 3]; 5] = [
[ 6, 0, 3 ],
[ 0, 7, 3 ],
[ 0, 1, 10 ],
[ 0, 2, 6 ],
[ 18, 10, 12 ],
];
#[rustfmt::skip]
static delay_matrix_dec: [[i8; 5]; 3] = [
[ 4, 0, 2, 0, 0 ],
[ 0, 9, 4, 7, 4 ],
[ 0, 3, 12, 7, 7 ],
];
fn rate_id(r: i32) -> usize {
match r {
8000 => 0,
12000 => 1,
16000 => 2,
24000 => 3,
48000 => 4,
_ => unreachable!("unsupported sampling rate"),
}
}
const SILK_RESAMPLER_MAX_FIR_ORDER: usize = 36;
#[derive(Copy, Clone)]
pub struct ResamplerState {
params: ResamplerParams,
mode: ResamplerMode,
delay_buf: [i16; 48],
}
#[derive(Copy, Clone)]
struct ResamplerParams {
pub batch_size: usize,
pub inv_ratio_q16: i32,
pub fs_in_khz: usize,
pub fs_out_khz: usize,
pub input_delay: usize,
}
#[derive(Copy, Clone)]
enum ResamplerMode {
Copy,
Up2Hq(ResamplerUp2HqState),
IirFir(ResamplerIirFirState),
DownFir(ResamplerDownFirParams, ResamplerDownFirState),
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union sFIR_union {
pub i32_0: [i32; SILK_RESAMPLER_MAX_FIR_ORDER],
pub i16_0: [i16; SILK_RESAMPLER_MAX_FIR_ORDER],
}
pub fn silk_resampler_init(Fs_Hz_in: i32, Fs_Hz_out: i32, forEnc: i32) -> ResamplerState {
let inputDelay = if forEnc != 0 {
if !matches!(Fs_Hz_in, 8000 | 12000 | 16000 | 24000 | 48000)
|| !matches!(Fs_Hz_out, 8000 | 12000 | 16000)
{
panic!("libopus: assert(0) called");
}
delay_matrix_enc[rate_id(Fs_Hz_in)][rate_id(Fs_Hz_out)] as i32
} else {
if !matches!(Fs_Hz_in, 8000 | 12000 | 16000)
|| !matches!(Fs_Hz_out, 8000 | 12000 | 16000 | 24000 | 48000)
{
panic!("libopus: assert(0) called");
}
delay_matrix_dec[rate_id(Fs_Hz_in)][rate_id(Fs_Hz_out)] as i32
};
let Fs_in_kHz = Fs_Hz_in / 1000;
let Fs_out_kHz = Fs_Hz_out / 1000;
let batchSize = Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS;
let mut up2x = 0;
let mode = match Fs_Hz_out.cmp(&Fs_Hz_in) {
Ordering::Greater => {
if Fs_Hz_out == Fs_Hz_in * 2 {
ResamplerMode::Up2Hq(ResamplerUp2HqState::default())
} else {
up2x = 1;
ResamplerMode::IirFir(ResamplerIirFirState::default())
}
}
Ordering::Less => {
let params = if Fs_Hz_out * 4 == Fs_Hz_in * 3 {
ResamplerDownFirParams {
fir_order: RESAMPLER_DOWN_ORDER_FIR0,
fir_fracs: 3,
coefs: &silk_Resampler_3_4_COEFS,
}
} else if Fs_Hz_out * 3 == Fs_Hz_in * 2 {
ResamplerDownFirParams {
fir_order: RESAMPLER_DOWN_ORDER_FIR0,
fir_fracs: 2,
coefs: &silk_Resampler_2_3_COEFS,
}
} else if Fs_Hz_out * 2 == Fs_Hz_in {
ResamplerDownFirParams {
fir_order: RESAMPLER_DOWN_ORDER_FIR1,
fir_fracs: 1,
coefs: &silk_Resampler_1_2_COEFS,
}
} else if Fs_Hz_out * 3 == Fs_Hz_in {
ResamplerDownFirParams {
fir_order: RESAMPLER_DOWN_ORDER_FIR2,
fir_fracs: 1,
coefs: &silk_Resampler_1_3_COEFS,
}
} else if Fs_Hz_out * 4 == Fs_Hz_in {
ResamplerDownFirParams {
fir_order: RESAMPLER_DOWN_ORDER_FIR2,
fir_fracs: 1,
coefs: &silk_Resampler_1_4_COEFS,
}
} else if Fs_Hz_out * 6 == Fs_Hz_in {
ResamplerDownFirParams {
fir_order: RESAMPLER_DOWN_ORDER_FIR2,
fir_fracs: 1,
coefs: &silk_Resampler_1_6_COEFS,
}
} else {
unreachable!("Unsupported resampling ratio: {} : {}", Fs_Hz_out, Fs_Hz_in);
};
ResamplerMode::DownFir(params, ResamplerDownFirState::default())
}
Ordering::Equal => ResamplerMode::Copy,
};
let mut invRatio_Q16 =
(((((Fs_Hz_in as u32) << (14 + up2x)) as i32 / Fs_Hz_out) as u32) << 2) as i32;
while (((invRatio_Q16 as i64 * Fs_Hz_out as i64) >> 16) as i32)
< ((Fs_Hz_in as u32) << up2x) as i32
{
invRatio_Q16 += 1;
}
let params = ResamplerParams {
batch_size: batchSize as usize,
inv_ratio_q16: invRatio_Q16,
fs_in_khz: Fs_in_kHz as usize,
fs_out_khz: Fs_out_kHz as usize,
input_delay: inputDelay as usize,
};
ResamplerState {
params,
mode,
delay_buf: [0; 48],
}
}
pub fn silk_resampler(S: &mut ResamplerState, out: &mut [i16], in_0: &[i16]) -> i32 {
assert!(in_0.len() >= S.params.fs_in_khz);
assert!(S.params.input_delay <= S.params.fs_in_khz);
let nSamples = S.params.fs_in_khz - S.params.input_delay;
S.delay_buf[S.params.input_delay..][..nSamples].copy_from_slice(&in_0[..nSamples]);
let delay_in = &S.delay_buf[..S.params.fs_in_khz];
let rest_in = &in_0[nSamples..][..in_0.len() - S.params.fs_in_khz];
let (delay_out, rest_out) = out.split_at_mut(S.params.fs_out_khz);
let rest_out = &mut rest_out[..rest_in.len() * S.params.fs_out_khz / S.params.fs_in_khz];
match &mut S.mode {
ResamplerMode::Up2Hq(state) => {
silk_resampler_private_up2_HQ(state, delay_out, delay_in);
silk_resampler_private_up2_HQ(state, rest_out, rest_in);
}
ResamplerMode::IirFir(state) => {
silk_resampler_private_IIR_FIR(&S.params, state, delay_out, delay_in);
silk_resampler_private_IIR_FIR(&S.params, state, rest_out, rest_in);
}
ResamplerMode::DownFir(ref params, state) => {
silk_resampler_private_down_FIR(&S.params, params, state, delay_out, delay_in);
silk_resampler_private_down_FIR(&S.params, params, state, rest_out, rest_in);
}
ResamplerMode::Copy => {
delay_out.copy_from_slice(delay_in);
rest_out.copy_from_slice(rest_in);
}
}
S.delay_buf[..S.params.input_delay].copy_from_slice(&in_0[in_0.len() - S.params.input_delay..]);
0
}