use super::*;
use super::seriesbiquad::*;
use rayon::prelude::*;
#[cfg_attr(feature = "python-bindings", pyclass)]
#[derive(Clone, Debug)]
pub struct BiquadBank {
biqs: Vec<Box<dyn Filter>>,
gains: Vec<Flt>,
}
#[cfg(feature = "python-bindings")]
#[cfg_attr(feature = "python-bindings", pymethods)]
impl BiquadBank {
#[new]
pub fn new_py(coefs: PyReadonlyArrayDyn<Flt>) -> PyResult<Self> {
let mut filts = vec![];
for col in coefs.as_array().columns() {
match col.as_slice() {
Some(colslice) => {
let new_ser = SeriesBiquad::new(colslice)?;
filts.push(new_ser.clone_dyn());
}
None => {
return Err(PyValueError::new_err("Error generating column"));
}
}
}
Ok(BiquadBank::new(filts))
}
#[pyo3(name = "filter")]
pub fn filter_py<'py>(
&mut self,
py: Python<'py>,
input: PyArrayLike1<Flt>,
) -> PyResult<PyArr1Flt<'py>> {
Ok(self.filter(input.as_slice()?).into_pyarray(py))
}
#[pyo3(name = "reset")]
pub fn reset_py(&mut self) {
self.reset();
}
#[pyo3(name = "set_gains")]
pub fn set_gains_py(&mut self, gains: PyArrayLike1<Flt>) -> PyResult<()> {
if gains.len()? != self.len() {
return Err(PyValueError::new_err("Invalid number of provided gains"));
}
self.set_gains(gains.as_slice()?);
Ok(())
}
#[pyo3(name = "set_gains_dB")]
pub fn set_gains_dB_py(&mut self, gains_dB: PyArrayLike1<Flt>) -> PyResult<()> {
if gains_dB.len()? != self.len() {
return Err(PyValueError::new_err("Invalid number of provided gains"));
}
self.set_gains_dB(gains_dB.as_slice()?);
Ok(())
}
#[pyo3(name = "len")]
pub fn len_py(&self) -> usize {
self.len()
}
}
impl BiquadBank {
pub fn new(biqs: Vec<Box<dyn Filter>>) -> BiquadBank {
let gains = vec![1.0; biqs.len()];
BiquadBank { biqs, gains }
}
pub fn len(&self) -> usize {
self.biqs.len()
}
pub fn is_empty(&self) -> bool {
self.biqs.is_empty()
}
pub fn set_gains_dB(&mut self, gains_dB: &[Flt]) {
if gains_dB.len() != self.gains.len() {
panic!("Invalid gains size!");
}
self.gains
.iter_mut()
.zip(gains_dB)
.for_each(|(g, gdB)| *g = Flt::powf(10., gdB / 20.));
}
pub fn set_gains(&mut self, gains: &[Flt]) {
if gains.len() != self.gains.len() {
panic!("Invalid gains size!");
}
self.gains.clone_from(&gains.to_vec());
}
pub fn analysis(&mut self, input: &[Flt]) -> Vec<Vd> {
let filtered_out: Vec<Vd> = self
.biqs
.par_iter_mut()
.map(|biq| biq.filter(input))
.collect();
filtered_out
}
}
impl Filter for BiquadBank {
fn filter(&mut self, input: &[Flt]) -> Vd {
let filtered_out = self.analysis(input);
let mut out: Vd = vec![0.; input.len()];
for (f, g) in filtered_out.iter().zip(&self.gains) {
for (outi, fi) in out.iter_mut().zip(f) {
*outi += g * fi;
}
}
out
}
fn reset(&mut self) {
self.biqs.iter_mut().for_each(|b| b.reset());
}
fn clone_dyn(&self) -> Box<dyn Filter> {
Box::new(self.clone())
}
}