1#[cfg(not(test))]
11use crate::math::Libm;
12
13use fon::chan::Ch32;
14
15#[derive(Default, Clone, Copy, Debug)]
17pub struct Triangle(f32);
18
19impl Triangle {
20 #[inline(always)]
22 pub fn new() -> Self {
23 Self::default()
24 }
25
26 #[inline(always)]
28 pub fn peek(&mut self) -> Ch32 {
29 (((1.0 - self.0).abs() - 0.5) * 2.0).into()
30 }
31
32 #[inline(always)]
34 pub fn step(&mut self, hz: f32) -> Ch32 {
35 let out = self.peek();
36 self.0 = (self.0 + 2.0 * super::SAMPLE_PERIOD * hz) % 2.0;
37 out
38 }
39
40 #[inline(always)]
42 pub fn phase(&mut self, hz: f32, shift: Ch32) -> Ch32 {
43 let original = self.0;
44 let shift = if f32::from(shift) < 0.0 {
45 1.0 + f32::from(shift)
46 } else {
47 f32::from(shift)
48 };
49 self.0 = (original + 2.0 * (super::SAMPLE_PERIOD * hz + shift)) % 2.0;
50 let out = self.peek();
51 self.0 = (original + 2.0 * super::SAMPLE_PERIOD * hz) % 2.0;
52 out
53 }
54
55 #[inline(always)]
57 pub fn shift(&mut self, shift: Ch32) {
58 let shift = if f32::from(shift) < 0.0 {
59 1.0 + f32::from(shift)
60 } else {
61 f32::from(shift)
62 };
63 self.0 = (self.0 + 2.0 * shift) % 2.0;
64 }
65}