use crate::fft::CepFft;
use crate::num_complex::{Complex, ComplexFloat};
use crate::CepFloat;
pub struct CepstrumExtractor<T: CepFloat> {
fft_instance: CepFft<T>,
}
impl<T: CepFloat> CepstrumExtractor<T> {
fn _ceps_with_instance_mut(
&self,
mut signal: &mut [Complex<T>],
f: fn(&Complex<T>) -> Complex<T>,
instance: usize,
) {
self.fft_instance.do_fft(&mut signal, instance);
signal.iter_mut().for_each(|fft_component| {
*fft_component = f(fft_component);
});
self.fft_instance.do_ifft(&mut signal, instance);
}
pub fn new(win_len: usize) -> CepstrumExtractor<T> {
Self {
fft_instance: CepFft::new(win_len),
}
}
pub fn set_len(&mut self, len: usize) {
self.fft_instance.set_len(len);
}
pub fn extend_instances(&self, new_count: usize) {
self.fft_instance.extend_scratches(new_count);
}
pub fn rceps_mut(&self, mut signal: &mut [Complex<T>]) {
self.rceps_with_instance_mut(&mut signal, 0);
}
pub fn rceps_to_vec(&self, signal: &[Complex<T>]) -> Vec<Complex<T>> {
let mut copied = signal.to_vec();
self.rceps_with_instance_mut(&mut copied, 0);
copied.truncate(copied.len() / 2);
copied
}
#[inline]
fn r_f(x: &Complex<T>) -> Complex<T> {
Complex::from(if x.re == T::zero() {
x.abs()
} else {
x.abs().ln()
})
}
pub fn rceps_with_instance_mut(&self, signal: &mut [Complex<T>], instance: usize) {
self._ceps_with_instance_mut(signal, Self::r_f, instance)
}
pub fn rceps_with_instance_to_vec(
&self,
signal: &[Complex<T>],
instance: usize,
) -> Vec<Complex<T>> {
let mut copied = signal.to_vec();
self.rceps_with_instance_mut(&mut copied, instance);
copied.truncate(copied.len() / 2);
copied
}
pub fn cceps_mut(&self, mut signal: &mut [Complex<T>]) {
self.rceps_with_instance_mut(&mut signal, 0);
}
pub fn cceps_to_vec(&self, signal: &[Complex<T>]) -> Vec<Complex<T>> {
let mut copied = signal.to_vec();
self.rceps_with_instance_mut(&mut copied, 0);
copied.truncate(copied.len() / 2);
copied
}
#[inline]
fn c_f(x: &Complex<T>) -> Complex<T> {
if x.re == T::zero() {
*x
} else {
x.ln()
}
}
pub fn cceps_with_instance_mut(&self, signal: &mut [Complex<T>], instance: usize) {
self._ceps_with_instance_mut(signal, Self::c_f, instance)
}
pub fn cceps_with_instance_to_vec(
&self,
signal: &[Complex<T>],
instance: usize,
) -> Vec<Complex<T>> {
let mut copied = signal.to_vec();
self.rceps_with_instance_mut(&mut copied, instance);
copied.truncate(copied.len() / 2);
copied
}
}