use crate::config::*;
use serde::{Deserialize, Serialize};
use snafu::prelude::*;
use strum::{EnumMessage, IntoEnumIterator};
type Result<T> = std::result::Result<T, OverlapError>;
#[derive(Snafu, Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum OverlapError {
#[snafu(display(
"Overlap value results in hop size of zero for given \
FFT length. Please use a larger FFT length, or a smaller overlap",
))]
ValueTooClose {},
}
#[cfg(feature = "python-bindings")]
impl From<OverlapError> for PyErr {
fn from(value: OverlapError) -> Self {
PyValueError::new_err(format!("{}", value))
}
}
#[cfg_attr(
feature = "python-bindings",
gen_stub_pyclass_complex_enum,
pyclass(frozen, from_py_object)
)]
#[derive(
Clone,
Copy,
Debug,
Deserialize,
PartialEq,
Serialize,
Hash,
strum_macros::EnumMessage,
strum_macros::EnumIter,
)]
#[non_exhaustive]
pub enum Overlap {
#[strum(message = "No overlap")]
NoOverlap {},
#[strum(message = "10% overlap")]
TenPercent {},
#[strum(message = "25% overlap")]
TwentyFivePercent {},
#[strum(message = "50% overlap")]
FiftyPercent {},
#[strum(message = "75% overlap")]
SeventyFivePercent {},
#[strum(message = "90% overlap")]
NinetyPercent {},
#[strum(message = "95% overlap")]
NinetyFivePercent {},
}
impl Default for Overlap {
fn default() -> Self {
Overlap::FiftyPercent {}
}
}
impl Overlap {
pub fn get_overlap_samples(&self, nfft: usize) -> i64 {
let nfft = nfft as i64;
match self {
Overlap::NoOverlap {} => 0,
Overlap::TenPercent {} => nfft / 10,
Overlap::TwentyFivePercent {} => nfft / 4,
Overlap::FiftyPercent {} => nfft / 2,
Overlap::SeventyFivePercent {} => (nfft * 3) / 4,
Overlap::NinetyPercent {} => (nfft * 9) / 10,
Overlap::NinetyFivePercent {} => (nfft * 95) / 100,
}
}
pub fn get_hop_size(&self, nfft: usize) -> i64 {
nfft as i64 - self.get_overlap_samples(nfft)
}
pub fn validate(&self, nfft: usize) -> Result<()> {
let hop_size_unchecked = self.get_hop_size(nfft);
ensure!(hop_size_unchecked > 0, ValueTooCloseSnafu {});
ensure!(hop_size_unchecked <= nfft as i64, ValueTooCloseSnafu {});
Ok(())
}
}
#[cfg(feature = "python-bindings")]
#[cfg_attr(feature = "python-bindings", gen_stub_pymethods, pymethods)]
impl Overlap {
#[inline]
fn __eq__(&self, other: &Self) -> bool {
self == other
}
fn __str__(&self) -> String {
self.get_message().unwrap().into()
}
#[staticmethod]
#[pyo3(name = "default")]
fn default_py() -> Self {
Self::default()
}
#[staticmethod]
fn all() -> Vec<Overlap> {
Self::iter().collect()
}
}