1use super::signal::{Rack, Real, Signal};
2use approx::relative_eq;
3
4#[derive(Copy, Clone, Debug)]
8pub struct ExpInterp {
9 low: Real,
10 mid: Real,
11 high: Real,
12 a: Real,
13 b: Real,
14 c: Real,
15 linear: bool,
16}
17
18impl ExpInterp {
19 pub fn new(low: Real, mid: Real, high: Real) -> Self {
20 let mut exp_interp = ExpInterp {
21 low,
22 mid,
23 high,
24 a: 0.0,
25 b: 0.0,
26 c: 0.0,
27 linear: true,
28 };
29 if relative_eq!(high - mid, mid - low) {
30 exp_interp
31 } else {
32 exp_interp.update(low, mid, high);
33 exp_interp
34 }
35 }
36
37 pub fn update(&mut self, low: Real, mid: Real, high: Real) {
38 if relative_eq!(high - mid, mid - low) {
39 self.low = low;
40 self.mid = mid;
41 self.high = high;
42 self.linear = true;
43 } else {
44 self.b = (mid - low) * (mid - low) / (high - 2.0 * mid + low);
45 self.a = low - self.b;
46 self.c = 2.0 * ((high - mid) / (mid - low)).ln();
47 self.linear = false;
48 }
49 }
50
51 pub fn interp(&self, x: Real) -> Real {
53 if self.linear {
54 self.low + (self.high - self.low) * x
55 } else {
56 self.a + self.b * (self.c * x).exp()
57 }
58 }
59
60 pub fn interp_inv(&self, y: Real) -> Real {
62 if self.linear {
63 (y - self.low) / (self.high - self.low)
64 } else {
65 ((y - self.a) / self.b).ln() / self.c
66 }
67 }
68}
69
70pub fn signals<T>(module: &mut T, start: u32, end: u32, sample_rate: Real) -> Vec<(f32, f32)>
71where
72 T: Signal,
73{
74 let rack = Rack::new(vec![]);
75 let mut result = vec![];
76 for i in start..=end {
77 result.push((
78 i as f32 / sample_rate as f32,
79 module.signal(&rack, sample_rate) as f32,
80 ));
81 }
82 result
83}
84
85#[derive(Clone)]
87pub struct RingBuffer<T> {
88 buffer: Vec<T>,
89 pub read_pos: Real,
90 pub write_pos: usize,
91}
92
93impl<T> RingBuffer<T>
94where
95 T: Clone + Default,
96{
97 pub fn new(read_pos: Real, write_pos: usize) -> Self {
98 assert!(
99 read_pos.trunc() as usize <= write_pos,
100 "Read position must be <= write postion"
101 );
102 RingBuffer {
103 buffer: vec![Default::default(); write_pos + 3],
105 read_pos,
106 write_pos,
107 }
108 }
109
110 pub fn push(&mut self, v: T) {
111 let n = self.buffer.len();
112 self.write_pos = (self.write_pos + 1) % n;
113 self.read_pos = (self.read_pos + 1.0) % n as Real;
114 self.buffer[self.write_pos] = v;
115 }
116
117 pub fn len(&self) -> usize {
118 self.buffer.len()
119 }
120
121 pub fn resize(&mut self, size: usize) {
122 self.buffer.resize_with(size, Default::default);
123 }
124
125 pub fn set_read_pos(&mut self, rp: Real) {
126 self.read_pos = rp % self.buffer.len() as Real;
127 }
128
129 pub fn set_write_pos(&mut self, wp: usize) {
130 self.write_pos = wp % self.buffer.len();
131 }
132}
133
134impl<T> RingBuffer<T>
135where
136 T: Copy + Default,
137{
138 pub fn get(&self) -> T {
139 self.buffer[self.read_pos.trunc() as usize]
140 }
141
142 pub fn get_offset(&self, offset: i32) -> T {
143 let n = self.buffer.len() as i32;
144 let mut offset = offset;
145 while offset < 0 {
146 offset += n;
147 }
148 let i = (self.read_pos.trunc() as usize + offset as usize) % n as usize;
149 self.buffer[i]
150 }
151}
152
153impl RingBuffer<Real> {
154 pub fn get_linear(&self) -> Real {
155 let f = self.read_pos - self.read_pos.trunc();
156 (1.0 - f) * self.get() + f * self.get_offset(1)
157 }
158
159 pub fn get_cubic(&self) -> Real {
161 let v0 = self.get_offset(-1);
162 let v1 = self.get();
163 let v2 = self.get_offset(1);
164 let v3 = self.get_offset(2);
165 let f = self.read_pos - self.read_pos.trunc();
166 let a1 = 0.5 * (v2 - v0);
167 let a2 = v0 - 2.5 * v1 + 2.0 * v2 - 0.5 * v3;
168 let a3 = 0.5 * (v3 - v0) + 1.5 * (v1 - v2);
169 a3 * f * f * f + a2 * f * f + a1 * f + v1
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176 use approx::relative_eq;
177
178 fn trunc4(x: Real) -> i32 {
179 (10_000.0 * x + 0.5) as i32
180 }
181 #[test]
182 fn linear_interp() {
183 let ie = ExpInterp::new(0.0, 0.5, 1.0);
184 assert!(relative_eq!(ie.interp(0.0), 0.0));
185 assert!(relative_eq!(ie.interp(0.5), 0.5));
186 assert!(relative_eq!(ie.interp(0.75), 0.75));
187 assert!(relative_eq!(ie.interp(1.0), 1.0));
188 }
189 #[test]
190 fn exp_interp() {
191 let ie = ExpInterp::new(0.0, 0.4, 1.0);
192 let result = trunc4(ie.interp(0.0));
193 assert_eq!(result, 0, "interp returned {}, epxected 0", result);
194 let result = trunc4(ie.interp(0.5));
195 assert_eq!(result, 4_000, "interp returned {}, epxected 4,000", result);
196 let result = trunc4(ie.interp(0.75));
197 assert_eq!(result, 6_697, "interp returned {}, epxected 6,697", result);
198 let result = trunc4(ie.interp(1.0));
199 assert_eq!(
200 result, 10_000,
201 "interp returned {}, epxected 10,1000",
202 result
203 );
204 }
205 #[test]
206 fn linear_interp_inv() {
207 let ie = ExpInterp::new(0.0, 0.5, 1.0);
208 assert!(relative_eq!(ie.interp_inv(0.0), 0.0));
209 assert!(relative_eq!(ie.interp_inv(0.5), 0.5));
210 assert!(relative_eq!(ie.interp_inv(0.75), 0.75));
211 assert!(relative_eq!(ie.interp_inv(1.0), 1.0));
212 }
213 #[test]
214 fn exp_interp_inv() {
215 let ie = ExpInterp::new(0.0, 0.4, 1.0);
216 let result = trunc4(ie.interp_inv(0.0));
217 assert_eq!(result, 0, "interp returned {}, epxected 0", result);
218 let result = trunc4(ie.interp_inv(0.4));
219 assert_eq!(result, 5_000, "interp returned {}, epxected 4,000", result);
220 let result = trunc4(ie.interp_inv(0.6697));
221 assert_eq!(result, 7_500, "interp returned {}, epxected 7,500", result);
222 let result = trunc4(ie.interp_inv(1.0));
223 assert_eq!(
224 result, 10_000,
225 "interp returned {}, epxected 10,1000",
226 result
227 );
228 }
229
230 #[test]
231 fn ring_buffer() {
232 let mut rb = RingBuffer::<Real>::new(0.5, 5);
233 let result = rb.get();
234 assert_eq!(result, 0.0, "get returned {}, expected 0.0", result);
235 for i in 0..=6 {
236 rb.push(i as Real);
237 }
238 let result = rb.get();
239 assert_eq!(result, 1.0, "get returned {}, expected 0.0", result);
240 let result = rb.get_linear();
241 assert_eq!(result, 1.5, "get_linear returned {}, expected 0.0", result);
242 let result = rb.get_cubic();
243 assert_eq!(result, 1.5, "get_cubic returned {}, expected 0.0", result);
244 }
245
246 #[test]
247 fn ring_buffer_resize() {
248 let mut rb = RingBuffer::<Real>::new(0.5, 5);
249 rb.resize(10);
250 for i in 0..=6 {
251 rb.push(i as Real);
252 }
253 let result = rb.get_linear();
254 assert_eq!(result, 1.5, "get_linear returned {}, expected 0.0", result);
255 let result = rb.get_cubic();
256 assert_eq!(result, 1.5, "get_cubic returned {}, expected 0.0", result);
257 }
258}