#![warn(missing_docs)]
extern crate audiopus_sys as ffi;
use std::convert::TryFrom;
use std::ffi::CStr;
use std::marker::PhantomData;
use std::os::raw::c_int;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
#[repr(i32)]
pub enum Application {
Voip = ffi::OPUS_APPLICATION_VOIP,
Audio = ffi::OPUS_APPLICATION_AUDIO,
LowDelay = ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY,
}
impl Application {
fn from_raw(raw: i32, what: &'static str) -> Result<Application> {
match raw {
ffi::OPUS_APPLICATION_VOIP => Ok(Application::Voip),
ffi::OPUS_APPLICATION_AUDIO => Ok(Application::Audio),
ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY => Ok(Application::LowDelay),
_ => Err(Error::bad_arg(what)),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Channels {
Mono = 1,
Stereo = 2,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
#[repr(i32)]
#[derive(Default)]
pub enum Bandwidth {
#[default]
Auto = ffi::OPUS_AUTO,
Narrowband = ffi::OPUS_BANDWIDTH_NARROWBAND,
Mediumband = ffi::OPUS_BANDWIDTH_MEDIUMBAND,
Wideband = ffi::OPUS_BANDWIDTH_WIDEBAND,
Superwideband = ffi::OPUS_BANDWIDTH_SUPERWIDEBAND,
Fullband = ffi::OPUS_BANDWIDTH_FULLBAND,
}
impl Bandwidth {
fn from_int(value: i32) -> Option<Bandwidth> {
Some(match value {
ffi::OPUS_AUTO => Bandwidth::Auto,
ffi::OPUS_BANDWIDTH_NARROWBAND => Bandwidth::Narrowband,
ffi::OPUS_BANDWIDTH_MEDIUMBAND => Bandwidth::Mediumband,
ffi::OPUS_BANDWIDTH_WIDEBAND => Bandwidth::Wideband,
ffi::OPUS_BANDWIDTH_SUPERWIDEBAND => Bandwidth::Superwideband,
ffi::OPUS_BANDWIDTH_FULLBAND => Bandwidth::Fullband,
_ => return None,
})
}
fn decode(value: i32, what: &'static str) -> Result<Bandwidth> {
match Bandwidth::from_int(value) {
Some(bandwidth) => Ok(bandwidth),
None => Err(Error::bad_arg(what)),
}
}
fn raw(self) -> i32 {
self as i32
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(i32)]
pub enum ErrorCode {
BadArg = ffi::OPUS_BAD_ARG,
BufferTooSmall = ffi::OPUS_BUFFER_TOO_SMALL,
InternalError = ffi::OPUS_INTERNAL_ERROR,
InvalidPacket = ffi::OPUS_INVALID_PACKET,
Unimplemented = ffi::OPUS_UNIMPLEMENTED,
InvalidState = ffi::OPUS_INVALID_STATE,
AllocFail = ffi::OPUS_ALLOC_FAIL,
Unknown = -8,
}
impl ErrorCode {
fn from_int(value: c_int) -> ErrorCode {
use ErrorCode::*;
match value {
ffi::OPUS_BAD_ARG => BadArg,
ffi::OPUS_BUFFER_TOO_SMALL => BufferTooSmall,
ffi::OPUS_INTERNAL_ERROR => InternalError,
ffi::OPUS_INVALID_PACKET => InvalidPacket,
ffi::OPUS_UNIMPLEMENTED => Unimplemented,
ffi::OPUS_INVALID_STATE => InvalidState,
ffi::OPUS_ALLOC_FAIL => AllocFail,
_ => Unknown,
}
}
pub fn description(self) -> &'static str {
unsafe { CStr::from_ptr(ffi::opus_strerror(self as c_int)) }.to_str().unwrap()
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Bitrate {
Bits(i32),
Max,
Auto,
}
impl Bitrate {
fn from_raw(raw: c_int) -> Result<Bitrate> {
Ok(match raw {
ffi::OPUS_AUTO => Bitrate::Auto,
ffi::OPUS_BITRATE_MAX => Bitrate::Max,
_ => Bitrate::Bits(raw),
})
}
fn raw(self) -> c_int {
match self {
Bitrate::Auto => ffi::OPUS_AUTO,
Bitrate::Max => ffi::OPUS_BITRATE_MAX,
Bitrate::Bits(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(i32)]
#[derive(Default)]
pub enum Signal {
#[default]
Auto = ffi::OPUS_AUTO,
Voice = ffi::OPUS_SIGNAL_VOICE,
Music = ffi::OPUS_SIGNAL_MUSIC,
}
impl Signal {
fn from_raw(raw: i32, what: &'static str) -> Result<Signal> {
match raw {
ffi::OPUS_AUTO => Ok(Signal::Auto),
ffi::OPUS_SIGNAL_VOICE => Ok(Signal::Voice),
ffi::OPUS_SIGNAL_MUSIC => Ok(Signal::Music),
_ => Err(Error::bad_arg(what)),
}
}
fn raw(self) -> i32 {
self as i32
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(i32)]
#[derive(Default)]
pub enum FrameSize {
#[default]
Arg = ffi::OPUS_FRAMESIZE_ARG,
Ms2_5 = ffi::OPUS_FRAMESIZE_2_5_MS,
Ms5 = ffi::OPUS_FRAMESIZE_5_MS,
Ms10 = ffi::OPUS_FRAMESIZE_10_MS,
Ms20 = ffi::OPUS_FRAMESIZE_20_MS,
Ms40 = ffi::OPUS_FRAMESIZE_40_MS,
Ms60 = ffi::OPUS_FRAMESIZE_60_MS,
Ms80 = ffi::OPUS_FRAMESIZE_80_MS,
Ms100 = ffi::OPUS_FRAMESIZE_100_MS,
Ms120 = ffi::OPUS_FRAMESIZE_120_MS,
}
impl FrameSize {
fn from_raw(raw: i32, what: &'static str) -> Result<FrameSize> {
match raw {
ffi::OPUS_FRAMESIZE_ARG => Ok(FrameSize::Arg),
ffi::OPUS_FRAMESIZE_2_5_MS => Ok(FrameSize::Ms2_5),
ffi::OPUS_FRAMESIZE_5_MS => Ok(FrameSize::Ms5),
ffi::OPUS_FRAMESIZE_10_MS => Ok(FrameSize::Ms10),
ffi::OPUS_FRAMESIZE_20_MS => Ok(FrameSize::Ms20),
ffi::OPUS_FRAMESIZE_40_MS => Ok(FrameSize::Ms40),
ffi::OPUS_FRAMESIZE_60_MS => Ok(FrameSize::Ms60),
ffi::OPUS_FRAMESIZE_80_MS => Ok(FrameSize::Ms80),
ffi::OPUS_FRAMESIZE_100_MS => Ok(FrameSize::Ms100),
ffi::OPUS_FRAMESIZE_120_MS => Ok(FrameSize::Ms120),
_ => Err(Error::bad_arg(what)),
}
}
fn raw(self) -> i32 {
self as i32
}
}
pub fn version() -> &'static str {
unsafe { CStr::from_ptr(ffi::opus_get_version_string()) }.to_str().unwrap()
}
macro_rules! ffi {
($f:ident $(, $rest:expr)*) => {
match unsafe { ffi::$f($($rest),*) } {
code if code < 0 => return Err(Error::from_code(stringify!($f), code)),
code => code,
}
}
}
macro_rules! ctl {
($f:ident, $this:ident, $ctl:path $(, $rest:expr)*) => {
match unsafe { ffi::$f($this.ptr, $ctl $(, $rest)*) } {
code if code < 0 => return Err(Error::from_code(
concat!(stringify!($f), "(", stringify!($ctl), ")"),
code,
)),
_ => (),
}
}
}
macro_rules! generic_ctls {
($t:ty, $fn:ident) => {
impl $t {
pub fn reset_state(&mut self) -> Result<()> {
ctl!($fn, self, ffi::OPUS_RESET_STATE);
Ok(())
}
pub fn get_final_range(&mut self) -> Result<u32> {
let mut value: u32 = 0;
ctl!($fn, self, ffi::OPUS_GET_FINAL_RANGE_REQUEST, &mut value);
Ok(value)
}
pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_BANDWIDTH_REQUEST, &mut value);
Bandwidth::decode(value, concat!(stringify!($fn), "(OPUS_GET_BANDWIDTH)"))
}
pub fn get_sample_rate(&mut self) -> Result<u32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_SAMPLE_RATE_REQUEST, &mut value);
Ok(value as u32)
}
pub fn set_phase_inversion_disabled(&mut self, disabled: bool) -> Result<()> {
let value: i32 = if disabled { 1 } else { 0 };
ctl!($fn, self, ffi::OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, value);
Ok(())
}
pub fn get_phase_inversion_disabled(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, &mut value);
Ok(value != 0)
}
pub fn get_in_dtx(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_IN_DTX_REQUEST, &mut value);
Ok(value != 0)
}
}
};
}
#[derive(Debug)]
pub struct Encoder {
ptr: *mut ffi::OpusEncoder,
channels: Channels,
}
impl Drop for Encoder {
fn drop(&mut self) {
unsafe { ffi::opus_encoder_destroy(self.ptr) }
}
}
unsafe impl Send for Encoder {}
impl Encoder {
pub fn new(sample_rate: u32, channels: Channels, mode: Application) -> Result<Encoder> {
let mut error = 0;
let ptr = unsafe {
ffi::opus_encoder_create(
sample_rate as i32,
channels as c_int,
mode as c_int,
&mut error,
)
};
if error != ffi::OPUS_OK || ptr.is_null() {
Err(Error::from_code("opus_encoder_create", error))
} else {
Ok(Encoder { ptr, channels })
}
}
pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
let len = ffi!(
opus_encode,
self.ptr,
input.as_ptr(),
len(input) / self.channels as c_int,
output.as_mut_ptr(),
len(output)
);
Ok(len as usize)
}
pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
let len = ffi!(
opus_encode_float,
self.ptr,
input.as_ptr(),
len(input) / self.channels as c_int,
output.as_mut_ptr(),
len(output)
);
Ok(len as usize)
}
pub fn encode_vec(&mut self, input: &[i16], max_size: usize) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![0; max_size];
let result = self.encode(input, output.as_mut_slice())?;
output.truncate(result);
Ok(output)
}
pub fn encode_vec_float(&mut self, input: &[f32], max_size: usize) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![0; max_size];
let result = self.encode_float(input, output.as_mut_slice())?;
output.truncate(result);
Ok(output)
}
}
macro_rules! encoder_ctls {
($t:ty, $fn:ident) => {
impl $t {
pub fn set_complexity(&mut self, value: i32) -> Result<()> {
ctl!($fn, self, ffi::OPUS_SET_COMPLEXITY_REQUEST, value);
Ok(())
}
pub fn get_complexity(&mut self) -> Result<i32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_COMPLEXITY_REQUEST, &mut value);
Ok(value)
}
pub fn set_bitrate(&mut self, value: Bitrate) -> Result<()> {
ctl!($fn, self, ffi::OPUS_SET_BITRATE_REQUEST, value.raw());
Ok(())
}
pub fn get_bitrate(&mut self) -> Result<Bitrate> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_BITRATE_REQUEST, &mut value);
Bitrate::from_raw(value)
}
pub fn set_vbr(&mut self, vbr: bool) -> Result<()> {
let value: i32 = if vbr { 1 } else { 0 };
ctl!($fn, self, ffi::OPUS_SET_VBR_REQUEST, value);
Ok(())
}
pub fn get_vbr(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_VBR_REQUEST, &mut value);
Ok(value != 0)
}
pub fn set_vbr_constraint(&mut self, vbr: bool) -> Result<()> {
let value: i32 = if vbr { 1 } else { 0 };
ctl!($fn, self, ffi::OPUS_SET_VBR_CONSTRAINT_REQUEST, value);
Ok(())
}
pub fn get_vbr_constraint(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_VBR_CONSTRAINT_REQUEST, &mut value);
Ok(value != 0)
}
pub fn set_force_channels(&mut self, value: Option<Channels>) -> Result<()> {
let value: i32 = match value {
None => ffi::OPUS_AUTO,
Some(Channels::Mono) => 1,
Some(Channels::Stereo) => 2,
};
ctl!($fn, self, ffi::OPUS_SET_FORCE_CHANNELS_REQUEST, value);
Ok(())
}
pub fn get_force_channels(&mut self) -> Result<Option<Channels>> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_FORCE_CHANNELS_REQUEST, &mut value);
match value {
ffi::OPUS_AUTO => Ok(None),
1 => Ok(Some(Channels::Mono)),
2 => Ok(Some(Channels::Stereo)),
_ => Err(Error::bad_arg(concat!(stringify!($fn), "(OPUS_GET_FORCE_CHANNELS)"))),
}
}
pub fn set_max_bandwidth(&mut self, bandwidth: Bandwidth) -> Result<()> {
let value: i32 = bandwidth.raw();
ctl!($fn, self, ffi::OPUS_SET_MAX_BANDWIDTH_REQUEST, value);
Ok(())
}
pub fn get_max_bandwidth(&mut self) -> Result<Bandwidth> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_MAX_BANDWIDTH_REQUEST, &mut value);
Bandwidth::decode(value, concat!(stringify!($fn), "(OPUS_GET_MAX_BANDWIDTH)"))
}
pub fn set_bandwidth(&mut self, bandwidth: Bandwidth) -> Result<()> {
let value: i32 = bandwidth.raw();
ctl!($fn, self, ffi::OPUS_SET_BANDWIDTH_REQUEST, value);
Ok(())
}
pub fn set_signal(&mut self, signal: Signal) -> Result<()> {
let value: i32 = signal.raw();
ctl!($fn, self, ffi::OPUS_SET_SIGNAL_REQUEST, value);
Ok(())
}
pub fn get_signal(&mut self) -> Result<Signal> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_SIGNAL_REQUEST, &mut value);
Signal::from_raw(value, concat!(stringify!($fn), "(OPUS_GET_SIGNAL)"))
}
pub fn set_application(&mut self, application: Application) -> Result<()> {
let value: i32 = application as i32;
ctl!($fn, self, ffi::OPUS_SET_APPLICATION_REQUEST, value);
Ok(())
}
pub fn get_application(&mut self) -> Result<Application> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_APPLICATION_REQUEST, &mut value);
Application::from_raw(value, concat!(stringify!($fn), "(OPUS_GET_APPLICATION)"))
}
pub fn get_lookahead(&mut self) -> Result<i32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_LOOKAHEAD_REQUEST, &mut value);
Ok(value)
}
pub fn set_inband_fec(&mut self, value: bool) -> Result<()> {
let value: i32 = if value { 1 } else { 0 };
ctl!($fn, self, ffi::OPUS_SET_INBAND_FEC_REQUEST, value);
Ok(())
}
pub fn get_inband_fec(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_INBAND_FEC_REQUEST, &mut value);
Ok(value != 0)
}
pub fn set_packet_loss_perc(&mut self, value: i32) -> Result<()> {
ctl!($fn, self, ffi::OPUS_SET_PACKET_LOSS_PERC_REQUEST, value);
Ok(())
}
pub fn get_packet_loss_perc(&mut self) -> Result<i32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_PACKET_LOSS_PERC_REQUEST, &mut value);
Ok(value)
}
pub fn set_dtx(&mut self, value: bool) -> Result<()> {
let value: i32 = if value { 1 } else { 0 };
ctl!($fn, self, ffi::OPUS_SET_DTX_REQUEST, value);
Ok(())
}
pub fn get_dtx(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_DTX_REQUEST, &mut value);
Ok(value != 0)
}
pub fn set_lsb_depth(&mut self, depth: i32) -> Result<()> {
ctl!($fn, self, ffi::OPUS_SET_LSB_DEPTH_REQUEST, depth);
Ok(())
}
pub fn get_lsb_depth(&mut self) -> Result<i32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_LSB_DEPTH_REQUEST, &mut value);
Ok(value)
}
pub fn set_expert_frame_duration(&mut self, framesize: FrameSize) -> Result<()> {
let value: i32 = framesize.raw();
ctl!($fn, self, ffi::OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, value);
Ok(())
}
pub fn get_expert_frame_duration(&mut self) -> Result<FrameSize> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, &mut value);
FrameSize::from_raw(
value,
concat!(stringify!($fn), "(OPUS_GET_EXPERT_FRAME_DURATION)"),
)
}
pub fn set_prediction_disabled(&mut self, disabled: bool) -> Result<()> {
let value: i32 = if disabled { 1 } else { 0 };
ctl!($fn, self, ffi::OPUS_SET_PREDICTION_DISABLED_REQUEST, value);
Ok(())
}
pub fn get_prediction_disabled(&mut self) -> Result<bool> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_PREDICTION_DISABLED_REQUEST, &mut value);
Ok(value != 0)
}
}
};
}
generic_ctls!(Encoder, opus_encoder_ctl);
encoder_ctls!(Encoder, opus_encoder_ctl);
#[derive(Debug)]
pub struct Decoder {
ptr: *mut ffi::OpusDecoder,
channels: Channels,
}
impl Drop for Decoder {
fn drop(&mut self) {
unsafe { ffi::opus_decoder_destroy(self.ptr) }
}
}
unsafe impl Send for Decoder {}
impl Decoder {
pub fn new(sample_rate: u32, channels: Channels) -> Result<Decoder> {
let mut error = 0;
let ptr =
unsafe { ffi::opus_decoder_create(sample_rate as i32, channels as c_int, &mut error) };
if error != ffi::OPUS_OK || ptr.is_null() {
Err(Error::from_code("opus_decoder_create", error))
} else {
Ok(Decoder { ptr, channels })
}
}
pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
let ptr = match input.len() {
0 => std::ptr::null(),
_ => input.as_ptr(),
};
let len = ffi!(
opus_decode,
self.ptr,
ptr,
len(input),
output.as_mut_ptr(),
len(output) / self.channels as c_int,
fec as c_int
);
Ok(len as usize)
}
pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
let ptr = match input.len() {
0 => std::ptr::null(),
_ => input.as_ptr(),
};
let len = ffi!(
opus_decode_float,
self.ptr,
ptr,
len(input),
output.as_mut_ptr(),
len(output) / self.channels as c_int,
fec as c_int
);
Ok(len as usize)
}
pub fn get_nb_samples(&self, packet: &[u8]) -> Result<usize> {
let len = ffi!(opus_decoder_get_nb_samples, self.ptr, packet.as_ptr(), packet.len() as i32);
Ok(len as usize)
}
}
macro_rules! decoder_ctls {
($t:ty, $fn:ident) => {
impl $t {
pub fn set_gain(&mut self, gain: i32) -> Result<()> {
ctl!($fn, self, ffi::OPUS_SET_GAIN_REQUEST, gain);
Ok(())
}
pub fn get_gain(&mut self) -> Result<i32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_GAIN_REQUEST, &mut value);
Ok(value)
}
pub fn get_last_packet_duration(&mut self) -> Result<u32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_LAST_PACKET_DURATION_REQUEST, &mut value);
Ok(value as u32)
}
pub fn get_pitch(&mut self) -> Result<i32> {
let mut value: i32 = 0;
ctl!($fn, self, ffi::OPUS_GET_PITCH_REQUEST, &mut value);
Ok(value)
}
}
};
}
generic_ctls!(Decoder, opus_decoder_ctl);
decoder_ctls!(Decoder, opus_decoder_ctl);
pub mod packet {
use super::ffi;
use super::*;
use std::{ptr, slice};
pub fn get_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
if packet.is_empty() {
return Err(Error::bad_arg("opus_packet_get_bandwidth"));
}
let bandwidth = ffi!(opus_packet_get_bandwidth, packet.as_ptr());
Bandwidth::decode(bandwidth, "opus_packet_get_bandwidth")
}
pub fn get_nb_channels(packet: &[u8]) -> Result<Channels> {
if packet.is_empty() {
return Err(Error::bad_arg("opus_packet_get_nb_channels"));
}
let channels = ffi!(opus_packet_get_nb_channels, packet.as_ptr());
match channels {
1 => Ok(Channels::Mono),
2 => Ok(Channels::Stereo),
_ => Err(Error::bad_arg("opus_packet_get_nb_channels")),
}
}
pub fn get_nb_frames(packet: &[u8]) -> Result<usize> {
let frames = ffi!(opus_packet_get_nb_frames, packet.as_ptr(), len(packet));
Ok(frames as usize)
}
pub fn get_nb_samples(packet: &[u8], sample_rate: u32) -> Result<usize> {
let frames =
ffi!(opus_packet_get_nb_samples, packet.as_ptr(), len(packet), sample_rate as c_int);
Ok(frames as usize)
}
pub fn get_samples_per_frame(packet: &[u8], sample_rate: u32) -> Result<usize> {
if packet.is_empty() {
return Err(Error::bad_arg("opus_packet_get_samples_per_frame"));
}
let samples =
ffi!(opus_packet_get_samples_per_frame, packet.as_ptr(), sample_rate as c_int);
Ok(samples as usize)
}
pub fn parse(packet: &[u8]) -> Result<Packet<'_>> {
let mut toc: u8 = 0;
let mut frames = [ptr::null(); 48];
let mut sizes = [0i16; 48];
let mut payload_offset: i32 = 0;
let num_frames = ffi!(
opus_packet_parse,
packet.as_ptr(),
len(packet),
&mut toc,
frames.as_mut_ptr(),
sizes.as_mut_ptr(),
&mut payload_offset
);
let mut frames_vec = Vec::with_capacity(num_frames as usize);
for i in 0..num_frames as usize {
frames_vec.push(unsafe { slice::from_raw_parts(frames[i], sizes[i] as usize) });
}
Ok(Packet {
toc,
frames: frames_vec,
payload_offset: payload_offset as usize,
})
}
#[derive(Debug)]
pub struct Packet<'a> {
pub toc: u8,
pub frames: Vec<&'a [u8]>,
pub payload_offset: usize,
}
pub fn pad(packet: &mut [u8], prev_len: usize) -> Result<usize> {
let result = ffi!(opus_packet_pad, packet.as_mut_ptr(), check_len(prev_len), len(packet));
Ok(result as usize)
}
pub fn unpad(packet: &mut [u8]) -> Result<usize> {
let result = ffi!(opus_packet_unpad, packet.as_mut_ptr(), len(packet));
Ok(result as usize)
}
pub fn multistream_pad(packet: &mut [u8], prev_len: usize, nb_streams: u8) -> Result<usize> {
let result = ffi!(
opus_multistream_packet_pad,
packet.as_mut_ptr(),
check_len(prev_len),
len(packet),
nb_streams as c_int
);
Ok(result as usize)
}
pub fn multistream_unpad(packet: &mut [u8], nb_streams: u8) -> Result<usize> {
let result = ffi!(
opus_multistream_packet_unpad,
packet.as_mut_ptr(),
len(packet),
nb_streams as c_int
);
Ok(result as usize)
}
}
#[derive(Debug)]
pub struct SoftClip {
channels: Channels,
memory: [f32; 2],
}
impl SoftClip {
pub fn new(channels: Channels) -> SoftClip {
SoftClip { channels, memory: [0.0; 2] }
}
pub fn apply(&mut self, signal: &mut [f32]) {
unsafe {
ffi::opus_pcm_soft_clip(
signal.as_mut_ptr(),
len(signal) / self.channels as c_int,
self.channels as c_int,
self.memory.as_mut_ptr(),
)
};
}
}
#[derive(Debug)]
pub struct Repacketizer {
ptr: *mut ffi::OpusRepacketizer,
}
impl Drop for Repacketizer {
fn drop(&mut self) {
unsafe { ffi::opus_repacketizer_destroy(self.ptr) }
}
}
unsafe impl Send for Repacketizer {}
impl Repacketizer {
pub fn new() -> Result<Repacketizer> {
let ptr = unsafe { ffi::opus_repacketizer_create() };
if ptr.is_null() {
Err(Error::from_code("opus_repacketizer_create", ffi::OPUS_ALLOC_FAIL))
} else {
Ok(Repacketizer { ptr })
}
}
pub fn combine(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<usize> {
let mut state = self.begin();
for &packet in input {
state.cat(packet)?;
}
state.out(output)
}
#[allow(clippy::needless_lifetimes)]
pub fn begin<'rp, 'buf>(&'rp mut self) -> RepacketizerState<'rp, 'buf> {
unsafe {
ffi::opus_repacketizer_init(self.ptr);
}
RepacketizerState { ptr: self.ptr, phantom: PhantomData }
}
}
#[derive(Debug)]
pub struct RepacketizerState<'rp, 'buf> {
ptr: *mut ffi::OpusRepacketizer,
phantom: PhantomData<(&'rp mut Repacketizer, &'buf [u8])>,
}
unsafe impl<'rp, 'buf> Send for RepacketizerState<'rp, 'buf> {}
impl<'rp, 'buf> RepacketizerState<'rp, 'buf> {
pub fn cat(&mut self, packet: &'buf [u8]) -> Result<()> {
ffi!(opus_repacketizer_cat, self.ptr, packet.as_ptr(), len(packet));
Ok(())
}
#[inline]
pub fn cat_move<'b2>(self, packet: &'b2 [u8]) -> Result<RepacketizerState<'rp, 'b2>>
where
'buf: 'b2,
{
let mut shorter = self;
shorter.cat(packet)?;
Ok(shorter)
}
pub fn get_nb_frames(&mut self) -> usize {
unsafe { ffi::opus_repacketizer_get_nb_frames(self.ptr) as usize }
}
pub fn out(&mut self, buffer: &mut [u8]) -> Result<usize> {
let result = ffi!(opus_repacketizer_out, self.ptr, buffer.as_mut_ptr(), len(buffer));
Ok(result as usize)
}
pub fn out_range(&mut self, begin: usize, end: usize, buffer: &mut [u8]) -> Result<usize> {
let result = ffi!(
opus_repacketizer_out_range,
self.ptr,
check_len(begin),
check_len(end),
buffer.as_mut_ptr(),
len(buffer)
);
Ok(result as usize)
}
}
#[derive(Debug)]
pub struct MSEncoder {
ptr: *mut ffi::OpusMSEncoder,
channels: c_int,
}
impl Drop for MSEncoder {
fn drop(&mut self) {
unsafe { ffi::opus_multistream_encoder_destroy(self.ptr) }
}
}
unsafe impl Send for MSEncoder {}
impl MSEncoder {
pub fn new(
sample_rate: u32,
streams: u8,
coupled_streams: u8,
mapping: &[u8],
application: Application,
) -> Result<MSEncoder> {
let mut error = 0;
let ptr = unsafe {
ffi::opus_multistream_encoder_create(
sample_rate as i32,
len(mapping),
streams as c_int,
coupled_streams as c_int,
mapping.as_ptr(),
application as c_int,
&mut error,
)
};
if error != ffi::OPUS_OK || ptr.is_null() {
Err(Error::from_code("opus_multistream_encoder_create", error))
} else {
Ok(MSEncoder { ptr, channels: len(mapping) })
}
}
pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
let len = ffi!(
opus_multistream_encode,
self.ptr,
input.as_ptr(),
len(input) / self.channels as c_int,
output.as_mut_ptr(),
len(output)
);
Ok(len as usize)
}
pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
let len = ffi!(
opus_multistream_encode_float,
self.ptr,
input.as_ptr(),
len(input) / self.channels as c_int,
output.as_mut_ptr(),
len(output)
);
Ok(len as usize)
}
pub fn encode_vec(&mut self, input: &[i16], max_size: usize) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![0; max_size];
let result = self.encode(input, output.as_mut_slice())?;
output.truncate(result);
Ok(output)
}
pub fn encode_vec_float(&mut self, input: &[f32], max_size: usize) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![0; max_size];
let result = self.encode_float(input, output.as_mut_slice())?;
output.truncate(result);
Ok(output)
}
}
generic_ctls!(MSEncoder, opus_multistream_encoder_ctl);
encoder_ctls!(MSEncoder, opus_multistream_encoder_ctl);
#[derive(Debug)]
pub struct MSDecoder {
ptr: *mut ffi::OpusMSDecoder,
channels: c_int,
}
impl Drop for MSDecoder {
fn drop(&mut self) {
unsafe { ffi::opus_multistream_decoder_destroy(self.ptr) }
}
}
unsafe impl Send for MSDecoder {}
impl MSDecoder {
pub fn new(
sample_rate: u32,
streams: u8,
coupled_streams: u8,
mapping: &[u8],
) -> Result<MSDecoder> {
let mut error = 0;
let ptr = unsafe {
ffi::opus_multistream_decoder_create(
sample_rate as i32,
len(mapping),
streams as c_int,
coupled_streams as c_int,
mapping.as_ptr(),
&mut error,
)
};
if error != ffi::OPUS_OK || ptr.is_null() {
Err(Error::from_code("opus_multistream_decoder_create", error))
} else {
Ok(MSDecoder { ptr, channels: len(mapping) })
}
}
pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
let ptr = match input.len() {
0 => std::ptr::null(),
_ => input.as_ptr(),
};
let len = ffi!(
opus_multistream_decode,
self.ptr,
ptr,
len(input),
output.as_mut_ptr(),
len(output) / self.channels as c_int,
fec as c_int
);
Ok(len as usize)
}
pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
let ptr = match input.len() {
0 => std::ptr::null(),
_ => input.as_ptr(),
};
let len = ffi!(
opus_multistream_decode_float,
self.ptr,
ptr,
len(input),
output.as_mut_ptr(),
len(output) / self.channels as c_int,
fec as c_int
);
Ok(len as usize)
}
}
generic_ctls!(MSDecoder, opus_multistream_decoder_ctl);
decoder_ctls!(MSDecoder, opus_multistream_decoder_ctl);
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct Error {
function: &'static str,
code: ErrorCode,
}
impl Error {
fn bad_arg(what: &'static str) -> Error {
Error { function: what, code: ErrorCode::BadArg }
}
fn from_code(what: &'static str, code: c_int) -> Error {
Error {
function: what,
code: ErrorCode::from_int(code),
}
}
#[inline]
pub fn function(&self) -> &'static str {
self.function
}
#[inline]
pub fn description(&self) -> &'static str {
self.code.description()
}
#[inline]
pub fn code(&self) -> ErrorCode {
self.code
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}: {}", self.function, self.description())
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
self.code.description()
}
}
fn check_len(val: usize) -> c_int {
match c_int::try_from(val) {
Ok(val2) => val2,
Err(_) => panic!("length out of range: {}", val),
}
}
#[inline]
fn len<T>(slice: &[T]) -> c_int {
check_len(slice.len())
}