saturation 0.2.3

Real-time saturation and clipping designed for use with vst's
Documentation
use core::{marker::PhantomData, ops::Range};
use alloc::alloc::{Allocator, Global};

use real_time_fir_iir_filters::param::FilterFloat;

use crate::CacheTable;

use super::{calc::TriodeCalc, TriodeClassA, TriodeModel};

#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
struct TriodeCacheFunc<F, M>
where
    F: FilterFloat,
    M: TriodeModel
{
    param: TriodeClassA<F>,
    marker: PhantomData<M>
}
impl<F, M> FnOnce<(F,)> for TriodeCacheFunc<F, M>
where
    F: FilterFloat,
    M: TriodeModel
{
    type Output = [F; 2];

    extern "rust-call" fn call_once(mut self, (vg,): (F,)) -> Self::Output
    {
        TriodeCalc::<F, M>::vp_a(&mut self.param, vg)
    }
}
impl<F, M> FnMut<(F,)> for TriodeCacheFunc<F, M>
where
    F: FilterFloat,
    M: TriodeModel
{
    extern "rust-call" fn call_mut(&mut self, (vg,): (F,)) -> Self::Output
    {
        TriodeCalc::<F, M>::vp_a(&mut self.param, vg)
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TriodeCache<F, M, A = Global>
where
    F: FilterFloat,
    M: TriodeModel,
    A: Allocator + Clone
{
    cache: CacheTable<F, 2, TriodeCacheFunc<F, M>, A>
}
impl<F, M> TriodeCache<F, M>
where
    F: FilterFloat,
    M: TriodeModel
{
    pub fn new(param: TriodeClassA<F>, range: Range<F>, resolution: usize) -> Self
    {
        Self::new_in(param, range, resolution, Global)
    }
}
impl<F, M, A> TriodeCache<F, M, A>
where
    F: FilterFloat,
    M: TriodeModel,
    A: Allocator + Clone
{
    pub fn new_in(param: TriodeClassA<F>, range: Range<F>, resolution: usize, alloc: A) -> Self
    {
        Self {
            cache: CacheTable::new_in(
                TriodeCacheFunc {
                    param,
                    marker: PhantomData
                },
                range,
                resolution,
                alloc
            )
        }
    }
}
impl<F, M, A> TriodeCalc<F, M> for TriodeCache<F, M, A>
where
    F: FilterFloat,
    M: TriodeModel,
    A: Allocator + Clone
{
    fn param(&self) -> &TriodeClassA<F>
    {
        &self.cache.func().param
    }
    fn param_mut(&mut self) -> &mut TriodeClassA<F>
    {
        &mut self.cache.func_mut().param
    }
    fn vp_a(&mut self, vg: F) -> [F; 2]
    {
        self.cache.saturate(vg)
    }
}