use std::convert::TryFrom;
use libfvad_sys as ffi;
#[derive(PartialEq, Debug)]
pub enum Mode {
Quality = 0,
LowBitrate = 1,
Aggressive = 2,
VeryAggressive = 3,
}
#[derive(PartialEq, Debug)]
pub enum SampleRate {
Rate8kHz = 8000,
Rate16kHz = 16000,
Rate32kHz = 32000,
Rate48kHz = 48000,
}
impl TryFrom<u64> for SampleRate {
type Error = ();
fn try_from(n: u64) -> Result<Self, Self::Error> {
match n {
8000 => Ok(SampleRate::Rate8kHz),
16000 => Ok(SampleRate::Rate16kHz),
32000 => Ok(SampleRate::Rate32kHz),
48000 => Ok(SampleRate::Rate48kHz),
_ => Err(()),
}
}
}
impl TryFrom<u32> for SampleRate {
type Error = ();
fn try_from(n: u32) -> Result<Self, Self::Error> {
SampleRate::try_from(n as u64)
}
}
impl TryFrom<u16> for SampleRate {
type Error = ();
fn try_from(n: u16) -> Result<Self, Self::Error> {
SampleRate::try_from(n as u64)
}
}
impl TryFrom<i64> for SampleRate {
type Error = ();
fn try_from(n: i64) -> Result<Self, Self::Error> {
match n {
8000 => Ok(SampleRate::Rate8kHz),
16000 => Ok(SampleRate::Rate16kHz),
32000 => Ok(SampleRate::Rate32kHz),
48000 => Ok(SampleRate::Rate48kHz),
_ => Err(()),
}
}
}
impl TryFrom<i32> for SampleRate {
type Error = ();
fn try_from(n: i32) -> Result<Self, Self::Error> {
SampleRate::try_from(n as i64)
}
}
impl TryFrom<i16> for SampleRate {
type Error = ();
fn try_from(n: i16) -> Result<Self, Self::Error> {
SampleRate::try_from(n as i64)
}
}
pub struct Fvad {
fvad: *mut ffi::Fvad,
}
impl Fvad {
pub fn new() -> Option<Self> {
let fvad = unsafe { ffi::fvad_new() };
match fvad.is_null() {
false => Some(fvad.into()),
true => None,
}
}
pub fn reset(self) {
unsafe { ffi::fvad_reset(self.fvad) }
}
pub fn set_mode(self, mode: Mode) -> Self {
let v = mode as i32;
match unsafe { ffi::fvad_set_mode(self.fvad, v) } {
0 => self,
-1 => panic!("fvad_set_mode() did not accept {} as a valid mode", v),
n => panic!("fvad_set_mode() returned {}", n),
}
}
pub fn set_sample_rate(self, sample_rate: SampleRate) -> Self {
let v = sample_rate as i32;
match unsafe { ffi::fvad_set_sample_rate(self.fvad, v) } {
0 => self,
-1 => panic!(
"fvad_set_sample_rate() did not accept {} as a valid sample_rate",
v
),
n => panic!("fvad_set_sample_rate() returned {}", n),
}
}
pub fn is_voice_frame(&mut self, frame: &[i16]) -> Option<bool> {
match unsafe { ffi::fvad_process(self.fvad, frame.as_ptr(), frame.len() as u64) } {
-1 => None,
0 => Some(false),
1 => Some(true),
n => panic!("fvad_process() returned {}", n),
}
}
}
impl From<*mut ffi::Fvad> for Fvad {
fn from(fvad: *mut ffi::Fvad) -> Self {
Fvad { fvad }
}
}
impl Drop for Fvad {
fn drop(&mut self) {
unsafe { ffi::fvad_free(self.fvad) }
}
}
unsafe impl Send for Fvad {}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn try_into_sample_rate() {
assert_eq!(SampleRate::try_from(7999i16), Err(()));
assert_eq!(SampleRate::try_from(7999i32), Err(()));
assert_eq!(SampleRate::try_from(7999i64), Err(()));
assert_eq!(SampleRate::try_from(7999u16), Err(()));
assert_eq!(SampleRate::try_from(7999u32), Err(()));
assert_eq!(SampleRate::try_from(7999u64), Err(()));
assert_eq!(SampleRate::try_from(8000i16), Ok(SampleRate::Rate8kHz));
assert_eq!(SampleRate::try_from(8000i32), Ok(SampleRate::Rate8kHz));
assert_eq!(SampleRate::try_from(8000i64), Ok(SampleRate::Rate8kHz));
assert_eq!(SampleRate::try_from(8000u16), Ok(SampleRate::Rate8kHz));
assert_eq!(SampleRate::try_from(8000u32), Ok(SampleRate::Rate8kHz));
assert_eq!(SampleRate::try_from(8000u64), Ok(SampleRate::Rate8kHz));
assert_eq!(SampleRate::try_from(16000), Ok(SampleRate::Rate16kHz));
assert_eq!(SampleRate::try_from(32000), Ok(SampleRate::Rate32kHz));
assert_eq!(SampleRate::try_from(48000), Ok(SampleRate::Rate48kHz));
}
#[test]
fn set_mode() {
Fvad::new()
.unwrap()
.set_mode(Mode::Quality)
.set_mode(Mode::LowBitrate)
.set_mode(Mode::Aggressive)
.set_mode(Mode::VeryAggressive);
}
#[test]
fn set_sample_rate() {
Fvad::new()
.unwrap()
.set_sample_rate(SampleRate::Rate8kHz)
.set_sample_rate(SampleRate::Rate16kHz)
.set_sample_rate(SampleRate::Rate32kHz)
.set_sample_rate(SampleRate::Rate48kHz);
}
#[test]
fn is_voice_frame() {
assert_eq!(
Fvad::new()
.unwrap()
.is_voice_frame(&std::iter::repeat(0).take(160).collect::<Vec<i16>>()),
Some(false)
);
}
}