extern crate spandsp_sys;
use std::fmt;
use std::os::raw::c_int;
use std::ptr::NonNull;
use crate::error::{Result, SpanDspError};
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct G722Options: i32 {
const SAMPLE_RATE_8000 = 0x0001;
const PACKED = 0x0002;
}
}
impl Default for G722Options {
fn default() -> Self {
Self::empty()
}
}
impl fmt::Display for G722Options {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
bitflags::parser::to_writer(self, f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum G722Rate {
Rate64000,
Rate56000,
Rate48000,
}
impl G722Rate {
fn as_raw(self) -> c_int {
match self {
G722Rate::Rate64000 => 64000,
G722Rate::Rate56000 => 56000,
G722Rate::Rate48000 => 48000,
}
}
pub fn bps(self) -> u32 {
self.as_raw() as u32
}
}
impl fmt::Display for G722Rate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
G722Rate::Rate64000 => f.write_str("64 kbit/s"),
G722Rate::Rate56000 => f.write_str("56 kbit/s"),
G722Rate::Rate48000 => f.write_str("48 kbit/s"),
}
}
}
impl TryFrom<u32> for G722Rate {
type Error = SpanDspError;
fn try_from(bps: u32) -> std::result::Result<Self, Self::Error> {
match bps {
64000 => Ok(G722Rate::Rate64000),
56000 => Ok(G722Rate::Rate56000),
48000 => Ok(G722Rate::Rate48000),
_ => Err(SpanDspError::InvalidInput(format!(
"invalid G.722 rate: {bps} bps"
))),
}
}
}
pub struct G722Encoder {
ptr: NonNull<spandsp_sys::g722_encode_state_t>,
}
impl G722Encoder {
pub fn new(rate: G722Rate, options: G722Options) -> Result<Self> {
let ptr = unsafe {
spandsp_sys::g722_encode_init(
std::ptr::null_mut(),
rate.as_raw(),
options.bits() as c_int,
)
};
let ptr = NonNull::new(ptr).ok_or(SpanDspError::InitFailed)?;
Ok(Self { ptr })
}
pub fn encode(&mut self, g722_data: &mut [u8], amp: &[i16]) -> usize {
let len = amp.len().min(c_int::MAX as usize) as c_int;
unsafe {
spandsp_sys::g722_encode(self.ptr.as_ptr(), g722_data.as_mut_ptr(), amp.as_ptr(), len)
as usize
}
}
pub fn as_ptr(&self) -> *mut spandsp_sys::g722_encode_state_t {
self.ptr.as_ptr()
}
}
impl Drop for G722Encoder {
fn drop(&mut self) {
unsafe {
spandsp_sys::g722_encode_free(self.ptr.as_ptr());
}
}
}
pub struct G722Decoder {
ptr: NonNull<spandsp_sys::g722_decode_state_t>,
}
impl G722Decoder {
pub fn new(rate: G722Rate, options: G722Options) -> Result<Self> {
let ptr = unsafe {
spandsp_sys::g722_decode_init(
std::ptr::null_mut(),
rate.as_raw(),
options.bits() as c_int,
)
};
let ptr = NonNull::new(ptr).ok_or(SpanDspError::InitFailed)?;
Ok(Self { ptr })
}
pub fn decode(&mut self, amp: &mut [i16], g722_data: &[u8]) -> usize {
let len = g722_data.len().min(c_int::MAX as usize) as c_int;
unsafe {
spandsp_sys::g722_decode(self.ptr.as_ptr(), amp.as_mut_ptr(), g722_data.as_ptr(), len)
as usize
}
}
pub fn as_ptr(&self) -> *mut spandsp_sys::g722_decode_state_t {
self.ptr.as_ptr()
}
}
impl Drop for G722Decoder {
fn drop(&mut self) {
unsafe {
spandsp_sys::g722_decode_free(self.ptr.as_ptr());
}
}
}