libdaw/nodes/
sawtooth_oscillator.rs1use 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 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}