euphony_dsp/osc/
wave.rs

1use crate::{fun::math::lerp, prelude::*};
2
3#[derive(Debug, Clone, Copy, Default, Node)]
4#[node(id = 114, module = "osc")]
5#[input(frequency, default = 440.0)]
6#[input(phase, trigger = set_phase)]
7#[buffer(buffer)]
8pub struct Wave {
9    phase: super::Phase,
10}
11
12impl Wave {
13    #[inline]
14    pub fn set_phase(&mut self, phase: f64) {
15        self.phase.set(phase);
16    }
17
18    #[inline]
19    pub fn render(&mut self, frequency: Input, buffer: Buffer, output: &mut [Sample]) {
20        if buffer.samples.is_empty() {
21            output.fill(0.0);
22            return;
23        }
24
25        let len = buffer.samples.len() as f64;
26
27        for (freq, output) in (frequency, output.iter_mut()).zip() {
28            let phase = self.phase.next(freq);
29            // interpolate the phase onto the buffer's len
30            let position = phase * len;
31            *output = lerp_buffer(buffer.samples, position);
32        }
33    }
34}
35
36#[derive(Debug, Clone, Copy, Default, Node)]
37#[node(id = 115, module = "osc")]
38#[input(frequency, default = 440.0)]
39#[input(position, default = 0.0)]
40#[input(phase, trigger = set_phase)]
41#[buffer(a)]
42#[buffer(b)]
43pub struct Morph {
44    phase: super::Phase,
45}
46
47impl Morph {
48    #[inline]
49    pub fn set_phase(&mut self, phase: f64) {
50        self.phase.set(phase);
51    }
52
53    #[inline]
54    pub fn render(
55        &mut self,
56        frequency: Input,
57        position: Input,
58        a: Buffer,
59        b: Buffer,
60        output: &mut [Sample],
61    ) {
62        if a.samples.is_empty() && b.samples.is_empty() {
63            output.fill(0.0);
64            return;
65        }
66
67        let a = if a.samples.is_empty() {
68            &[0.0]
69        } else {
70            a.samples
71        };
72
73        let b = if b.samples.is_empty() {
74            &[0.0]
75        } else {
76            b.samples
77        };
78
79        let a_len = a.len() as f64;
80        let b_len = b.len() as f64;
81
82        for (freq, position, output) in (frequency, position, output.iter_mut()).zip() {
83            let phase = self.phase.next(freq);
84            let position = position.fract().abs();
85            // interpolate the phase onto the buffer's len
86            let a_position = phase * a_len;
87            let b_position = phase * b_len;
88            let a_value = lerp_buffer(a, a_position);
89            let b_value = lerp_buffer(b, b_position);
90
91            *output = (a_value * (1.0 - position)) + (b_value * position);
92        }
93    }
94}
95
96#[derive(Debug, Clone, Copy, Default, Node)]
97#[node(id = 317, module = "filter")]
98#[input(signal)]
99#[buffer(buffer)]
100pub struct Shaper;
101
102impl Shaper {
103    #[inline]
104    pub fn render(&mut self, signal: Input, buffer: Buffer, output: &mut [Sample]) {
105        if buffer.samples.is_empty() {
106            output.fill(0.0);
107            return;
108        }
109
110        let len = buffer.samples.len() as f64;
111
112        for (t, output) in (signal, output.iter_mut()).zip() {
113            // interpolate the signal (-1..1) to 0..1
114            let t = (t * 0.5 + 0.5).fract();
115            // interpolate the signal onto the buffer's len
116            let position = t * len;
117            *output = lerp_buffer(buffer.samples, position);
118        }
119    }
120}
121
122#[inline(always)]
123fn lerp_buffer(buffer: &[Sample], position: f64) -> Sample {
124    // round down to the nearest index
125    let index = position as usize;
126
127    // get index and index+1 wrapped to the beginning
128    let a = *unsafe { buffer.get_unchecked(index) };
129    let b = *if let Some(s) = buffer.get(index + 1) {
130        s
131    } else {
132        unsafe { buffer.get_unchecked(0) }
133    };
134
135    // interpolate between the two indexes
136    let fract = position.fract();
137    lerp(a, b, fract)
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn wave_test() {
146        let mut osc = Wave::new();
147        let mut out = [0.0; 500];
148        let freq = 480.0.into();
149        let buffer = (&[-1.0, 1.0][..]).into();
150        osc.render(freq, buffer, &mut out);
151        eprintln!("{:?}", out);
152        // panic!();
153    }
154}