1use super::audionode::*;
4use super::math::*;
5use super::setting::*;
6use super::signal::*;
7use super::*;
8use numeric_array::*;
9
10#[derive(Default, Clone)]
17pub struct Moog<F: Real, N: Size<f32>> {
18 _marker: core::marker::PhantomData<N>,
19 q: F,
20 cutoff: F,
21 sample_rate: F,
22 rez: F,
23 p: F,
24 k: F,
25 s0: F,
26 s1: F,
27 s2: F,
28 s3: F,
29 px: F,
30 ps0: F,
31 ps1: F,
32 ps2: F,
33}
34
35impl<F: Real, N: Size<f32>> Moog<F, N> {
36 pub fn new(cutoff: F, q: F) -> Self {
37 let mut node = Self {
38 sample_rate: convert(DEFAULT_SR),
39 ..Self::default()
40 };
41 node.set_cutoff_q(cutoff, q);
42 node
43 }
44
45 #[inline]
48 pub fn set_cutoff_q(&mut self, cutoff: F, q: F) {
49 self.cutoff = cutoff;
50 self.q = q;
51 let c = F::new(2) * cutoff / self.sample_rate;
52 self.p = c * (F::from_f64(1.8) - F::from_f64(0.8) * c);
53 self.k = F::new(2) * sin(c * F::PI * F::from_f64(0.5)) - F::one();
54 let t1 = (F::one() - self.p) * F::from_f64(1.386249);
55 let t2 = F::new(12) + t1 * t1;
56 self.rez = q * (t2 + F::new(6) * t1) / (t2 - F::new(6) * t1);
57 }
58}
59
60impl<F: Real, N: Size<f32>> AudioNode for Moog<F, N> {
61 const ID: u64 = 60;
62 type Inputs = N;
63 type Outputs = typenum::U1;
64
65 fn reset(&mut self) {
66 self.s0 = F::zero();
67 self.s1 = F::zero();
68 self.s2 = F::zero();
69 self.s3 = F::zero();
70 self.px = F::zero();
71 self.ps0 = F::zero();
72 self.ps1 = F::zero();
73 self.ps2 = F::zero();
74 }
75
76 fn set_sample_rate(&mut self, sample_rate: f64) {
77 self.sample_rate = convert(sample_rate);
78 self.set_cutoff_q(self.cutoff, self.q);
79 }
80
81 #[inline]
82 fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
83 if N::USIZE > 1 {
84 self.set_cutoff_q(convert(input[1]), convert(input[2]));
85 }
86
87 let x = -self.rez * self.s3 + convert(input[0]);
88
89 self.s0 = (x + self.px) * self.p - self.k * self.s0;
90 self.s1 = (self.s0 + self.ps0) * self.p - self.k * self.s1;
91 self.s2 = (self.s1 + self.ps1) * self.p - self.k * self.s2;
92 self.s3 = tanh((self.s2 + self.ps2) * self.p - self.k * self.s3);
93
94 self.px = x;
95 self.ps0 = self.s0;
96 self.ps1 = self.s1;
97 self.ps2 = self.s2;
98
99 [convert(self.s3)].into()
100 }
101
102 fn set(&mut self, setting: Setting) {
103 match setting.parameter() {
104 Parameter::Center(cutoff) => self.set_cutoff_q(F::from_f32(*cutoff), self.q),
105 Parameter::CenterQ(cutoff, q) => {
106 self.set_cutoff_q(F::from_f32(*cutoff), F::from_f32(*q))
107 }
108 _ => (),
109 }
110 }
111
112 fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
113 let mut output = SignalFrame::new(self.outputs());
114 output.set(0, input.at(0).distort(0.0));
115 output
116 }
117}