Skip to main content

oscen/
envelopes.rs

1use super::signal::*;
2use super::utils::ExpInterp;
3use crate::{as_any_mut, gate, std_signal};
4use std::{
5    any::Any,
6    ops::{Index, IndexMut},
7};
8
9#[derive(Copy, Clone)]
10pub struct Adsr {
11    tag: Tag,
12    attack: In,
13    decay: In,
14    sustain: In,
15    release: In,
16    clock: Real,
17    sustain_time: Real,
18    triggered: bool,
19    level: Real,
20    a_param: Real,
21    d_param: Real,
22    r_param: Real,
23    a_interp: ExpInterp,
24    d_interp: ExpInterp,
25    r_interp: ExpInterp,
26}
27
28impl Adsr {
29    pub fn new(a_param: Real, d_param: Real, r_param: Real) -> Self {
30        let a_interp = ExpInterp::new(0.0, 0.5, 1.0);
31        let d_interp = ExpInterp::new(0.0, 0.5, 1.0);
32        let r_interp = ExpInterp::new(0.0, 0.5, 1.0);
33        Self {
34            tag: mk_tag(),
35            attack: (0.01).into(),
36            decay: 0.into(),
37            sustain: 1.into(),
38            release: (0.1).into(),
39            clock: 0.0,
40            sustain_time: 0.0,
41            triggered: false,
42            level: 0.0,
43            a_param,
44            d_param,
45            r_param,
46            a_interp,
47            d_interp,
48            r_interp,
49        }
50    }
51
52    pub fn linear() -> Self {
53        Self::new(0.5, 0.5, 0.5)
54    }
55
56    pub fn exp_20() -> Self {
57        Self::new(0.2, 0.2, 0.2)
58    }
59
60    pub fn attack<T: Into<In>>(&mut self, arg: T) -> &mut Self {
61        self.attack = arg.into();
62        self
63    }
64
65    pub fn decay<T: Into<In>>(&mut self, arg: T) -> &mut Self {
66        self.decay = arg.into();
67        self
68    }
69
70    pub fn sustain<T: Into<In>>(&mut self, arg: T) -> &mut Self {
71        self.sustain = arg.into();
72        self
73    }
74
75    pub fn release<T: Into<In>>(&mut self, arg: T) -> &mut Self {
76        self.release = arg.into();
77        self
78    }
79
80    pub fn calc_level(&mut self, rack: &Rack) -> Real {
81        fn max01(a: f64) -> f64 {
82            if a > 0.01 {
83                a
84            } else {
85                0.01
86            }
87        }
88
89        let a = max01(In::val(rack, self.attack));
90        let d = max01(In::val(rack, self.decay));
91        let s = In::val(rack, self.sustain);
92        let r = max01(In::val(rack, self.release));
93
94        if self.triggered {
95            match self.clock {
96                // Attack
97                t if t < a => self.a_interp.interp(t / a),
98                // Decay
99                t if t < a + d => self.d_interp.interp((t - a) / d),
100                // Sustain
101                t => {
102                    self.sustain_time = t - a - d;
103                    s
104                }
105            }
106        } else {
107            match self.clock {
108                // Attack
109                t if t < a => self.a_interp.interp(t / a),
110                // Decay
111                t if t < a + d => self.d_interp.interp((t - a) / d),
112                // Release
113                t if t < a + d + r + self.sustain_time => {
114                    self.r_interp.interp((t - a - d - self.sustain_time) / r)
115                }
116                // Off
117                _ => 0.,
118            }
119        }
120    }
121
122    pub fn on(&mut self) {
123        self.triggered = true;
124        self.sustain_time = 0.0;
125        self.clock = self.a_interp.interp_inv(self.level);
126    }
127
128    pub fn off(&mut self) {
129        self.triggered = false;
130    }
131}
132
133impl Builder for Adsr {}
134
135gate!(Adsr);
136
137impl Signal for Adsr {
138    std_signal!();
139    fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
140        self.a_interp.update(0.0, 1.0 - self.a_param, 1.0);
141        let s = In::val(rack, self.sustain);
142        self.d_interp.update(1.0, s + self.d_param * (1.0 - s), s);
143        self.r_interp.update(s, self.r_param * s, 0.0);
144        self.level = self.calc_level(rack);
145        self.clock += 1. / sample_rate;
146        self.level
147    }
148}
149
150impl Index<&str> for Adsr {
151    type Output = In;
152
153    fn index(&self, index: &str) -> &Self::Output {
154        match index {
155            "attack" => &self.attack,
156            "decay" => &self.decay,
157            "sustain" => &self.sustain,
158            "release" => &self.release,
159            _ => panic!("Adsr does not have a field named: {}", index),
160        }
161    }
162}
163
164impl IndexMut<&str> for Adsr {
165    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
166        match index {
167            "attack" => &mut self.attack,
168            "decay" => &mut self.decay,
169            "sustain" => &mut self.sustain,
170            "release" => &mut self.release,
171            _ => panic!("Adsr does not have a field named: {}", index),
172        }
173    }
174}