extern crate spandsp_sys;
use std::fmt;
use std::os::raw::c_int;
use std::ptr::NonNull;
use crate::error::{Result, SpanDspError};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum G726Encoding {
Linear,
ULaw,
ALaw,
}
impl G726Encoding {
fn as_raw(self) -> c_int {
match self {
G726Encoding::Linear => spandsp_sys::G726_ENCODING_LINEAR as c_int,
G726Encoding::ULaw => spandsp_sys::G726_ENCODING_ULAW as c_int,
G726Encoding::ALaw => spandsp_sys::G726_ENCODING_ALAW as c_int,
}
}
}
impl fmt::Display for G726Encoding {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
G726Encoding::Linear => f.write_str("linear"),
G726Encoding::ULaw => f.write_str("u-law"),
G726Encoding::ALaw => f.write_str("A-law"),
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum G726Packing {
#[default]
None,
Left,
Right,
}
impl G726Packing {
fn as_raw(self) -> c_int {
match self {
G726Packing::None => spandsp_sys::G726_PACKING_NONE as c_int,
G726Packing::Left => spandsp_sys::G726_PACKING_LEFT as c_int,
G726Packing::Right => spandsp_sys::G726_PACKING_RIGHT as c_int,
}
}
}
impl fmt::Display for G726Packing {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
G726Packing::None => f.write_str("none"),
G726Packing::Left => f.write_str("left"),
G726Packing::Right => f.write_str("right"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum G726Rate {
Rate16000,
Rate24000,
Rate32000,
Rate40000,
}
impl G726Rate {
fn as_raw(self) -> c_int {
match self {
G726Rate::Rate16000 => 16000,
G726Rate::Rate24000 => 24000,
G726Rate::Rate32000 => 32000,
G726Rate::Rate40000 => 40000,
}
}
pub fn bps(self) -> u32 {
self.as_raw() as u32
}
pub fn bits_per_sample(self) -> u8 {
match self {
G726Rate::Rate16000 => 2,
G726Rate::Rate24000 => 3,
G726Rate::Rate32000 => 4,
G726Rate::Rate40000 => 5,
}
}
}
impl fmt::Display for G726Rate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
G726Rate::Rate16000 => f.write_str("16 kbit/s"),
G726Rate::Rate24000 => f.write_str("24 kbit/s"),
G726Rate::Rate32000 => f.write_str("32 kbit/s"),
G726Rate::Rate40000 => f.write_str("40 kbit/s"),
}
}
}
impl TryFrom<u32> for G726Rate {
type Error = SpanDspError;
fn try_from(bps: u32) -> std::result::Result<Self, Self::Error> {
match bps {
16000 => Ok(G726Rate::Rate16000),
24000 => Ok(G726Rate::Rate24000),
32000 => Ok(G726Rate::Rate32000),
40000 => Ok(G726Rate::Rate40000),
_ => Err(SpanDspError::InvalidInput(format!(
"invalid G.726 rate: {bps} bps"
))),
}
}
}
pub struct G726State {
ptr: NonNull<spandsp_sys::g726_state_t>,
}
impl G726State {
pub fn new(rate: G726Rate, encoding: G726Encoding, packing: G726Packing) -> Result<Self> {
let ptr = unsafe {
spandsp_sys::g726_init(
std::ptr::null_mut(),
rate.as_raw(),
encoding.as_raw(),
packing.as_raw(),
)
};
let ptr = NonNull::new(ptr).ok_or(SpanDspError::InitFailed)?;
Ok(Self { ptr })
}
pub fn encode(&mut self, g726_data: &mut [u8], amp: &[i16]) -> usize {
let len = amp.len().min(c_int::MAX as usize) as c_int;
unsafe {
spandsp_sys::g726_encode(self.ptr.as_ptr(), g726_data.as_mut_ptr(), amp.as_ptr(), len)
as usize
}
}
pub fn decode(&mut self, amp: &mut [i16], g726_data: &[u8]) -> usize {
let g726_bytes = g726_data.len().min(c_int::MAX as usize) as c_int;
unsafe {
spandsp_sys::g726_decode(
self.ptr.as_ptr(),
amp.as_mut_ptr(),
g726_data.as_ptr(),
g726_bytes,
) as usize
}
}
pub fn as_ptr(&self) -> *mut spandsp_sys::g726_state_t {
self.ptr.as_ptr()
}
}
impl Drop for G726State {
fn drop(&mut self) {
unsafe {
spandsp_sys::g726_free(self.ptr.as_ptr());
}
}
}