euphony-dsp 0.1.1

implementation of euphony's signal processing nodes
Documentation
use crate::prelude::*;

#[derive(Debug, Default, Node)]
#[node(id = 200, module = "env")]
#[input(target, default = 0.0, trigger = set_target)]
#[input(duration, default = 0.01, trigger = set_duration)]
#[input(value, default = 0.0, trigger = set_value)]
pub struct Linear {
    value: f64,
    target: f64,
    duration: f64,
    step: f64,
    samples: usize,
}

impl Linear {
    #[inline]
    fn set_value(&mut self, value: f64) {
        self.value = value;
        self.update();
    }

    #[inline]
    fn set_target(&mut self, value: f64) {
        self.target = value;
        self.update();
    }

    #[inline]
    fn set_duration(&mut self, value: f64) {
        self.duration = value;
        self.update();
    }

    fn update(&mut self) {
        let diff = self.target - self.value;
        let samples = (self.duration * Rate::VALUE).round();
        self.samples = samples as _;
        if self.samples > 0 {
            self.step = diff / samples;
        } else {
            self.step = 0.0;
        }
    }

    #[inline]
    pub fn render(&mut self, output: &mut [f64]) {
        for frame in output {
            *frame = self.value;
            if let Some(samples) = self.samples.checked_sub(1) {
                self.samples = samples;
                self.value += self.step;
            } else {
                self.value = self.target;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn linear_test() {
        let mut env = Linear::new();
        env.set_target(1.0);

        let mut out = [0.0; 512];
        env.render(&mut out[..]);
        assert_eq!(out[0], 0.0);
        assert_eq!(out[511], 1.0);
        assert_ne!(out[1], 0.0);

        env.set_target(0.0);
        env.render(&mut out[..]);
        assert_eq!(out[0], 1.0);
        assert_eq!(out[511], 0.0);
    }
}