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 t if t < a => self.a_interp.interp(t / a),
98 t if t < a + d => self.d_interp.interp((t - a) / d),
100 t => {
102 self.sustain_time = t - a - d;
103 s
104 }
105 }
106 } else {
107 match self.clock {
108 t if t < a => self.a_interp.interp(t / a),
110 t if t < a + d => self.d_interp.interp((t - a) / d),
112 t if t < a + d + r + self.sustain_time => {
114 self.r_interp.interp((t - a - d - self.sustain_time) / r)
115 }
116 _ => 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}