libdaw/nodes/
sawtooth_oscillator.rs

1use crate::{stream::Stream, sync::AtomicF64, FrequencyNode, Node, Result};
2use std::sync::atomic::Ordering;
3
4#[derive(Debug)]
5pub struct SawtoothOscillator {
6    frequency: AtomicF64,
7    sample_rate: f64,
8    sample: AtomicF64,
9    delta: AtomicF64,
10    channels: usize,
11}
12
13impl SawtoothOscillator {
14    pub fn new(sample_rate: u32, channels: u16) -> Self {
15        let node = SawtoothOscillator {
16            frequency: AtomicF64::new(256.0),
17            sample: Default::default(),
18            sample_rate: sample_rate as f64,
19            delta: AtomicF64::new(0.01),
20            channels: channels.into(),
21        };
22        node.calculate_delta();
23        node
24    }
25
26    fn calculate_delta(&self) {
27        // Multiply by 2.0 because the samples vary from -1.0 to 1.0, which is a
28        // 2.0 range.
29        self.delta.store(
30            self.frequency.load(Ordering::Relaxed) * 2.0 / self.sample_rate,
31            Ordering::Relaxed,
32        );
33    }
34}
35
36impl FrequencyNode for SawtoothOscillator {
37    fn set_frequency(&self, frequency: f64) -> Result<()> {
38        self.frequency.store(frequency, Ordering::Relaxed);
39        self.calculate_delta();
40        Ok(())
41    }
42    fn get_frequency(&self) -> Result<f64> {
43        Ok(self.frequency.load(Ordering::Relaxed))
44    }
45}
46
47impl Node for SawtoothOscillator {
48    fn process<'a, 'b, 'c>(&'a self, _: &'b [Stream], outputs: &'c mut Vec<Stream>) -> Result<()> {
49        let sample = self.sample.swap(
50            (self.sample.load(Ordering::Relaxed) + self.delta.load(Ordering::Relaxed) + 1.0f64)
51                % 2.0f64
52                - 1.0f64,
53            Ordering::Relaxed,
54        );
55
56        let mut output = Stream::new(self.channels);
57        output.fill(sample);
58        outputs.push(output);
59        Ok(())
60    }
61}