oscillation/waveform/
sine.rs1use num_traits::{Euclid, Float, FloatConst};
2
3use crate::Wavetable;
4
5use super::Waveform;
6
7#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
8pub struct Sine;
9
10impl<F> Waveform<F> for Sine
11where
12 F: Float + FloatConst + Euclid
13{
14 fn waveform(&self, theta: F) -> F
15 {
16 theta.cos()
17 }
18 fn waveform_with_dtc(&self, theta: F, duty_cycle: F) -> F
19 {
20 let half = crate::duty_cycle_default::<F>();
21
22 if duty_cycle == half
23 {
24 return self.waveform(theta)
25 }
26 let one = F::one();
27 let eps = F::from(EPS).unwrap();
28
29 let mut a = (one - duty_cycle - duty_cycle).clamp(-one, one);
30 let s = a.signum();
31 a = a.abs();
32 let p = (a + eps)/(a - one - eps);
33
34 let mut numer = (-p*s*theta.cos()).exp();
35 if !numer.is_finite()
36 {
37 numer = F::zero()
38 }
39
40 s*(p.tanh().recip() - numer/p.sinh())
41 }
42 fn wavetable<const N: usize>(&self) -> Option<Wavetable<F, N>>
43 {
44 None
45 }
46 fn wavetable_with_dtc<const N: usize>(&self, duty_cycle: F) -> Option<Wavetable<F, N>>
47 {
48 let half = crate::duty_cycle_default::<F>();
49
50 if duty_cycle == half
51 {
52 return None
53 }
54 let zero = F::zero();
55 let one = F::one();
56 let eps = F::from(EPS).unwrap();
57
58 let mut a = (one - duty_cycle - duty_cycle).clamp(-one, one);
59 let s = a.signum();
60 a = a.abs();
61 let p = (a + eps)/(a - one - eps);
62
63 #[repr(C)]
64 struct In<const N: usize>
65 {
66 i0: f64,
67 i_n: [f64; N]
68 }
69
70 let mut i_n = In {
71 i0: 0.0,
72 i_n: [0.0; N]
73 };
74
75 {
76 let n = N.min(MAX_N);
77 let x = (-p*s).to_f64().unwrap().clamp(-MAX_I_N, MAX_I_N);
78 let i_n = unsafe {
79 core::slice::from_raw_parts_mut(&mut i_n.i0, n + 1)
80 };
81 rgsl::bessel::In_array(0, n as u32, x, i_n)
82 .expect("Bessel function failed.");
83 }
84
85 let g = p.sinh().recip();
86 let g2 = -s*(g + g);
87
88 Some(Wavetable::from_array(
89 s*(p.tanh().recip() - g*F::from(i_n.i0).unwrap()),
90 i_n.i_n.map(|i_n| (g2*F::from(i_n).unwrap(), zero))
91 ))
92 }
93}
94
95const MAX_N: usize = 64;
96const MAX_I_N: f64 = f32::MAX_EXP as f64;
97const EPS: f64 = 1.0/MAX_I_N;
98
99#[cfg(test)]
100mod test
101{
102 use core::error::Error;
103
104 use super::Sine;
105
106 #[test]
107 fn it_works() -> Result<(), Box<dyn Error>>
108 {
109 crate::tests::print_waveform(Sine)
110 }
111}