use crate::silk::FrameSignalType;
use crate::silk::errors::SilkError;
const ENCODER_NUM_CHANNELS: i32 = 2;
const MIN_TARGET_RATE_BPS: i32 = 5_000;
const MAX_TARGET_RATE_BPS: i32 = 80_000;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncControl {
pub n_channels_api: i32,
pub n_channels_internal: i32,
pub api_sample_rate: i32,
pub max_internal_sample_rate: i32,
pub min_internal_sample_rate: i32,
pub desired_internal_sample_rate: i32,
pub payload_size_ms: i32,
pub bit_rate: i32,
pub packet_loss_percentage: i32,
pub complexity: i32,
pub use_in_band_fec: i32,
pub use_dred: i32,
pub lbrr_coded: i32,
pub use_dtx: i32,
pub use_cbr: i32,
pub max_bits: i32,
pub to_mono: bool,
pub opus_can_switch: bool,
pub reduced_dependency: bool,
pub internal_sample_rate: i32,
pub allow_bandwidth_switch: bool,
pub in_wb_mode_without_variable_lp: bool,
pub stereo_width_q14: i32,
pub switch_ready: bool,
pub signal_type: FrameSignalType,
pub offset: i32,
}
impl Default for EncControl {
fn default() -> Self {
Self {
n_channels_api: 1,
n_channels_internal: 1,
api_sample_rate: 16_000,
max_internal_sample_rate: 16_000,
min_internal_sample_rate: 16_000,
desired_internal_sample_rate: 16_000,
payload_size_ms: 20,
bit_rate: 32_000,
packet_loss_percentage: 0,
complexity: 10,
use_in_band_fec: 0,
use_dred: 0,
lbrr_coded: 0,
use_dtx: 0,
use_cbr: 0,
max_bits: 0,
to_mono: false,
opus_can_switch: false,
reduced_dependency: false,
internal_sample_rate: 16_000,
allow_bandwidth_switch: false,
in_wb_mode_without_variable_lp: false,
stereo_width_q14: 0,
switch_ready: false,
signal_type: FrameSignalType::Inactive,
offset: 0,
}
}
}
impl EncControl {
pub fn check_control_input(&self) -> Result<(), SilkError> {
const API_SAMPLE_RATES: [i32; 7] = [8000, 12_000, 16_000, 24_000, 32_000, 44_100, 48_000];
const INTERNAL_SAMPLE_RATES: [i32; 3] = [8000, 12_000, 16_000];
const PAYLOAD_SIZES_MS: [i32; 4] = [10, 20, 40, 60];
if !API_SAMPLE_RATES.contains(&self.api_sample_rate)
|| !INTERNAL_SAMPLE_RATES.contains(&self.desired_internal_sample_rate)
|| !INTERNAL_SAMPLE_RATES.contains(&self.max_internal_sample_rate)
|| !INTERNAL_SAMPLE_RATES.contains(&self.min_internal_sample_rate)
|| self.min_internal_sample_rate > self.desired_internal_sample_rate
|| self.max_internal_sample_rate < self.desired_internal_sample_rate
|| self.min_internal_sample_rate > self.max_internal_sample_rate
{
return Err(SilkError::EncFsNotSupported);
}
if self.bit_rate < MIN_TARGET_RATE_BPS || self.bit_rate > MAX_TARGET_RATE_BPS {
return Err(SilkError::EncInvalidBitrate);
}
if !PAYLOAD_SIZES_MS.contains(&self.payload_size_ms) {
return Err(SilkError::EncPacketSizeNotSupported);
}
if !(0..=100).contains(&self.packet_loss_percentage) {
return Err(SilkError::EncInvalidLossRate);
}
if !matches!(self.use_dtx, 0 | 1) {
return Err(SilkError::EncInvalidDtxSetting);
}
if !matches!(self.use_cbr, 0 | 1) {
return Err(SilkError::EncInvalidCbrSetting);
}
if !matches!(self.use_in_band_fec, 0 | 1) {
return Err(SilkError::EncInvalidInbandFecSetting);
}
if !matches!(self.lbrr_coded, 0 | 1) {
return Err(SilkError::EncInternalError);
}
if self.n_channels_api < 1
|| self.n_channels_api > ENCODER_NUM_CHANNELS
|| self.n_channels_internal < 1
|| self.n_channels_internal > ENCODER_NUM_CHANNELS
|| self.n_channels_internal > self.n_channels_api
{
return Err(SilkError::EncInvalidNumberOfChannelsError);
}
if !(0..=10).contains(&self.complexity) {
return Err(SilkError::EncInvalidComplexitySetting);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn accepts_valid_configuration() {
let control = EncControl::default();
assert_eq!(control.check_control_input(), Ok(()));
}
#[test]
fn rejects_invalid_sample_rates() {
let mut control = EncControl::default();
control.api_sample_rate = 11_000;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncFsNotSupported)
);
control.api_sample_rate = 16_000;
control.desired_internal_sample_rate = 20_000;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncFsNotSupported)
);
control.desired_internal_sample_rate = 12_000;
control.max_internal_sample_rate = 8_000;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncFsNotSupported)
);
}
#[test]
fn validates_payload_size() {
let mut control = EncControl::default();
control.payload_size_ms = 15;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncPacketSizeNotSupported)
);
}
#[test]
fn validates_bit_rate_bounds() {
let mut control = EncControl::default();
control.bit_rate = 4_000;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidBitrate)
);
control.bit_rate = 90_000;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidBitrate)
);
}
#[test]
fn checks_boolean_flags() {
let mut control = EncControl::default();
control.use_dtx = 2;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidDtxSetting)
);
control.use_dtx = 0;
control.use_cbr = -1;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidCbrSetting)
);
control.use_cbr = 0;
control.use_in_band_fec = 5;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidInbandFecSetting)
);
}
#[test]
fn validates_channel_configuration() {
let mut control = EncControl::default();
control.n_channels_api = 0;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidNumberOfChannelsError)
);
control.n_channels_api = 2;
control.n_channels_internal = 3;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidNumberOfChannelsError)
);
control.n_channels_internal = 2;
control.n_channels_api = 1;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidNumberOfChannelsError)
);
}
#[test]
fn enforces_complexity_bounds() {
let mut control = EncControl::default();
control.complexity = 11;
assert_eq!(
control.check_control_input(),
Err(SilkError::EncInvalidComplexitySetting)
);
}
}