use mousiki::c_style_api::opus_decoder::{
OpusDecoderCtlRequest, opus_decode, opus_decoder_create, opus_decoder_ctl,
};
use mousiki::c_style_api::opus_encoder::{
OpusEncodeError, OpusEncoderCtlError, OpusEncoderCtlRequest, opus_encode, opus_encoder_create,
opus_encoder_ctl,
};
use mousiki::c_style_api::opus_multistream::{
OpusMultistreamDecoderCtlRequest, OpusMultistreamEncoderCtlRequest,
OpusMultistreamEncoderError, opus_multistream_decode, opus_multistream_decoder_create,
opus_multistream_decoder_ctl, opus_multistream_encode, opus_multistream_encoder_create,
opus_multistream_encoder_ctl, opus_multistream_encoder_get_encoder_state,
};
use mousiki::c_style_api::packet::{
Mode, opus_packet_get_mode, opus_packet_get_nb_frames, opus_packet_get_samples_per_frame,
opus_packet_parse,
};
use mousiki::c_style_api::repacketizer::{
opus_multistream_packet_pad, opus_multistream_packet_unpad, opus_packet_pad, opus_packet_unpad,
};
const OPUS_APPLICATION_VOIP: i32 = 2048;
const OPUS_APPLICATION_AUDIO: i32 = 2049;
const OPUS_APPLICATION_RESTRICTED_LOWDELAY: i32 = 2051;
const OPUS_AUTO: i32 = -1000;
const OPUS_BITRATE_MAX: i32 = -1;
const OPUS_UNIMPLEMENTED: i32 = -5;
const MODE_SILK_ONLY: i32 = 1000;
const MODE_HYBRID: i32 = 1001;
const MODE_CELT_ONLY: i32 = 1002;
const OPUS_FRAMESIZE_2_5_MS: i32 = 5001;
const OPUS_FRAMESIZE_5_MS: i32 = 5002;
const OPUS_FRAMESIZE_10_MS: i32 = 5003;
const OPUS_FRAMESIZE_20_MS: i32 = 5004;
const OPUS_FRAMESIZE_40_MS: i32 = 5005;
const OPUS_FRAMESIZE_60_MS: i32 = 5006;
const OPUS_FRAMESIZE_80_MS: i32 = 5007;
const OPUS_FRAMESIZE_100_MS: i32 = 5008;
const OPUS_FRAMESIZE_120_MS: i32 = 5009;
const OPUS_BANDWIDTH_NARROWBAND: i32 = 1101;
const OPUS_BANDWIDTH_MEDIUMBAND: i32 = 1102;
const OPUS_BANDWIDTH_WIDEBAND: i32 = 1103;
const OPUS_BANDWIDTH_SUPERWIDEBAND: i32 = 1104;
const OPUS_BANDWIDTH_FULLBAND: i32 = 1105;
const OPUS_SIGNAL_VOICE: i32 = 3001;
const OPUS_SIGNAL_MUSIC: i32 = 3002;
const MAX_PACKET: usize = 1500;
const MAX_FRAME_SAMP: usize = 5760;
const SAMPLES: usize = 48_000 * 30;
const SSAMPLES: usize = SAMPLES / 3;
#[derive(Clone)]
struct FastRand {
rz: u32,
rw: u32,
}
impl FastRand {
fn new(seed: u32) -> Self {
Self { rz: seed, rw: seed }
}
fn next(&mut self) -> u32 {
self.rz = 36969u32
.wrapping_mul(self.rz & 0xFFFF)
.wrapping_add(self.rz >> 16);
self.rw = 18000u32
.wrapping_mul(self.rw & 0xFFFF)
.wrapping_add(self.rw >> 16);
(self.rz << 16).wrapping_add(self.rw)
}
}
fn rand_sample<T: Copy>(rng: &mut FastRand, values: &[T]) -> T {
let idx = rng.next() as usize % values.len();
values[idx]
}
fn deb2_impl(t: &mut [u8], out: &mut [u8], p: &mut usize, k: usize, x: usize, y: usize) {
if x > 2 {
if y < 3 {
for i in 0..y {
*p = p.saturating_sub(1);
out[*p] = t[i + 1];
}
}
return;
}
t[x] = t[x - y];
deb2_impl(t, out, p, k, x + 1, y);
for i in (t[x - y] + 1)..(k as u8) {
t[x] = i;
deb2_impl(t, out, p, k, x + 1, x);
}
}
fn debruijn2(k: usize) -> Vec<u8> {
let mut out = vec![0u8; k * k];
let mut t = vec![0u8; k * 2];
let mut p = k * k;
deb2_impl(&mut t, &mut out, &mut p, k, 1, 1);
out
}
fn clamp_i16(value: i32) -> i16 {
value.clamp(i16::MIN as i32, i16::MAX as i32) as i16
}
fn generate_music(buf: &mut [i16], len: usize, rng: &mut FastRand) {
let samples = len.min(buf.len() / 2);
if samples == 0 {
return;
}
let mut a1 = 0i32;
let mut b1 = 0i32;
let mut a2 = 0i32;
let mut b2 = 0i32;
let mut c1 = 0i32;
let mut c2 = 0i32;
let mut d1 = 0i32;
let mut d2 = 0i32;
let mut j = 0i32;
let silence = samples.min(2880);
for i in 0..silence {
let idx = i * 2;
buf[idx] = 0;
buf[idx + 1] = 0;
}
for i in silence..samples {
let mut v1 =
(((j * ((j >> 12) ^ ((j >> 10 | j >> 12) & 26 & (j >> 7)))) & 128) + 128) << 15;
let mut v2 = v1;
let r = rng.next();
v1 += (r & 65_535) as i32;
v1 -= (r >> 16) as i32;
let r = rng.next();
v2 += (r & 65_535) as i32;
v2 -= (r >> 16) as i32;
b1 = v1 - a1 + ((b1 * 61 + 32) >> 6);
a1 = v1;
b2 = v2 - a2 + ((b2 * 61 + 32) >> 6);
a2 = v2;
c1 = (30 * (c1 + b1 + d1) + 32) >> 6;
d1 = b1;
c2 = (30 * (c2 + b2 + d2) + 32) >> 6;
d2 = b2;
v1 = (c1 + 128) >> 8;
v2 = (c2 + 128) >> 8;
let idx = i * 2;
buf[idx] = clamp_i16(v1);
buf[idx + 1] = clamp_i16(v2);
if i % 6 == 0 {
j += 1;
}
}
}
fn get_frame_size_enum(frame_size: usize, sampling_rate: usize) -> i32 {
if frame_size == sampling_rate / 400 {
OPUS_FRAMESIZE_2_5_MS
} else if frame_size == sampling_rate / 200 {
OPUS_FRAMESIZE_5_MS
} else if frame_size == sampling_rate / 100 {
OPUS_FRAMESIZE_10_MS
} else if frame_size == sampling_rate / 50 {
OPUS_FRAMESIZE_20_MS
} else if frame_size == sampling_rate / 25 {
OPUS_FRAMESIZE_40_MS
} else if frame_size == 3 * sampling_rate / 50 {
OPUS_FRAMESIZE_60_MS
} else if frame_size == 4 * sampling_rate / 50 {
OPUS_FRAMESIZE_80_MS
} else if frame_size == 5 * sampling_rate / 50 {
OPUS_FRAMESIZE_100_MS
} else if frame_size == 6 * sampling_rate / 50 {
OPUS_FRAMESIZE_120_MS
} else {
panic!("unsupported frame size: {frame_size}");
}
}
fn seed_from_env() -> u32 {
std::env::var("SEED")
.ok()
.and_then(|value| value.parse::<u32>().ok())
.unwrap_or(0xC0DEC0DE)
}
fn no_fuzz() -> bool {
std::env::var_os("TEST_OPUS_NOFUZZ").is_some()
}
fn is_bad_arg_multistream_create(err: &OpusMultistreamEncoderError) -> bool {
matches!(
err,
OpusMultistreamEncoderError::BadArgument
| OpusMultistreamEncoderError::EncoderInit(
mousiki::c_style_api::opus_encoder::OpusEncoderInitError::BadArgument
)
)
}
fn test_encode(
enc: &mut mousiki::c_style_api::opus_encoder::OpusEncoder<'_>,
channels: usize,
frame_size: usize,
dec: &mut mousiki::c_style_api::opus_decoder::OpusDecoder<'_>,
rng: &mut FastRand,
) -> Result<(), String> {
let mut samp_count = 0usize;
let mut inbuf = vec![0i16; SSAMPLES];
generate_music(&mut inbuf, SSAMPLES / 2, rng);
let mut outbuf = vec![0i16; MAX_FRAME_SAMP * 3];
let mut packet = vec![0u8; MAX_PACKET + 257];
let limit = SSAMPLES / 2;
if limit <= MAX_FRAME_SAMP {
return Ok(());
}
while samp_count < limit - MAX_FRAME_SAMP {
let start = samp_count
.checked_mul(channels)
.ok_or("input offset overflow")?;
let end = start
.checked_add(frame_size * channels)
.ok_or("input end overflow")?;
if end > inbuf.len() {
return Err("input buffer too small".to_string());
}
let len = opus_encode(
enc,
&inbuf[start..end],
frame_size,
&mut packet[..MAX_PACKET],
)
.map_err(|err| format!("opus_encode failed: {err:?}"))?;
if len > MAX_PACKET {
return Err("opus_encode returned oversized packet".to_string());
}
let out_samples = match opus_decode(
dec,
Some(&packet[..len]),
len,
&mut outbuf,
MAX_FRAME_SAMP,
false,
) {
Ok(samples) => samples,
Err(err) => {
let mut fs = 0i32;
let _ = opus_decoder_ctl(dec, OpusDecoderCtlRequest::GetSampleRate(&mut fs));
let fs_u32 = fs.max(0) as u32;
let frame_samples =
opus_packet_get_samples_per_frame(&packet[..len], fs_u32).unwrap_or_default();
let nb_frames = opus_packet_get_nb_frames(&packet[..len], len).unwrap_or_default();
let mode = opus_packet_get_mode(&packet[..len]).ok();
return Err(format!(
"opus_decode failed: {err:?}, len={len}, packet_samples={frame_samples}, \
nb_frames={nb_frames}, mode={mode:?}"
));
}
};
if out_samples != frame_size {
let mut fs = 0i32;
let _ = opus_decoder_ctl(dec, OpusDecoderCtlRequest::GetSampleRate(&mut fs));
let fs_u32 = fs.max(0) as u32;
let frame_samples =
opus_packet_get_samples_per_frame(&packet[..len], fs_u32).unwrap_or_default();
let nb_frames = opus_packet_get_nb_frames(&packet[..len], len).unwrap_or_default();
let mode = opus_packet_get_mode(&packet[..len]).ok();
return Err(format!(
"decoded sample count mismatch: expected {frame_size}, got {out_samples}, \
packet_samples={frame_samples}, nb_frames={nb_frames}, mode={mode:?}"
));
}
samp_count += frame_size;
}
Ok(())
}
fn fuzz_encoder_settings(
num_encoders: usize,
num_setting_changes: usize,
rng: &mut FastRand,
) -> Result<(), String> {
let sampling_rates = [8000, 12_000, 16_000, 24_000, 48_000];
let channels = [1, 2];
let applications = [
OPUS_APPLICATION_AUDIO,
OPUS_APPLICATION_VOIP,
OPUS_APPLICATION_RESTRICTED_LOWDELAY,
];
let bitrates = [
6000,
12_000,
16_000,
24_000,
32_000,
48_000,
64_000,
96_000,
510_000,
OPUS_AUTO,
OPUS_BITRATE_MAX,
];
let force_channels = [OPUS_AUTO, OPUS_AUTO, 1, 2];
let use_vbr = [0, 1, 1];
let vbr_constraints = [0, 1, 1];
let complexities = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let max_bandwidths = [
OPUS_BANDWIDTH_NARROWBAND,
OPUS_BANDWIDTH_MEDIUMBAND,
OPUS_BANDWIDTH_WIDEBAND,
OPUS_BANDWIDTH_SUPERWIDEBAND,
OPUS_BANDWIDTH_FULLBAND,
OPUS_BANDWIDTH_FULLBAND,
];
let signals = [OPUS_AUTO, OPUS_AUTO, OPUS_SIGNAL_VOICE, OPUS_SIGNAL_MUSIC];
let inband_fecs = [0, 0, 1];
let packet_loss_perc = [0, 1, 2, 5];
let lsb_depths = [8, 24];
let prediction_disabled = [0, 0, 1];
let use_dtx = [0, 1];
let frame_sizes_ms_x2 = [5, 10, 20, 40, 80, 120, 160, 200, 240];
for _ in 0..num_encoders {
let sampling_rate = rand_sample(rng, &sampling_rates);
let num_channels = rand_sample(rng, &channels);
let application = rand_sample(rng, &applications);
let mut dec = opus_decoder_create(sampling_rate, num_channels)
.map_err(|err| format!("decoder create failed: {err:?}"))?;
let mut enc = opus_encoder_create(sampling_rate, num_channels, application)
.map_err(|err| format!("encoder create failed: {err:?}"))?;
for _ in 0..num_setting_changes {
let bitrate = rand_sample(rng, &bitrates);
let mut force_channel = rand_sample(rng, &force_channels);
let vbr = rand_sample(rng, &use_vbr) != 0;
let vbr_constraint = rand_sample(rng, &vbr_constraints) != 0;
let complexity = rand_sample(rng, &complexities);
let max_bw = rand_sample(rng, &max_bandwidths);
let sig = rand_sample(rng, &signals);
let inband_fec = rand_sample(rng, &inband_fecs) != 0;
let pkt_loss = rand_sample(rng, &packet_loss_perc);
let lsb_depth = rand_sample(rng, &lsb_depths);
let pred_disabled = rand_sample(rng, &prediction_disabled) != 0;
let dtx = rand_sample(rng, &use_dtx) != 0;
let frame_size_ms_x2 = rand_sample(rng, &frame_sizes_ms_x2);
let frame_size = frame_size_ms_x2 as usize * sampling_rate as usize / 2000;
let frame_size_enum = get_frame_size_enum(frame_size, sampling_rate as usize);
if force_channel != OPUS_AUTO {
force_channel = force_channel.min(num_channels);
}
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBitrate(bitrate))
.map_err(|err| format!("set bitrate failed: {err:?}"))?;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetForceChannels(force_channel),
)
.map_err(|err| format!("set force channels failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetVbr(vbr))
.map_err(|err| format!("set vbr failed: {err:?}"))?;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetVbrConstraint(vbr_constraint),
)
.map_err(|err| format!("set vbr constraint failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetComplexity(complexity))
.map_err(|err| format!("set complexity failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetMaxBandwidth(max_bw))
.map_err(|err| format!("set max bandwidth failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetSignal(sig))
.map_err(|err| format!("set signal failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetInbandFec(inband_fec))
.map_err(|err| format!("set inband fec failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetPacketLossPerc(pkt_loss))
.map_err(|err| format!("set packet loss failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetLsbDepth(lsb_depth))
.map_err(|err| format!("set lsb depth failed: {err:?}"))?;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetPredictionDisabled(pred_disabled),
)
.map_err(|err| format!("set prediction disabled failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetDtx(dtx))
.map_err(|err| format!("set dtx failed: {err:?}"))?;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetExpertFrameDuration(frame_size_enum),
)
.map_err(|err| format!("set frame duration failed: {err:?}"))?;
if let Err(msg) =
test_encode(&mut enc, num_channels as usize, frame_size, &mut dec, rng)
{
return Err(format!(
"fuzz_encoder_settings failed: {msg}, fs={}k, ch={}, app={}, bitrate={}, \
force_ch={}, vbr={}, vbr_constraint={}, complexity={}, max_bw={}, signal={}, \
inband_fec={}, pkt_loss={}, lsb_depth={}, pred_disabled={}, dtx={}, frame_ms_x2={}",
sampling_rate / 1000,
num_channels,
application,
bitrate,
force_channel,
vbr as i32,
vbr_constraint as i32,
complexity,
max_bw,
sig,
inband_fec as i32,
pkt_loss,
lsb_depth,
pred_disabled as i32,
dtx as i32,
frame_size_ms_x2
));
}
}
}
Ok(())
}
fn run_test1(no_fuzz: bool, rng: &mut FastRand) -> Result<(), String> {
let fsizes = [960 * 3, 960 * 2, 120, 240, 480, 960];
let mut mapping = [0u8; 256];
mapping[0] = 0;
mapping[1] = 1;
mapping[2] = 255;
let mut enc = opus_encoder_create(48_000, 2, OPUS_APPLICATION_VOIP)
.map_err(|err| format!("encoder create failed: {err:?}"))?;
let invalid = opus_multistream_encoder_create(8000, 2, 2, 0, &mapping, OPUS_UNIMPLEMENTED);
if !matches!(invalid, Err(ref err) if is_bad_arg_multistream_create(err)) {
return Err("invalid multistream create should fail".to_string());
}
let invalid = opus_multistream_encoder_create(8000, 0, 1, 0, &mapping, OPUS_APPLICATION_VOIP);
if !matches!(invalid, Err(ref err) if is_bad_arg_multistream_create(err)) {
return Err("invalid multistream create should fail".to_string());
}
let invalid = opus_multistream_encoder_create(44_100, 2, 2, 0, &mapping, OPUS_APPLICATION_VOIP);
if !matches!(invalid, Err(ref err) if is_bad_arg_multistream_create(err)) {
return Err("invalid multistream create should fail".to_string());
}
let invalid = opus_multistream_encoder_create(8000, 2, 2, 3, &mapping, OPUS_APPLICATION_VOIP);
if !matches!(invalid, Err(ref err) if is_bad_arg_multistream_create(err)) {
return Err("invalid multistream create should fail".to_string());
}
let invalid =
opus_multistream_encoder_create(8000, 2, usize::MAX, 0, &mapping, OPUS_APPLICATION_VOIP);
if !matches!(invalid, Err(ref err) if is_bad_arg_multistream_create(err)) {
return Err("invalid multistream create should fail".to_string());
}
let invalid = opus_multistream_encoder_create(8000, 256, 2, 0, &mapping, OPUS_APPLICATION_VOIP);
if !matches!(invalid, Err(ref err) if is_bad_arg_multistream_create(err)) {
return Err("invalid multistream create should fail".to_string());
}
let mut ms_enc =
opus_multistream_encoder_create(8000, 2, 2, 0, &mapping, OPUS_APPLICATION_AUDIO)
.map_err(|err| format!("multistream encoder create failed: {err:?}"))?;
let mut lsb = 0;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::GetBitrate(&mut lsb),
)
.map_err(|err| format!("get bitrate failed: {err:?}"))?;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::GetLsbDepth(&mut lsb),
)
.map_err(|err| format!("get lsb depth failed: {err:?}"))?;
if lsb < 16 {
return Err("lsb depth below expected minimum".to_string());
}
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut ms_enc, 1)
.map_err(|err| format!("get encoder state failed: {err:?}"))?;
let mut stream_lsb = 0;
opus_encoder_ctl(
stream_encoder,
OpusEncoderCtlRequest::GetLsbDepth(&mut stream_lsb),
)
.map_err(|err| format!("get stream lsb depth failed: {err:?}"))?;
if lsb != stream_lsb {
return Err("lsb depth mismatch between multistream and stream".to_string());
}
let invalid_state = opus_multistream_encoder_get_encoder_state(&mut ms_enc, 2);
if !matches!(invalid_state, Err(OpusMultistreamEncoderError::BadArgument)) {
return Err("invalid stream id should fail".to_string());
}
let mut dec =
opus_decoder_create(48_000, 2).map_err(|err| format!("decoder create failed: {err:?}"))?;
let mut ms_dec = opus_multistream_decoder_create(48_000, 2, 2, 0, &mapping)
.map_err(|err| format!("multistream decoder create failed: {err:?}"))?;
let mut ms_dec_err = opus_multistream_decoder_create(48_000, 3, 2, 0, &mapping)
.map_err(|err| format!("multistream decoder create failed: {err:?}"))?;
let mut dec_err = Vec::with_capacity(10);
dec_err.push(
opus_decoder_create(48_000, 2).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(48_000, 1).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(24_000, 2).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(24_000, 1).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(16_000, 2).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(16_000, 1).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(12_000, 2).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(12_000, 1).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(8000, 2).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
dec_err.push(
opus_decoder_create(8000, 1).map_err(|err| format!("decoder create failed: {err:?}"))?,
);
let mut inbuf = vec![0i16; SAMPLES * 2];
let mut outbuf = vec![0i16; SAMPLES * 2];
let mut out2buf = vec![0i16; MAX_FRAME_SAMP * 3];
generate_music(&mut inbuf, SAMPLES, rng);
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBandwidth(OPUS_AUTO))
.map_err(|err| format!("set bandwidth failed: {err:?}"))?;
let invalid = opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetForceMode(-2));
if !matches!(invalid, Err(OpusEncoderCtlError::BadArgument)) {
return Err("invalid force mode should fail".to_string());
}
let mut packet = vec![0u8; MAX_PACKET + 257];
let invalid = opus_encode(&mut enc, &inbuf, 500, &mut packet[..MAX_PACKET]);
if !matches!(invalid, Err(OpusEncodeError::BadArgument)) {
return Err("encode with invalid frame size should fail".to_string());
}
let allow_silk_final_range = std::env::var_os("ALLOW_SILK_FINAL_RANGE").is_some();
let silk_range_limit = 48_000 / 50;
for rc in 0..3 {
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetVbr(rc < 2))
.map_err(|err| format!("set vbr failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetVbrConstraint(rc == 1))
.map_err(|err| format!("set vbr constraint failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetVbrConstraint(rc == 1))
.map_err(|err| format!("set vbr constraint failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetInbandFec(rc == 0))
.map_err(|err| format!("set inband fec failed: {err:?}"))?;
for j in 0..13 {
let modes = [0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2];
let rates = [
6000, 12_000, 48_000, 16_000, 32_000, 48_000, 64_000, 512_000, 13_000, 24_000,
48_000, 64_000, 96_000,
];
let frame = [
960 * 2,
960,
480,
960,
960,
960,
480,
960 * 3,
960 * 3,
960,
480,
240,
120,
];
let rate = rates[j] + (rng.next() % rates[j] as u32) as i32;
let mut i = 0usize;
let mut count = 0i32;
while i < SSAMPLES - MAX_FRAME_SAMP {
let frame_size = frame[j];
if rng.next() & 255 == 0 {
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::ResetState)
.map_err(|err| format!("reset encoder failed: {err:?}"))?;
opus_decoder_ctl(&mut dec, OpusDecoderCtlRequest::ResetState)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
if rng.next() & 1 != 0 {
opus_decoder_ctl(
&mut dec_err[(rng.next() & 1) as usize],
OpusDecoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
}
}
if rng.next() & 127 == 0 {
opus_decoder_ctl(
&mut dec_err[(rng.next() & 1) as usize],
OpusDecoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
}
if rng.next() % 10 == 0 {
let complex = (rng.next() % 11) as i32;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetComplexity(complex))
.map_err(|err| format!("set complexity failed: {err:?}"))?;
}
if rng.next() % 50 == 0 {
opus_decoder_ctl(&mut dec, OpusDecoderCtlRequest::ResetState)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
}
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetInbandFec(rc == 0))
.map_err(|err| format!("set inband fec failed: {err:?}"))?;
let mode = MODE_SILK_ONLY + modes[j];
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetForceMode(mode))
.map_err(|err| format!("set force mode failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetDtx(rng.next() & 1 != 0))
.map_err(|err| format!("set dtx failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBitrate(rate))
.map_err(|err| format!("set bitrate failed: {err:?}"))?;
let forced_channels = if rates[j] >= 64_000 { 2 } else { 1 };
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetForceChannels(forced_channels),
)
.map_err(|err| format!("set force channels failed: {err:?}"))?;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetComplexity((count >> 2) % 11),
)
.map_err(|err| format!("set complexity failed: {err:?}"))?;
let pkt_loss = (rng.next() & 15) & (rng.next() % 15);
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetPacketLossPerc(pkt_loss as i32),
)
.map_err(|err| format!("set packet loss failed: {err:?}"))?;
let mut bw = if modes[j] == 0 {
OPUS_BANDWIDTH_NARROWBAND + (rng.next() % 3) as i32
} else if modes[j] == 1 {
OPUS_BANDWIDTH_SUPERWIDEBAND + (rng.next() & 1) as i32
} else {
OPUS_BANDWIDTH_NARROWBAND + (rng.next() % 5) as i32
};
if modes[j] == 2 && bw == OPUS_BANDWIDTH_MEDIUMBAND {
bw += 3;
}
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBandwidth(bw))
.map_err(|err| format!("set bandwidth failed: {err:?}"))?;
let offset = i * 2;
let len = opus_encode(
&mut enc,
&inbuf[offset..],
frame_size,
&mut packet[..MAX_PACKET],
)
.map_err(|err| {
format!(
"encode failed: {err:?}, mode={mode}, rate={rate}, frame_size={frame_size}, \
bw={bw}, rc={rc}, pkt_loss={pkt_loss}, forced_channels={forced_channels}, \
count={count}, offset={offset}"
)
})?;
if len > MAX_PACKET {
return Err("encoded packet too large".to_string());
}
let mut enc_final_range = 0u32;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::GetFinalRange(&mut enc_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
let mut len = len;
if rng.next() & 3 == 0 {
opus_packet_pad(&mut packet, len, len + 1)
.map_err(|err| format!("packet pad failed: {err:?}"))?;
len += 1;
}
if rng.next() & 7 == 0 {
opus_packet_pad(&mut packet, len, len + 256)
.map_err(|err| format!("packet pad failed: {err:?}"))?;
len += 256;
}
if rng.next() & 3 == 0 {
len = opus_packet_unpad(&mut packet, len)
.map_err(|err| format!("packet unpad failed: {err:?}"))?;
}
let out_samples = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf[offset..],
MAX_FRAME_SAMP,
false,
)
.map_err(|err| {
format!(
"decode failed: {err:?}, stage=main, mode={}, frame_size={}, len={}, \
offset={}, rc={}, bw={}, rate={}",
MODE_SILK_ONLY + modes[j],
frame_size,
len,
offset,
rc,
bw,
rate
)
})?;
if out_samples != frame_size {
return Err("decoded sample count mismatch".to_string());
}
let mut dec_final_range = 0u32;
opus_decoder_ctl(
&mut dec,
OpusDecoderCtlRequest::GetFinalRange(&mut dec_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
if allow_silk_final_range
&& modes[j] == 0
&& frame_size <= silk_range_limit
&& enc_final_range != dec_final_range
{
return Err(format!(
"final range mismatch: mode={}, frame_size={}, enc={}, dec={}, \
rate={}, bw={}, rc={}, pkt_loss={}, forced_channels={}, count={}",
MODE_SILK_ONLY + modes[j],
frame_size,
enc_final_range,
dec_final_range,
rate,
bw,
rc,
pkt_loss,
forced_channels,
count
));
}
let out_samples = opus_decode(
&mut dec_err[0],
Some(&packet[..len]),
len,
&mut out2buf,
frame_size,
rng.next() & 3 != 0,
)
.map_err(|err| {
format!(
"decode failed: {err:?}, stage=lbr, mode={}, frame_size={}, len={}, \
offset={}, rc={}, bw={}, rate={}",
MODE_SILK_ONLY + modes[j],
frame_size,
len,
offset,
rc,
bw,
rate
)
})?;
if out_samples != frame_size {
return Err("lbr decode sample count mismatch".to_string());
}
let use_packet = rng.next() & 3 != 0;
let packet_len = if use_packet { len } else { 0 };
let packet_opt = if use_packet {
Some(&packet[..len])
} else {
None
};
let out_samples = opus_decode(
&mut dec_err[1],
packet_opt,
packet_len,
&mut out2buf,
MAX_FRAME_SAMP,
rng.next() & 7 != 0,
)
.map_err(|err| {
format!(
"decode failed: {err:?}, stage=lbr_plc, mode={}, frame_size={}, len={}, \
offset={}, rc={}, bw={}, rate={}, use_packet={}",
MODE_SILK_ONLY + modes[j],
frame_size,
packet_len,
offset,
rc,
bw,
rate,
use_packet as i32
)
})?;
if out_samples < 120 {
return Err("lbr decode produced too few samples".to_string());
}
i += frame_size;
count += 1;
}
}
}
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetForceMode(OPUS_AUTO))
.map_err(|err| format!("set force mode failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetForceChannels(OPUS_AUTO))
.map_err(|err| format!("set force channels failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetInbandFec(false))
.map_err(|err| format!("set inband fec failed: {err:?}"))?;
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetDtx(false))
.map_err(|err| format!("set dtx failed: {err:?}"))?;
for rc in 0..3 {
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetVbr(rc < 2),
)
.map_err(|err| format!("set vbr failed: {err:?}"))?;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetVbrConstraint(rc == 1),
)
.map_err(|err| format!("set vbr constraint failed: {err:?}"))?;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetVbrConstraint(rc == 1),
)
.map_err(|err| format!("set vbr constraint failed: {err:?}"))?;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetInbandFec(rc == 0),
)
.map_err(|err| format!("set inband fec failed: {err:?}"))?;
for j in 0..16 {
let modes = [0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2];
let rates = [
4000, 12_000, 32_000, 8000, 16_000, 32_000, 48_000, 88_000, 4000, 12_000, 32_000,
8000, 16_000, 32_000, 48_000, 88_000,
];
let frame = [
160, 160, 80, 160, 160, 80, 40, 20, 160, 160, 80, 160, 160, 80, 40, 20,
];
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetInbandFec(rc == 0 && j == 1),
)
.map_err(|err| format!("set inband fec failed: {err:?}"))?;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetForceMode(MODE_SILK_ONLY + modes[j]),
)
.map_err(|err| format!("set force mode failed: {err:?}"))?;
let rate = rates[j] + (rng.next() % rates[j] as u32) as i32;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetDtx(rng.next() & 1 != 0),
)
.map_err(|err| format!("set dtx failed: {err:?}"))?;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetBitrate(rate),
)
.map_err(|err| format!("set bitrate failed: {err:?}"))?;
let mut i = 0usize;
let mut count = 0i32;
while i < (SSAMPLES / 12) - MAX_FRAME_SAMP {
let mut pred = false;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::GetPredictionDisabled(&mut pred),
)
.map_err(|err| format!("get prediction disabled failed: {err:?}"))?;
let new_pred = (rng.next() & 15) < if pred { 11 } else { 4 };
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetPredictionDisabled(new_pred),
)
.map_err(|err| format!("set prediction disabled failed: {err:?}"))?;
let frame_size = frame[j];
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetComplexity((count >> 2) % 11),
)
.map_err(|err| format!("set complexity failed: {err:?}"))?;
let pkt_loss = (rng.next() & 15) & (rng.next() % 15);
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::SetPacketLossPerc(pkt_loss as i32),
)
.map_err(|err| format!("set packet loss failed: {err:?}"))?;
if rng.next() & 255 == 0 {
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset encoder failed: {err:?}"))?;
opus_multistream_decoder_ctl(
&mut ms_dec,
OpusMultistreamDecoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
if rng.next() & 3 != 0 {
opus_multistream_decoder_ctl(
&mut ms_dec_err,
OpusMultistreamDecoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
}
}
if rng.next() & 255 == 0 {
opus_multistream_decoder_ctl(
&mut ms_dec_err,
OpusMultistreamDecoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
}
let offset = i * 2;
let len =
opus_multistream_encode(&mut ms_enc, &inbuf[offset..], frame_size, &mut packet)
.map_err(|err| format!("multistream encode failed: {err:?}"))?;
if len > MAX_PACKET {
return Err("multistream packet too large".to_string());
}
let mut enc_final_range = 0u32;
opus_multistream_encoder_ctl(
&mut ms_enc,
OpusMultistreamEncoderCtlRequest::GetFinalRange(&mut enc_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
let mut len = len;
if rng.next() & 3 == 0 {
opus_multistream_packet_pad(&mut packet, len, len + 1, 2)
.map_err(|err| format!("packet pad failed: {err:?}"))?;
len += 1;
}
if rng.next() & 7 == 0 {
opus_multistream_packet_pad(&mut packet, len, len + 256, 2)
.map_err(|err| format!("packet pad failed: {err:?}"))?;
len += 256;
}
if rng.next() & 3 == 0 {
len = opus_multistream_packet_unpad(&mut packet, len, 2)
.map_err(|err| format!("packet unpad failed: {err:?}"))?;
}
let out_samples = opus_multistream_decode(
&mut ms_dec,
&packet[..len],
len,
&mut out2buf,
MAX_FRAME_SAMP,
false,
)
.map_err(|err| format!("multistream decode failed: {err:?}"))?;
if out_samples != frame_size * 6 {
return Err("multistream decoded sample count mismatch".to_string());
}
let mut dec_final_range = 0u32;
opus_multistream_decoder_ctl(
&mut ms_dec,
OpusMultistreamDecoderCtlRequest::GetFinalRange(&mut dec_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
if allow_silk_final_range && modes[j] == 0 && enc_final_range != dec_final_range {
return Err(format!(
"multistream final range mismatch: frame_size={}, enc={}, dec={}",
frame_size, enc_final_range, dec_final_range
));
}
let loss = rng.next() & 63 == 0;
let loss_len = if loss { 0 } else { len };
let loss_packet = if loss { &packet[..0] } else { &packet[..len] };
let out_samples = opus_multistream_decode(
&mut ms_dec_err,
loss_packet,
loss_len,
&mut out2buf,
frame_size * 6,
rng.next() & 3 != 0,
)
.map_err(|err| format!("multistream decode failed: {err:?}"))?;
if out_samples != frame_size * 6 {
return Err("multistream lbr decoded sample count mismatch".to_string());
}
i += frame_size;
count += 1;
}
}
}
let mut bitrate_bps = 512_000i32;
let mut fsize = (rng.next() % 31) as usize;
let mut fswitch = 100i32;
let db62 = debruijn2(6);
let mut i = 0usize;
while i < SAMPLES * 4 {
let frame_size = fsizes[db62[fsize] as usize];
let offset = i % (SAMPLES - MAX_FRAME_SAMP);
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBitrate(bitrate_bps))
.map_err(|err| format!("set bitrate failed: {err:?}"))?;
let len = opus_encode(
&mut enc,
&inbuf[offset * 2..],
frame_size,
&mut packet[..MAX_PACKET],
)
.map_err(|err| format!("encode failed: {err:?}"))?;
if len > MAX_PACKET {
return Err("encoded packet too large".to_string());
}
let mut enc_final_range = 0u32;
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::GetFinalRange(&mut enc_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
let out_samples = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf[offset * 2..],
MAX_FRAME_SAMP,
false,
)
.map_err(|err| format!("decode failed: {err:?}"))?;
if out_samples != frame_size {
return Err("decoded sample count mismatch".to_string());
}
let mut dec_final_range = 0u32;
opus_decoder_ctl(
&mut dec,
OpusDecoderCtlRequest::GetFinalRange(&mut dec_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
let compare_range = allow_silk_final_range
&& matches!(
opus_packet_get_mode(&packet[..len]),
Ok(mousiki::c_style_api::packet::Mode::SILK)
);
if compare_range && frame_size <= silk_range_limit && dec_final_range != enc_final_range {
return Err(format!(
"final range mismatch: frame_size={}, enc={}, dec={}, bitrate={}",
frame_size, enc_final_range, dec_final_range, bitrate_bps
));
}
let parsed = opus_packet_parse(&packet[..len], len)
.map_err(|err| format!("packet parse failed: {err:?}"))?;
let mut len = len;
if rng.next() & 1023 == 0 {
len = 0;
}
for byte_idx in parsed.payload_offset..len {
for bit in 0..8 {
if !no_fuzz && rng.next() & 1023 == 0 {
packet[byte_idx] ^= 1u8 << bit;
}
}
}
let out_samples = if len > 0 {
opus_decode(
&mut dec_err[0],
Some(&packet[..len]),
len,
&mut out2buf,
MAX_FRAME_SAMP,
false,
)
.map_err(|err| format!("decode failed: {err:?}"))?
} else {
opus_decode(
&mut dec_err[0],
None,
0,
&mut out2buf,
MAX_FRAME_SAMP,
false,
)
.map_err(|err| format!("decode failed: {err:?}"))?
};
if len > 0 && out_samples != frame_size {
return Err("decoded sample count mismatch".to_string());
}
let mut dec_final_range = 0u32;
opus_decoder_ctl(
&mut dec_err[0],
OpusDecoderCtlRequest::GetFinalRange(&mut dec_final_range),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
let dec2 = (rng.next() % 9 + 1) as usize;
let out_samples = if len > 0 {
opus_decode(
&mut dec_err[dec2],
Some(&packet[..len]),
len,
&mut out2buf,
MAX_FRAME_SAMP,
false,
)
.map_err(|err| format!("decode failed: {err:?}"))?
} else {
opus_decode(
&mut dec_err[dec2],
None,
0,
&mut out2buf,
MAX_FRAME_SAMP,
false,
)
.map_err(|err| format!("decode failed: {err:?}"))?
};
if out_samples > MAX_FRAME_SAMP {
return Err("decoded sample count exceeds max".to_string());
}
let mut dec_final_range2 = 0u32;
opus_decoder_ctl(
&mut dec_err[dec2],
OpusDecoderCtlRequest::GetFinalRange(&mut dec_final_range2),
)
.map_err(|err| format!("get final range failed: {err:?}"))?;
if len > 0 && dec_final_range != dec_final_range2 {
return Err(format!(
"final range mismatch: frame_size={}, dec1={}, dec2={}",
frame_size, dec_final_range, dec_final_range2
));
}
fswitch -= 1;
if fswitch < 1 {
let new_size;
fsize = (fsize + 1) % 36;
new_size = fsizes[db62[fsize] as usize];
if new_size == 960 || new_size == 480 {
fswitch = (2880 / new_size) as i32 * ((rng.next() % 19) as i32 + 1);
} else {
fswitch = (rng.next() % (2880 / new_size) as u32) as i32 + 1;
}
}
bitrate_bps = (((rng.next() % 508_000) as i32 + 4000) + bitrate_bps) >> 1;
i += frame_size;
}
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::ResetState)
.map_err(|err| format!("reset encoder failed: {err:?}"))?;
opus_multistream_encoder_ctl(&mut ms_enc, OpusMultistreamEncoderCtlRequest::ResetState)
.map_err(|err| format!("reset encoder failed: {err:?}"))?;
opus_decoder_ctl(&mut dec, OpusDecoderCtlRequest::ResetState)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
opus_multistream_decoder_ctl(&mut ms_dec, OpusMultistreamDecoderCtlRequest::ResetState)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
opus_multistream_decoder_ctl(
&mut ms_dec_err,
OpusMultistreamDecoderCtlRequest::ResetState,
)
.map_err(|err| format!("reset decoder failed: {err:?}"))?;
Ok(())
}
#[test]
fn opus_encode_decode_smoke() {
let sampling_rate = 48_000usize;
let channels = 2usize;
let frame_size = sampling_rate / 50;
let frame_enum = get_frame_size_enum(frame_size, sampling_rate);
let mut enc = opus_encoder_create(
sampling_rate as i32,
channels as i32,
OPUS_APPLICATION_AUDIO,
)
.expect("encoder");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetExpertFrameDuration(frame_enum),
)
.expect("set frame duration");
let mut dec = opus_decoder_create(sampling_rate as i32, channels as i32).expect("decoder");
let total_frames = 10usize;
let total_samples = frame_size * total_frames;
let mut inbuf = vec![0i16; total_samples * channels];
let mut rng = FastRand::new(0xC0DEC0DE);
generate_music(&mut inbuf, total_samples, &mut rng);
let mut packet = vec![0u8; MAX_PACKET];
let mut outbuf = vec![0i16; MAX_FRAME_SAMP * channels];
for frame_idx in 0..total_frames {
let start = frame_idx * frame_size * channels;
let end = start + frame_size * channels;
let len =
opus_encode(&mut enc, &inbuf[start..end], frame_size, &mut packet).expect("encode");
assert!(len <= MAX_PACKET);
let decoded = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf,
MAX_FRAME_SAMP,
false,
)
.expect("decode");
assert_eq!(decoded, frame_size);
}
}
#[test]
fn opus_encode_silk_10ms_round_trip() {
let sampling_rate = 48_000usize;
let channels = 2usize;
let frame_size = sampling_rate / 100;
let mut enc = opus_encoder_create(
sampling_rate as i32,
channels as i32,
OPUS_APPLICATION_AUDIO,
)
.expect("encoder");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetForceMode(MODE_SILK_ONLY),
)
.expect("force silk");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetExpertFrameDuration(OPUS_FRAMESIZE_10_MS),
)
.expect("set frame duration");
let mut dec = opus_decoder_create(sampling_rate as i32, channels as i32).expect("decoder");
let mut inbuf = vec![0i16; frame_size * channels];
let mut rng = FastRand::new(0xDEC0DE01);
generate_music(&mut inbuf, frame_size, &mut rng);
let mut packet = vec![0u8; MAX_PACKET];
let mut outbuf = vec![0i16; MAX_FRAME_SAMP * channels];
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode");
let decoded = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf,
MAX_FRAME_SAMP,
false,
)
.expect("decode");
assert_eq!(decoded, frame_size);
}
#[test]
fn opus_encode_celt_60ms_multiframe_round_trip() {
let sampling_rate = 48_000usize;
let channels = 2usize;
let frame_size = 3 * sampling_rate / 50;
let mut enc = opus_encoder_create(
sampling_rate as i32,
channels as i32,
OPUS_APPLICATION_AUDIO,
)
.expect("encoder");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetForceMode(MODE_CELT_ONLY),
)
.expect("force celt");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetExpertFrameDuration(OPUS_FRAMESIZE_60_MS),
)
.expect("set frame duration");
let mut dec = opus_decoder_create(sampling_rate as i32, channels as i32).expect("decoder");
let mut inbuf = vec![0i16; frame_size * channels];
let mut rng = FastRand::new(0xDEC0DE02);
generate_music(&mut inbuf, frame_size, &mut rng);
let mut packet = vec![0u8; MAX_PACKET];
let mut outbuf = vec![0i16; MAX_FRAME_SAMP * channels];
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode");
let decoded = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf,
MAX_FRAME_SAMP,
false,
)
.expect("decode");
assert_eq!(decoded, frame_size);
}
#[test]
fn opus_encode_hybrid_round_trip() {
let sampling_rate = 48_000usize;
let channels = 2usize;
let frame_size = sampling_rate / 50;
let mut enc = opus_encoder_create(
sampling_rate as i32,
channels as i32,
OPUS_APPLICATION_AUDIO,
)
.expect("encoder");
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetForceMode(MODE_HYBRID))
.expect("force hybrid");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetExpertFrameDuration(OPUS_FRAMESIZE_20_MS),
)
.expect("set frame duration");
let mut dec = opus_decoder_create(sampling_rate as i32, channels as i32).expect("decoder");
let mut inbuf = vec![0i16; frame_size * channels];
let mut rng = FastRand::new(0xDEC0DE03);
generate_music(&mut inbuf, frame_size, &mut rng);
let mut packet = vec![0u8; MAX_PACKET];
let mut outbuf = vec![0i16; MAX_FRAME_SAMP * channels];
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode");
let decoded = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf,
MAX_FRAME_SAMP,
false,
)
.expect("decode");
assert_eq!(decoded, frame_size);
}
#[test]
fn opus_encode_hybrid_multiframe_round_trip() {
let sampling_rate = 48_000usize;
let channels = 1usize;
let frame_size = 2 * sampling_rate / 50;
let mut enc = opus_encoder_create(
sampling_rate as i32,
channels as i32,
OPUS_APPLICATION_AUDIO,
)
.expect("encoder");
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetForceMode(MODE_HYBRID))
.expect("force hybrid");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetExpertFrameDuration(OPUS_FRAMESIZE_40_MS),
)
.expect("set frame duration");
let mut dec = opus_decoder_create(sampling_rate as i32, channels as i32).expect("decoder");
let mut inbuf = vec![0i16; frame_size * channels];
let mut rng = FastRand::new(0xDEC0DE04);
generate_music(&mut inbuf, frame_size, &mut rng);
let mut packet = vec![0u8; MAX_PACKET];
let mut outbuf = vec![0i16; MAX_FRAME_SAMP * channels];
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode");
assert_eq!(opus_packet_get_mode(&packet[..len]).unwrap(), Mode::HYBRID);
assert_eq!(opus_packet_get_nb_frames(&packet[..len], len).unwrap(), 2);
assert_eq!(
opus_packet_get_samples_per_frame(&packet[..len], 48_000).unwrap(),
sampling_rate / 50
);
let decoded = opus_decode(
&mut dec,
Some(&packet[..len]),
len,
&mut outbuf,
MAX_FRAME_SAMP,
false,
)
.expect("decode");
assert_eq!(decoded, frame_size);
}
#[test]
fn opus_encode_hybrid_to_celt_transition_emits_bridge_frame() {
let sampling_rate = 48_000usize;
let channels = 1usize;
let frame_size = sampling_rate / 50;
let mut enc = opus_encoder_create(
sampling_rate as i32,
channels as i32,
OPUS_APPLICATION_AUDIO,
)
.expect("encoder");
opus_encoder_ctl(
&mut enc,
OpusEncoderCtlRequest::SetBandwidth(OPUS_BANDWIDTH_FULLBAND),
)
.expect("set bandwidth");
let mut rng = FastRand::new(0xDEC0DE05);
let mut packet = vec![0u8; MAX_PACKET];
let mut inbuf = vec![0i16; frame_size * channels];
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBitrate(12_000)).expect("set low bitrate");
generate_music(&mut inbuf, frame_size, &mut rng);
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode hybrid");
assert_eq!(opus_packet_get_mode(&packet[..len]).unwrap(), Mode::HYBRID);
opus_encoder_ctl(&mut enc, OpusEncoderCtlRequest::SetBitrate(256_000))
.expect("set high bitrate");
generate_music(&mut inbuf, frame_size, &mut rng);
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode transition");
assert_eq!(opus_packet_get_mode(&packet[..len]).unwrap(), Mode::HYBRID);
generate_music(&mut inbuf, frame_size, &mut rng);
let len = opus_encode(&mut enc, &inbuf, frame_size, &mut packet).expect("encode celt");
assert_eq!(opus_packet_get_mode(&packet[..len]).unwrap(), Mode::CELT);
}
#[test]
fn opus_encoder_ctl_application_lookahead_and_dtx_parity() {
let sample_rate = 48_000;
let channels = 1;
let frame_size = sample_rate as usize / 50;
let mut encoder =
opus_encoder_create(sample_rate, channels, OPUS_APPLICATION_AUDIO).expect("encoder");
let mut application = 0;
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::GetApplication(&mut application),
)
.expect("get application");
assert_eq!(application, OPUS_APPLICATION_AUDIO);
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::SetApplication(OPUS_APPLICATION_VOIP),
)
.expect("set application before first encode");
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::GetApplication(&mut application),
)
.expect("get application after set");
assert_eq!(application, OPUS_APPLICATION_VOIP);
let mut sample_rate_out = 0;
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::GetSampleRate(&mut sample_rate_out),
)
.expect("get sample rate");
assert_eq!(sample_rate_out, sample_rate);
let mut lookahead = 0;
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::GetLookahead(&mut lookahead),
)
.expect("get lookahead");
assert_eq!(lookahead, sample_rate / 400 + sample_rate / 250);
let mut voice_ratio = 0;
opus_encoder_ctl(&mut encoder, OpusEncoderCtlRequest::SetVoiceRatio(37))
.expect("set voice ratio");
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::GetVoiceRatio(&mut voice_ratio),
)
.expect("get voice ratio");
assert_eq!(voice_ratio, 37);
let mut rld_encoder =
opus_encoder_create(sample_rate, channels, OPUS_APPLICATION_RESTRICTED_LOWDELAY)
.expect("rld encoder");
opus_encoder_ctl(
&mut rld_encoder,
OpusEncoderCtlRequest::GetLookahead(&mut lookahead),
)
.expect("get rld lookahead");
assert_eq!(lookahead, sample_rate / 400);
opus_encoder_ctl(&mut encoder, OpusEncoderCtlRequest::SetDtx(true)).expect("enable dtx");
opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::SetForceMode(MODE_SILK_ONLY),
)
.expect("force silk");
let quiet_frame = vec![0i16; frame_size * channels as usize];
let mut packet = vec![0u8; MAX_PACKET];
for _ in 0..12 {
opus_encode(&mut encoder, &quiet_frame, frame_size, &mut packet).expect("encode quiet");
}
let mut in_dtx = false;
opus_encoder_ctl(&mut encoder, OpusEncoderCtlRequest::GetInDtx(&mut in_dtx))
.expect("get in dtx");
assert!(in_dtx);
let invalid = opus_encoder_ctl(
&mut encoder,
OpusEncoderCtlRequest::SetApplication(OPUS_APPLICATION_AUDIO),
);
assert!(matches!(invalid, Err(OpusEncoderCtlError::BadArgument)));
}
#[test]
fn opus_multistream_encoder_ctl_matches_first_stream_for_new_getters() {
let sample_rate = 48_000;
let mapping = [0u8, 1u8];
let frame_size = sample_rate as usize / 50;
let mut encoder =
opus_multistream_encoder_create(sample_rate, 2, 2, 0, &mapping, OPUS_APPLICATION_AUDIO)
.expect("multistream encoder");
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::SetApplication(OPUS_APPLICATION_VOIP),
)
.expect("set multistream application");
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut encoder, 0)
.expect("get first stream encoder");
let mut stream_application = 0;
opus_encoder_ctl(
stream_encoder,
OpusEncoderCtlRequest::GetApplication(&mut stream_application),
)
.expect("get stream application");
assert_eq!(stream_application, OPUS_APPLICATION_VOIP);
let mut application = 0;
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::GetApplication(&mut application),
)
.expect("get multistream application");
assert_eq!(application, stream_application);
let mut sample_rate_out = 0;
let mut stream_sample_rate = 0;
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::GetSampleRate(&mut sample_rate_out),
)
.expect("get multistream sample rate");
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut encoder, 0)
.expect("get first stream encoder");
opus_encoder_ctl(
stream_encoder,
OpusEncoderCtlRequest::GetSampleRate(&mut stream_sample_rate),
)
.expect("get stream sample rate");
assert_eq!(sample_rate_out, stream_sample_rate);
let mut lookahead = 0;
let mut stream_lookahead = 0;
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::GetLookahead(&mut lookahead),
)
.expect("get multistream lookahead");
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut encoder, 0)
.expect("get first stream encoder");
opus_encoder_ctl(
stream_encoder,
OpusEncoderCtlRequest::GetLookahead(&mut stream_lookahead),
)
.expect("get stream lookahead");
assert_eq!(lookahead, stream_lookahead);
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut encoder, 0)
.expect("get first stream encoder");
opus_encoder_ctl(stream_encoder, OpusEncoderCtlRequest::SetVoiceRatio(55))
.expect("set stream voice ratio");
let mut voice_ratio = 0;
let mut stream_voice_ratio = 0;
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::GetVoiceRatio(&mut voice_ratio),
)
.expect("get multistream voice ratio");
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut encoder, 0)
.expect("get first stream encoder");
opus_encoder_ctl(
stream_encoder,
OpusEncoderCtlRequest::GetVoiceRatio(&mut stream_voice_ratio),
)
.expect("get stream voice ratio");
assert_eq!(voice_ratio, stream_voice_ratio);
opus_multistream_encoder_ctl(&mut encoder, OpusMultistreamEncoderCtlRequest::SetDtx(true))
.expect("enable multistream dtx");
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::SetForceMode(MODE_SILK_ONLY),
)
.expect("force multistream silk");
let quiet_frame = vec![0i16; frame_size * 2];
let mut packet = vec![0u8; MAX_PACKET];
for _ in 0..12 {
opus_multistream_encode(&mut encoder, &quiet_frame, frame_size, &mut packet)
.expect("encode quiet multistream frame");
}
let mut in_dtx = false;
let mut stream_in_dtx = false;
opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::GetInDtx(&mut in_dtx),
)
.expect("get multistream in dtx");
let stream_encoder = opus_multistream_encoder_get_encoder_state(&mut encoder, 0)
.expect("get first stream encoder");
opus_encoder_ctl(
stream_encoder,
OpusEncoderCtlRequest::GetInDtx(&mut stream_in_dtx),
)
.expect("get stream in dtx");
assert_eq!(in_dtx, stream_in_dtx);
assert!(in_dtx);
let invalid = opus_multistream_encoder_ctl(
&mut encoder,
OpusMultistreamEncoderCtlRequest::SetApplication(OPUS_APPLICATION_AUDIO),
);
assert!(matches!(
invalid,
Err(OpusMultistreamEncoderError::BadArgument)
));
}
#[test]
fn opus_encode_run_test1() {
let mut rng = FastRand::new(seed_from_env());
run_test1(no_fuzz(), &mut rng).expect("run_test1 should succeed");
}
#[test]
fn opus_encode_fuzz_encoder_settings() {
if no_fuzz() {
return;
}
let mut rng = FastRand::new(seed_from_env().wrapping_add(1));
fuzz_encoder_settings(5, 40, &mut rng).expect("fuzz settings should succeed");
}