#![deny(rust_2018_idioms)]
pub mod coder;
pub mod error;
pub mod packet;
pub mod repacketizer;
pub mod softclip;
pub use crate::error::{Error, ErrorCode, Result};
pub use audiopus_sys as ffi;
pub trait TryFrom<T>: Sized {
type Error;
fn try_from(value: T) -> Result<Self>;
}
pub trait TryInto<T>: Sized {
type Error;
fn try_into(self) -> Result<T>;
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Signal {
Auto = ffi::OPUS_AUTO,
Voice = ffi::OPUS_SIGNAL_VOICE,
Music = ffi::OPUS_SIGNAL_MUSIC,
}
impl TryFrom<i32> for Signal {
type Error = Error;
fn try_from(value: i32) -> Result<Self> {
Ok(match value {
ffi::OPUS_AUTO => Signal::Auto,
ffi::OPUS_SIGNAL_VOICE => Signal::Voice,
ffi::OPUS_SIGNAL_MUSIC => Signal::Music,
_ => return Err(Error::InvalidSignal(value)),
})
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Bitrate {
BitsPerSecond(i32),
Max,
Auto,
}
impl From<Bitrate> for i32 {
fn from(bitrate: Bitrate) -> i32 {
match bitrate {
Bitrate::Auto => ffi::OPUS_AUTO,
Bitrate::Max => ffi::OPUS_BITRATE_MAX,
Bitrate::BitsPerSecond(bits) => bits,
}
}
}
impl TryFrom<i32> for Bitrate {
type Error = Error;
fn try_from(value: i32) -> Result<Bitrate> {
Ok(match value {
ffi::OPUS_AUTO => Bitrate::Auto,
ffi::OPUS_BITRATE_MAX => Bitrate::Max,
x if x.is_positive() => Bitrate::BitsPerSecond(x),
_ => return Err(Error::InvalidBandwidth(value)),
})
}
}
#[repr(i32)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum SampleRate {
Hz8000 = 8000,
Hz12000 = 12000,
Hz16000 = 16000,
Hz24000 = 24000,
Hz48000 = 48000,
}
impl TryFrom<i32> for SampleRate {
type Error = Error;
fn try_from(value: i32) -> Result<Self> {
Ok(match value {
8000 => SampleRate::Hz8000,
12000 => SampleRate::Hz12000,
16000 => SampleRate::Hz16000,
24000 => SampleRate::Hz24000,
48000 => SampleRate::Hz48000,
_ => return Err(Error::InvalidSampleRate(value)),
})
}
}
#[repr(i32)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Application {
Voip = ffi::OPUS_APPLICATION_VOIP,
Audio = ffi::OPUS_APPLICATION_AUDIO,
LowDelay = ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY,
}
impl TryFrom<i32> for Application {
type Error = Error;
fn try_from(value: i32) -> Result<Self> {
Ok(match value {
ffi::OPUS_APPLICATION_VOIP => Application::Voip,
ffi::OPUS_APPLICATION_AUDIO => Application::Audio,
ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY => Application::LowDelay,
_ => return Err(Error::InvalidApplication),
})
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Channels {
Auto = ffi::OPUS_AUTO,
Mono = 1,
Stereo = 2,
}
impl Channels {
pub fn is_mono(self) -> bool {
if let Channels::Mono = self {
return true;
}
false
}
pub fn is_stereo(self) -> bool {
if let Channels::Stereo = self {
return true;
}
false
}
}
impl TryFrom<i32> for Channels {
type Error = Error;
fn try_from(value: i32) -> Result<Channels> {
Ok(match value {
ffi::OPUS_AUTO => Channels::Auto,
1 => Channels::Mono,
2 => Channels::Stereo,
_ => return Err(Error::InvalidChannels(value)),
})
}
}
impl From<Channels> for i32 {
fn from(channels: Channels) -> i32 {
channels as i32
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Bandwidth {
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 TryFrom<i32> for Bandwidth {
type Error = Error;
fn try_from(value: i32) -> Result<Self> {
Ok(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 Err(Error::InvalidBandwidth(value)),
})
}
}
pub struct MutSignals<'a, T>(&'a mut [T]);
impl<'a, T> TryInto<MutSignals<'a, T>> for &'a mut [T] {
type Error = Error;
fn try_into(self) -> Result<MutSignals<'a, T>> {
if self.len() > std::i32::MAX as usize {
return Err(Error::SignalsTooLarge);
}
Ok(MutSignals(self))
}
}
impl<'a, T> TryInto<MutSignals<'a, T>> for &'a mut Vec<T> {
type Error = Error;
fn try_into(self) -> Result<MutSignals<'a, T>> {
if self.len() > std::i32::MAX as usize {
return Err(Error::SignalsTooLarge);
}
Ok(MutSignals(self))
}
}
impl<'a, T> TryInto<MutSignals<'a, T>> for &'a mut MutSignals<'a, T> {
type Error = Error;
fn try_into(self) -> Result<MutSignals<'a, T>> {
Ok(MutSignals(self.0))
}
}
impl<'a, T> MutSignals<'a, T> {
pub fn as_mut_ptr(&mut self) -> *mut T {
self.0.as_mut_ptr()
}
pub fn i32_len(&self) -> i32 {
self.0.len() as i32
}
}
#[cfg(test)]
mod tests {
use super::{ffi, Application, Error, Signal, TryFrom};
use matches::assert_matches;
#[test]
fn signal_try_from() {
assert_matches!(Signal::try_from(ffi::OPUS_SIGNAL_MUSIC), Ok(Signal::Music));
assert_matches!(Signal::try_from(ffi::OPUS_SIGNAL_VOICE), Ok(Signal::Voice));
assert_matches!(Signal::try_from(ffi::OPUS_AUTO), Ok(Signal::Auto));
assert_matches!(Signal::try_from(0), Err(Error::InvalidSignal(0)));
}
#[test]
fn application_try_from() {
assert_matches!(
Application::try_from(ffi::OPUS_APPLICATION_AUDIO),
Ok(Application::Audio)
);
assert_matches!(
Application::try_from(ffi::OPUS_APPLICATION_VOIP),
Ok(Application::Voip)
);
assert_matches!(
Application::try_from(ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY),
Ok(Application::LowDelay)
);
assert_matches!(Application::try_from(11), Err(Error::InvalidApplication));
}
}