1use crate::prelude::*;
2
3#[derive(Debug, Default, Node)]
4#[node(id = 200, module = "env")]
5#[input(target, default = 0.0, trigger = set_target)]
6#[input(duration, default = 0.01, trigger = set_duration)]
7#[input(value, default = 0.0, trigger = set_value)]
8pub struct Linear {
9 value: f64,
10 target: f64,
11 duration: f64,
12 step: f64,
13 samples: usize,
14}
15
16impl Linear {
17 #[inline]
18 fn set_value(&mut self, value: f64) {
19 self.value = value;
20 self.update();
21 }
22
23 #[inline]
24 fn set_target(&mut self, value: f64) {
25 self.target = value;
26 self.update();
27 }
28
29 #[inline]
30 fn set_duration(&mut self, value: f64) {
31 self.duration = value;
32 self.update();
33 }
34
35 fn update(&mut self) {
36 let diff = self.target - self.value;
37 let samples = (self.duration * Rate::VALUE).round();
38 self.samples = samples as _;
39 if self.samples > 0 {
40 self.step = diff / samples;
41 } else {
42 self.step = 0.0;
43 }
44 }
45
46 #[inline]
47 pub fn render(&mut self, output: &mut [f64]) {
48 for frame in output {
49 *frame = self.value;
50 if let Some(samples) = self.samples.checked_sub(1) {
51 self.samples = samples;
52 self.value += self.step;
53 } else {
54 self.value = self.target;
55 }
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn linear_test() {
66 let mut env = Linear::new();
67 env.set_target(1.0);
68
69 let mut out = [0.0; 512];
70 env.render(&mut out[..]);
71 assert_eq!(out[0], 0.0);
72 assert_eq!(out[511], 1.0);
73 assert_ne!(out[1], 0.0);
74
75 env.set_target(0.0);
76 env.render(&mut out[..]);
77 assert_eq!(out[0], 1.0);
78 assert_eq!(out[511], 0.0);
79 }
80}