use crate::{
check_init, ffi,
vec::{FVec, FVecMut},
AsNativeStr, Error, Result, Smpl, SpecMethod, Status,
};
use std::{
fmt::{Display, Formatter, Result as FmtResult},
str::FromStr,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OnsetMode {
Energy,
Hfc,
Complex,
Phase,
WPhase,
SpecDiff,
Kl,
Mkl,
SpecFlux,
}
impl SpecMethod for OnsetMode {}
impl AsNativeStr for OnsetMode {
fn as_native_str(&self) -> &'static str {
use self::OnsetMode::*;
match self {
Energy => "energy\0",
Hfc => "hfc\0",
Complex => "complex\0",
Phase => "phase\0",
WPhase => "wphase\0",
Mkl => "mkl\0",
Kl => "kl\0",
SpecFlux => "specflux\0",
SpecDiff => "specdiff\0",
}
}
}
impl Default for OnsetMode {
fn default() -> Self {
OnsetMode::Hfc
}
}
impl AsRef<str> for OnsetMode {
fn as_ref(&self) -> &str {
self.as_rust_str()
}
}
impl Display for OnsetMode {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
self.as_ref().fmt(f)
}
}
impl FromStr for OnsetMode {
type Err = Error;
fn from_str(src: &str) -> Result<Self> {
use self::OnsetMode::*;
Ok(match src {
"energy" => Energy,
"hfc" => Hfc,
"complex" => Complex,
"phase" => Phase,
"wphase" => WPhase,
"mkl" => Mkl,
"kl" => Kl,
"specflux" => SpecFlux,
"specdiff" => SpecDiff,
_ => return Err(Error::InvalidArg),
})
}
}
pub struct Onset {
onset: *mut ffi::aubio_onset_t,
}
impl Drop for Onset {
fn drop(&mut self) {
unsafe { ffi::del_aubio_onset(self.onset) }
}
}
impl Onset {
pub fn new(
method: OnsetMode,
buf_size: usize,
hop_size: usize,
sample_rate: u32,
) -> Result<Self> {
let onset = unsafe {
ffi::new_aubio_onset(
method.as_native_cstr(),
buf_size as ffi::uint_t,
hop_size as ffi::uint_t,
sample_rate as ffi::uint_t,
)
};
check_init(onset)?;
Ok(Self { onset })
}
pub fn with_awhitening(mut self, enable: bool) -> Self {
self.set_awhitening(enable);
self
}
pub fn with_compression(mut self, lambda: Smpl) -> Self {
self.set_compression(lambda);
self
}
pub fn with_silence(mut self, silence: Smpl) -> Self {
self.set_silence(silence);
self
}
pub fn with_threshold(mut self, threshold: Smpl) -> Self {
self.set_threshold(threshold);
self
}
pub fn with_minioi(mut self, minioi: usize) -> Self {
self.set_minioi(minioi);
self
}
pub fn with_minioi_s(mut self, minioi: Smpl) -> Self {
self.set_minioi_s(minioi);
self
}
pub fn with_minioi_ms(mut self, minioi: Smpl) -> Self {
self.set_minioi_ms(minioi);
self
}
pub fn with_delay(mut self, delay: usize) -> Self {
self.set_delay(delay);
self
}
pub fn with_delay_s(mut self, delay: Smpl) -> Self {
self.set_delay_s(delay);
self
}
pub fn with_delay_ms(mut self, delay: Smpl) -> Self {
self.set_delay_ms(delay);
self
}
pub fn do_<'i, 'o, I, O>(&mut self, input: I, onset: O) -> Status
where
I: Into<FVec<'i>>,
O: Into<FVecMut<'o>>,
{
let input = input.into();
let mut onset = onset.into();
input.check_size(self.get_hop())?;
onset.check_size(1)?;
unsafe { ffi::aubio_onset_do(self.onset, input.as_ptr(), onset.as_mut_ptr()) }
Ok(())
}
pub fn do_result<'i, I>(&mut self, input: I) -> Result<Smpl>
where
I: Into<FVec<'i>>,
{
let mut onset = [0.; 1];
self.do_(input, &mut onset)?;
Ok(onset[0])
}
pub fn get_hop(&self) -> usize {
(unsafe { ffi::aubio_pvoc_get_hop(self.onset.cast::<ffi::aubio_pvoc_t>()) }) as usize
}
pub fn get_last(&self) -> usize {
(unsafe { ffi::aubio_onset_get_last(self.onset) }) as usize
}
pub fn get_last_s(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_last_s(self.onset) }
}
pub fn get_last_ms(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_last_ms(self.onset) }
}
pub fn set_awhitening(&mut self, enable: bool) {
unsafe {
ffi::aubio_onset_set_awhitening(self.onset, if enable { 1 } else { 0 });
}
}
pub fn get_awhitening(&self) -> bool {
0.0 < (unsafe { ffi::aubio_onset_get_awhitening(self.onset) })
}
pub fn set_compression(&mut self, lambda: Smpl) {
unsafe {
ffi::aubio_onset_set_compression(self.onset, lambda);
}
}
pub fn get_compression(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_compression(self.onset) }
}
pub fn set_silence(&mut self, silence: Smpl) {
unsafe {
ffi::aubio_onset_set_silence(self.onset, silence);
}
}
pub fn get_silence(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_silence(self.onset) }
}
pub fn get_descriptor(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_descriptor(self.onset) }
}
pub fn get_thresholded_descriptor(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_thresholded_descriptor(self.onset) }
}
pub fn set_threshold(&mut self, threshold: Smpl) {
unsafe {
ffi::aubio_onset_set_threshold(self.onset, threshold);
}
}
pub fn get_threshold(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_threshold(self.onset) }
}
pub fn set_minioi(&mut self, minioi: usize) {
unsafe {
ffi::aubio_onset_set_minioi(self.onset, minioi as ffi::uint_t);
}
}
pub fn get_minioi(&self) -> usize {
(unsafe { ffi::aubio_onset_get_minioi(self.onset) }) as usize
}
pub fn set_minioi_s(&mut self, minioi: Smpl) {
unsafe {
ffi::aubio_onset_set_minioi_s(self.onset, minioi);
}
}
pub fn get_minioi_s(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_minioi_s(self.onset) }
}
pub fn set_minioi_ms(&mut self, minioi: Smpl) {
unsafe {
ffi::aubio_onset_set_minioi_ms(self.onset, minioi);
}
}
pub fn get_minioi_ms(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_minioi_ms(self.onset) }
}
pub fn set_delay(&mut self, delay: usize) {
unsafe {
ffi::aubio_onset_set_delay(self.onset, delay as ffi::uint_t);
}
}
pub fn get_delay(&self) -> usize {
(unsafe { ffi::aubio_onset_get_delay(self.onset) }) as usize
}
pub fn set_delay_s(&mut self, delay: Smpl) {
unsafe {
ffi::aubio_onset_set_delay_s(self.onset, delay);
}
}
pub fn get_delay_s(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_delay_s(self.onset) }
}
pub fn set_delay_ms(&mut self, delay: Smpl) {
unsafe {
ffi::aubio_onset_set_delay_ms(self.onset, delay);
}
}
pub fn get_delay_ms(&self) -> Smpl {
unsafe { ffi::aubio_onset_get_delay_ms(self.onset) }
}
pub fn set_default_parameters(&mut self, mode: OnsetMode) {
unsafe {
ffi::aubio_onset_set_default_parameters(self.onset, mode.as_native_cstr());
}
}
pub fn reset(&mut self) {
unsafe {
ffi::aubio_onset_reset(self.onset);
}
}
}
#[cfg(test)]
mod test {
use crate::*;
#[test]
fn test() {
}
#[test]
fn test_wrong_params() {
const WIN_S: usize = 1024;
const HOP_S: usize = WIN_S / 2;
const SAMPLERATE: u32 = 44100;
assert!(Onset::new(Default::default(), 5, 0, SAMPLERATE).is_err());
assert!(Onset::new(Default::default(), 1, 1, SAMPLERATE).is_err());
assert!(Onset::new(Default::default(), HOP_S, WIN_S, SAMPLERATE).is_err());
assert!(Onset::new(Default::default(), 1024, 512, 0).is_err());
assert_eq!(
Onset::new(Default::default(), 5, 2, SAMPLERATE).is_ok(),
cfg!(any(
feature = "fftw3",
all(feature = "pkg-config", not(feature = "builtin"))
))
);
}
}