1use crate::euclid::Modulus;
4use std::f64::consts;
5pub fn log_spaced(length: usize, start_exp: f64, stop_exp: f64) -> Vec<f64> {
17 match length {
18 0 => Vec::new(),
19 1 => vec![10f64.powf(stop_exp)],
20 _ => {
21 let step = (stop_exp - start_exp) / (length - 1) as f64;
22 let mut vec = (0..length)
23 .map(|x| 10f64.powf(start_exp + (x as f64) * step))
24 .collect::<Vec<f64>>();
25 vec[length - 1] = 10f64.powf(stop_exp);
26 vec
27 }
28 }
29}
30
31#[derive(Clone, Copy, PartialEq, Debug)]
33pub struct InfinitePeriodic {
34 amplitude: f64,
35 step: f64,
36 phase: f64,
37 k: f64,
38}
39
40impl InfinitePeriodic {
41 pub fn new(
53 sampling_rate: f64,
54 frequency: f64,
55 amplitude: f64,
56 phase: f64,
57 delay: i64,
58 ) -> InfinitePeriodic {
59 let step = frequency / sampling_rate * amplitude;
60 InfinitePeriodic {
61 amplitude,
62 step,
63 phase: (phase - delay as f64 * step).modulus(amplitude),
64 k: 0.0,
65 }
66 }
67
68 pub fn default(sampling_rate: f64, frequency: f64) -> InfinitePeriodic {
80 Self::new(sampling_rate, frequency, 1.0, 0.0, 0)
81 }
82}
83
84impl std::fmt::Display for InfinitePeriodic {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{self:#?}")
87 }
88}
89
90impl Iterator for InfinitePeriodic {
91 type Item = f64;
92
93 fn next(&mut self) -> Option<f64> {
94 let mut x = self.phase + self.k * self.step;
95 if x >= self.amplitude {
96 x %= self.amplitude;
97 self.phase = x;
98 self.k = 0.0;
99 }
100 self.k += 1.0;
101 Some(x)
102 }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq)]
107pub struct InfiniteSinusoidal {
108 amplitude: f64,
109 mean: f64,
110 step: f64,
111 phase: f64,
112 i: usize,
113}
114
115impl InfiniteSinusoidal {
116 pub fn new(
132 sampling_rate: f64,
133 frequency: f64,
134 amplitude: f64,
135 mean: f64,
136 phase: f64,
137 delay: i64,
138 ) -> InfiniteSinusoidal {
139 let pi2 = consts::PI * 2.0;
140 let step = frequency / sampling_rate * pi2;
141 InfiniteSinusoidal {
142 amplitude,
143 mean,
144 step,
145 phase: (phase - delay as f64 * step) % pi2,
146 i: 0,
147 }
148 }
149
150 pub fn default(sampling_rate: f64, frequency: f64, amplitude: f64) -> InfiniteSinusoidal {
166 Self::new(sampling_rate, frequency, amplitude, 0.0, 0.0, 0)
167 }
168}
169
170impl std::fmt::Display for InfiniteSinusoidal {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 write!(f, "{:#?}", &self)
173 }
174}
175
176impl Iterator for InfiniteSinusoidal {
177 type Item = f64;
178
179 fn next(&mut self) -> Option<f64> {
180 let x = self.mean + self.amplitude * (self.phase + self.i as f64 * self.step).sin();
181 self.i += 1;
182 if self.i == 1000 {
183 self.i = 0;
184 self.phase = (self.phase + 1000.0 * self.step) % (consts::PI * 2.0);
185 }
186 Some(x)
187 }
188}
189
190#[derive(Debug, Clone, Copy, PartialEq)]
193pub struct InfiniteSquare {
194 periodic: InfinitePeriodic,
195 high_duration: f64,
196 high_value: f64,
197 low_value: f64,
198}
199
200impl InfiniteSquare {
201 pub fn new(
214 high_duration: i64,
215 low_duration: i64,
216 high_value: f64,
217 low_value: f64,
218 delay: i64,
219 ) -> InfiniteSquare {
220 let duration = (high_duration + low_duration) as f64;
221 InfiniteSquare {
222 periodic: InfinitePeriodic::new(1.0, 1.0 / duration, duration, 0.0, delay),
223 high_duration: high_duration as f64,
224 high_value,
225 low_value,
226 }
227 }
228}
229
230impl std::fmt::Display for InfiniteSquare {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232 write!(f, "{:#?}", &self)
233 }
234}
235
236impl Iterator for InfiniteSquare {
237 type Item = f64;
238
239 fn next(&mut self) -> Option<f64> {
240 self.periodic.next().map(|x| {
241 if x < self.high_duration {
242 self.high_value
243 } else {
244 self.low_value
245 }
246 })
247 }
248}
249
250#[derive(Debug, Clone, Copy, PartialEq)]
253pub struct InfiniteTriangle {
254 periodic: InfinitePeriodic,
255 raise_duration: f64,
256 raise: f64,
257 fall: f64,
258 high_value: f64,
259 low_value: f64,
260}
261
262impl InfiniteTriangle {
263 pub fn new(
284 raise_duration: i64,
285 fall_duration: i64,
286 high_value: f64,
287 low_value: f64,
288 delay: i64,
289 ) -> InfiniteTriangle {
290 let duration = (raise_duration + fall_duration) as f64;
291 let height = high_value - low_value;
292 InfiniteTriangle {
293 periodic: InfinitePeriodic::new(1.0, 1.0 / duration, duration, 0.0, delay),
294 raise_duration: raise_duration as f64,
295 raise: height / raise_duration as f64,
296 fall: height / fall_duration as f64,
297 high_value,
298 low_value,
299 }
300 }
301}
302
303impl std::fmt::Display for InfiniteTriangle {
304 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305 write!(f, "{:#?}", &self)
306 }
307}
308
309impl Iterator for InfiniteTriangle {
310 type Item = f64;
311
312 fn next(&mut self) -> Option<f64> {
313 self.periodic.next().map(|x| {
314 if x < self.raise_duration {
315 self.low_value + x * self.raise
316 } else {
317 self.high_value - (x - self.raise_duration) * self.fall
318 }
319 })
320 }
321}
322
323#[derive(Debug, Clone, Copy, PartialEq)]
326pub struct InfiniteSawtooth {
327 periodic: InfinitePeriodic,
328 low_value: f64,
329}
330
331impl InfiniteSawtooth {
332 pub fn new(period: i64, high_value: f64, low_value: f64, delay: i64) -> InfiniteSawtooth {
345 let height = high_value - low_value;
346 let period = period as f64;
347 InfiniteSawtooth {
348 periodic: InfinitePeriodic::new(
349 1.0,
350 1.0 / period,
351 height * period / (period - 1.0),
352 0.0,
353 delay,
354 ),
355 low_value,
356 }
357 }
358}
359
360impl std::fmt::Display for InfiniteSawtooth {
361 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
362 write!(f, "{:#?}", &self)
363 }
364}
365
366impl Iterator for InfiniteSawtooth {
367 type Item = f64;
368
369 fn next(&mut self) -> Option<f64> {
370 self.periodic.next().map(|x| x + self.low_value)
371 }
372}