1use serde::de::{self, Error};
2use serde::ser::{self, SerializeTuple};
3
4use std::cell::RefCell;
5use std::fmt;
6
7#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
8pub struct Point {
9 pub stop: f32,
13
14 pub amplitude: f32,
16}
17
18impl ser::Serialize for Point {
19 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: ser::Serializer,
22 {
23 let mut tup = serializer.serialize_tuple(2)?;
24 tup.serialize_element(&((self.stop * 100.0) as i8))?;
25 tup.serialize_element(&((self.amplitude * 255.0) as u8))?;
26 tup.end()
27 }
28}
29
30struct PointVisitor;
31
32impl<'de> de::Visitor<'de> for PointVisitor {
33 type Value = Point;
34
35 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
36 formatter.write_str("A pair of tuples")
37 }
38
39 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
40 where
41 A: de::SeqAccess<'de>,
42 {
43 let stop: Option<i8> = seq.next_element()?;
44 let stop = stop.ok_or_else(|| A::Error::invalid_length(0, &self))?;
45 let amplitude: Option<u8> = seq.next_element()?;
46 let amplitude = amplitude.ok_or_else(|| A::Error::invalid_length(1, &self))?;
47 let stop = stop as f32 / 100.0;
48 let amplitude = amplitude as f32 / 255.0;
49 Ok(Point { stop, amplitude })
50 }
51}
52
53impl<'de> de::Deserialize<'de> for Point {
54 fn deserialize<D>(deserializer: D) -> Result<Point, D::Error>
55 where
56 D: de::Deserializer<'de>,
57 {
58 deserializer.deserialize_tuple(2, PointVisitor)
59 }
60}
61
62#[derive(Debug, Clone, PartialEq)]
63pub struct Envelope {
64 pub points: Vec<Point>,
65
66 note_points: RefCell<Vec<Point>>,
68}
69
70impl ser::Serialize for Envelope {
71 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72 where
73 S: ser::Serializer,
74 {
75 use ser::SerializeSeq;
76 let mut seq = serializer.serialize_seq(Some(self.points.len()))?;
77 for point in &self.points {
78 seq.serialize_element(point)?;
79 }
80 seq.end()
81 }
82}
83
84struct EnvelopeVisitor;
85
86impl<'de> de::Visitor<'de> for EnvelopeVisitor {
87 type Value = Envelope;
88
89 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
90 formatter.write_str("A sequence of points")
91 }
92
93 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
94 where
95 A: de::SeqAccess<'de>,
96 {
97 let mut points = match seq.size_hint() {
98 Some(size) => Vec::with_capacity(size),
99 None => Vec::new(),
100 };
101 while let Some(point) = seq.next_element()? {
102 points.push(point);
103 }
104 Ok(Envelope {
105 points,
106 note_points: RefCell::new(Vec::new()),
107 })
108 }
109}
110
111impl<'de> de::Deserialize<'de> for Envelope {
112 fn deserialize<D>(deserializer: D) -> Result<Envelope, D::Error>
113 where
114 D: de::Deserializer<'de>,
115 {
116 deserializer.deserialize_seq(EnvelopeVisitor)
117 }
118}
119
120impl Default for Envelope {
121 fn default() -> Self {
122 Envelope {
123 points: vec![
124 Point {
125 stop: 0.0,
126 amplitude: 0.0,
127 },
128 Point {
129 stop: 0.05,
130 amplitude: 1.0,
131 },
132 Point {
133 stop: -0.05,
134 amplitude: 0.8,
135 },
136 Point {
137 stop: -0.01,
138 amplitude: 0.0,
139 },
140 ],
141 note_points: RefCell::new(Vec::new()),
142 }
143 }
144}
145
146#[inline]
147fn lerp(x: f32, a: (f32, f32), b: (f32, f32)) -> f32 {
148 a.1 + (x - a.0) * (b.1 - a.1) / (b.0 - a.0)
149}
150
151impl Envelope {
152 pub fn prepare_note(&self, note_length: f32) {
153 let mut points: Vec<Point> = self
156 .points
157 .iter()
158 .filter_map(|point| {
159 let stop = if point.stop < 0.0 {
160 note_length + point.stop
162 } else {
163 point.stop
164 };
165
166 Some(Point {
167 amplitude: point.amplitude,
168 stop,
169 })
170 .filter(|p| (0.0..=note_length).contains(&p.stop))
171 })
172 .collect();
173
174 let mut lastmax = -1.0;
175 points.retain(move |point| {
179 if point.stop > lastmax {
180 lastmax = point.stop;
181 true
182 } else {
183 false
184 }
185 });
186
187 let mut note_points = self.note_points.borrow_mut();
188 *note_points = points;
189 }
190
191 pub fn amplitude_at_time(&self, time_point: f32) -> f32 {
192 let mut points = self.note_points.borrow_mut();
193
194 if points.first().unwrap().stop >= time_point {
196 points.first().unwrap().amplitude
197 } else if points.last().unwrap().stop <= time_point {
198 points.last().unwrap().amplitude
199 } else {
200 loop {
201 let (first, second) = (&points[0], &points[1]);
202 if first.stop <= time_point && time_point <= second.stop {
203 return lerp(
204 time_point,
205 (first.stop, first.amplitude),
206 (second.stop, second.amplitude),
207 );
208 } else {
209 points.remove(0);
210 }
211 }
212 }
213 }
214}