oscillation 0.1.1

Oscillators and a collection of waveforms for real-time usage.
Documentation
use core::ops::{Deref, DerefMut};

use num_traits::{Euclid, Float, FloatConst};

use crate::{waveform::Waveform, WavetableView};

moddef::moddef!(
    flat(pub) mod {
        direct_dtc,
        direct,
        wave_dtc,
        wave,
    }
);

pub trait OscillatorState<F>: Sized + From<Self::Waveform> + From<Direct<Self::Waveform>> + From<Self::WithoutDTC> + From<Self::WithoutWavetable>
where
    F: Float + FloatConst
{
    type Waveform: Waveform<F>;

    type WithDTC: OscillatorState<F, Waveform = Self::Waveform, WithDTC = Self::WithDTC> + From<Self> + From<Self::WithoutDTC> + From<DirectDTC<F, Self::Waveform>>;
    type WithoutDTC: OscillatorState<F, Waveform = Self::Waveform, WithoutDTC = Self::WithoutDTC>;

    type WithWavetable<const N: usize>: OscillatorState<F, Waveform = Self::Waveform, WithWavetable<N> = Self::WithWavetable<N>> + From<Self::WithoutWavetable> + From<Wave<F, Self::Waveform, N>>;
    type WithoutWavetable: OscillatorState<F, Waveform = Self::Waveform, WithoutWavetable = Self::WithoutWavetable>;

    type WithWaveform<W>: OscillatorState<F, Waveform = W, WithWaveform<W> = Self::WithWaveform<W>>
    where
        W: Waveform<F>;

    fn delete_cache(&mut self)
    {

    }
    
    fn next(&mut self, theta: F, omega: F, rate: F) -> F;

    fn duty_cycle(&self) -> F
    {
        crate::duty_cycle_default()
    }

    fn wavetable(&self) -> Option<WavetableView<'_, F>>
    {
        None
    }

    fn waveform(&self) -> &Self::Waveform;
    fn waveform_mut(&mut self) -> &mut Self::Waveform;

    fn with_dtc(self, duty_cycle: F) -> Self::WithDTC;
    fn without_dtc(self) -> Self::WithoutDTC;

    fn with_wavetable<const N: usize>(self) -> Self::WithWavetable<N>;
    fn without_wavetable(self) -> Self::WithoutWavetable;

    fn with_waveform<W>(self, waveform: W) -> Self::WithWaveform<W>
    where
        W: Waveform<F>
    {
        self.map_waveform(|_| waveform)
    }
    fn map_waveform<W>(self, waveform: impl FnOnce(Self::Waveform) -> W) -> Self::WithWaveform<W>
    where
        W: Waveform<F>;
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
pub struct Oscillator<F, S>
where
    F: Float + FloatConst,
    S: OscillatorState<F>
{
    pub omega: F,
    pub phi: F,
    theta: F,
    state: S
}

impl<F, S> Oscillator<F, S>
where
    F: Float + FloatConst,
    S: OscillatorState<F>
{
    pub fn new(omega: F, phi: F, mut state: S) -> Self
    {
        state.delete_cache();
        Self::new_trusted(omega, phi, state)
    }

    fn new_trusted(omega: F, phi: F, state: S) -> Self
    {
        Self {
            omega,
            phi,
            theta: F::zero(),
            state
        }
    }

    pub fn next(&mut self, rate: F) -> F
    where
        F: Euclid
    {
        let tau = F::TAU();

        self.theta = (self.theta + self.omega/rate).rem_euclid(&tau);
        self.state.next(self.theta + self.phi, self.omega, rate)
    }

    pub fn map_state<SS>(self, map: impl FnOnce(S) -> SS) -> Oscillator<F, SS>
    where
        SS: OscillatorState<F>
    {
        self.map_state_trusted(|mut state| {
            state.delete_cache();
            map(state)
        })
    }
    fn map_state_trusted<SS>(self, map: impl FnOnce(S) -> SS) -> Oscillator<F, SS>
    where
        SS: OscillatorState<F>
    {
        let Self { omega, phi, theta, state } = self;
        Oscillator {
            omega,
            phi,
            theta,
            state: map(state)
        }
    }

    pub fn with_dtc(self, duty_cycle: F) -> Oscillator<F, S::WithDTC>
    {
        self.map_state_trusted(|state| state.with_dtc(duty_cycle))
    }
    pub fn without_dtc(self) -> Oscillator<F, S::WithoutDTC>
    {
        self.map_state_trusted(|state| state.without_dtc())
    }

    pub fn with_wavetable<const N: usize>(self) -> Oscillator<F, S::WithWavetable<N>>
    {
        self.map_state_trusted(|state| state.with_wavetable())
    }
    pub fn without_wavetable(self) -> Oscillator<F, S::WithoutWavetable>
    {
        self.map_state_trusted(|state| state.without_wavetable())
    }

    pub fn with_waveform<W>(self, waveform: W) -> Oscillator<F, S::WithWaveform<W>>
    where
        W: Waveform<F>
    {
        self.map_state_trusted(|state| state.with_waveform(waveform))
    }
    pub fn map_waveform<W>(self, waveform: impl FnOnce(S::Waveform) -> W) -> Oscillator<F, S::WithWaveform<W>>
    where
        W: Waveform<F>
    {
        self.map_state_trusted(|state| state.map_waveform(waveform))
    }
}

impl<F, S> Deref for Oscillator<F, S>
where
    F: Float + FloatConst,
    S: OscillatorState<F>
{
    type Target = S;

    fn deref(&self) -> &Self::Target
    {
        &self.state
    }
}
impl<F, S> DerefMut for Oscillator<F, S>
where
    F: Float + FloatConst,
    S: OscillatorState<F>
{
    fn deref_mut(&mut self) -> &mut Self::Target
    {
        self.state.delete_cache();
        &mut self.state
    }
}

#[cfg(test)]
mod test
{
    use core::{error::Error, f32::consts::TAU};

    use crate::waveform::Sawtooth;

    use super::{Oscillator, Wave};

    #[test]
    fn it_works() -> Result<(), Box<dyn Error>>
    {
        const N: usize = 16;
        const L: usize = 64;
        const RATE: f32 = 8000.0;

        let mut osc = Oscillator::new(TAU, 0.0, Wave::<_, _, L>::from(Sawtooth));

        let y = core::array::from_fn::<_, N, _>(|_| osc.next(RATE));

        println!("{:?}", y);

        Ok(())
    }
}