use crate::prelude::*;
pub trait Coefficients {
fn eval<A: Audio, B: Ring>(&self, inputs: &B) -> A
where
B::Buf: buf::Buffer<Item = A>;
}
#[derive(Clone, Default, Debug)]
pub struct Dense<T: AsRef<[f64]>>(pub T);
impl<T: AsRef<[f64]>> Dense<T> {
pub const fn new(inner: T) -> Self {
Self(inner)
}
pub fn get(&self, degree: usize) -> f64 {
self.0.as_ref().get(degree).copied().unwrap_or_default()
}
}
impl<T: AsRef<[f64]>> Coefficients for Dense<T> {
fn eval<A: Audio, B: Ring>(&self, samples: &B) -> A
where
B::Buf: buf::Buffer<Item = A>,
{
self.0
.as_ref()
.iter()
.enumerate()
.map(|(k, &c)| samples.get(k) * c)
.sum()
}
}
pub type DenseStc<const N: usize> = Dense<[f64; N]>;
pub type DenseDyn = Dense<Vec<f64>>;
pub type Zero = DenseStc<0>;
impl<const N: usize> DenseStc<N> {
#[must_use]
pub const fn zero() -> Self {
Self([0.0; N])
}
}
#[derive(Clone, Default, Debug)]
pub struct Sparse<T: AsRef<[(usize, f64)]>>(pub T);
impl<T: AsRef<[(usize, f64)]>> Sparse<T> {
pub const fn new(inner: T) -> Self {
Self(inner)
}
pub fn get(&self, degree: usize) -> f64 {
match self.0.as_ref().iter().find(|&&(k, _)| k == degree) {
Some(&(_, c)) => c,
None => 0.0,
}
}
pub fn get_ordered(&self, degree: usize) -> f64 {
let array = self.0.as_ref();
match array.binary_search_by_key(°ree, |&(k, _)| k) {
Ok(idx) => array[idx].1,
Err(_) => 0.0,
}
}
}
impl<T: AsRef<[(usize, f64)]>> Coefficients for Sparse<T> {
fn eval<A: Audio, B: Ring>(&self, samples: &B) -> A
where
B::Buf: buf::Buffer<Item = A>,
{
self.0
.as_ref()
.iter()
.map(|&(k, c)| samples.get(k) * c)
.sum()
}
}
pub type SparseStc<const N: usize> = Sparse<[f64; N]>;
pub type SparseDyn = Sparse<Vec<f64>>;
#[derive(Clone, Copy, Debug, Default)]
pub struct DiffEq<T: Coefficients, U: Coefficients> {
pub input: T,
pub feedback: U,
}
impl<T: Coefficients, U: Coefficients> DiffEq<T, U> {
#[must_use]
pub const fn new_raw(input: T, feedback: U) -> Self {
Self { input, feedback }
}
}
impl<T: Coefficients> DiffEq<T, Zero> {
#[must_use]
pub const fn new_fir(input: T) -> Self {
Self::new_raw(input, Zero::zero())
}
}
impl<T: Coefficients, U: Coefficients> FilterMap for DiffEq<T, U> {
fn eval<A: Audio, I: Ring, O: Ring>(&self, inputs: &I, outputs: &O) -> A
where
I::Buf: buf::BufferMut<Item = A>,
O::Buf: buf::BufferMut<Item = A>,
{
self.input.eval(inputs) - self.feedback.eval(outputs)
}
}