Skip to main content

dirtydata_runtime/nodes/
sources.rs

1use super::base::*;
2use dirtydata_core::types::ConfigSnapshot;
3use std::sync::Arc;
4use rand::prelude::*;
5use rand_pcg::Pcg32;
6
7pub struct OscillatorNode {
8    pub phase: f32,
9    pub freq_smooth: Option<SmoothedValue>,
10}
11
12impl OscillatorNode {
13    pub fn new() -> Self { Self { phase: 0.0, freq_smooth: None } }
14}
15
16impl DspNode for OscillatorNode {
17    fn process(&mut self, _inputs: &[f32], outputs: &mut [[f32; 2]], config: &ConfigSnapshot, ctx: &ProcessContext) {
18        let freq_target = config.get("frequency").and_then(|v| v.as_float()).unwrap_or(440.0) as f32;
19        let wave_type = config.get("waveform").and_then(|v| v.as_string());
20        let smooth = self.freq_smooth.get_or_insert_with(|| SmoothedValue::new(freq_target, ctx.sample_rate, 10.0));
21        let freq = smooth.next();
22        let phase_inc = freq / ctx.sample_rate;
23        let val = match wave_type.map(|s| s.as_str()).unwrap_or("sine") {
24            "sine" => (self.phase * 2.0 * std::f32::consts::PI).sin(),
25            "saw" => (self.phase * 2.0) - 1.0,
26            "square" => if self.phase < 0.5 { 1.0 } else { -1.0 },
27            _ => (self.phase * 2.0 * std::f32::consts::PI).sin(),
28        };
29        outputs[0] = [val, val];
30        self.phase = (self.phase + phase_inc) % 1.0;
31    }
32    fn update_parameter(&mut self, param: &str, value: f32) {
33        if param == "frequency" { if let Some(s) = &mut self.freq_smooth { s.set_target(value); } }
34    }
35    fn extract_state(&self) -> NodeState { 
36        NodeState::from_json(serde_json::json!({ "phase": self.phase })) 
37    }
38    fn inject_state(&mut self, state: &NodeState) {
39        if let Some(data) = state.to_json::<serde_json::Value>() {
40            if let Some(p) = data.get("phase").and_then(|v| v.as_f64()) {
41                self.phase = p as f32;
42            }
43        }
44    }
45}
46
47pub struct NoiseNode {
48    rng: Pcg32,
49}
50
51impl NoiseNode {
52    pub fn new(seed: u64) -> Self { Self { rng: Pcg32::seed_from_u64(seed) } }
53}
54
55impl DspNode for NoiseNode {
56    fn process(&mut self, _inputs: &[f32], outputs: &mut [[f32; 2]], _config: &ConfigSnapshot, _ctx: &ProcessContext) {
57        let val: f32 = self.rng.gen_range(-1.0..1.0);
58        outputs[0] = [val, val];
59    }
60    fn extract_state(&self) -> NodeState { NodeState::Empty }
61    fn inject_state(&mut self, _state: &NodeState) {}
62}
63
64pub struct AssetReaderNode {
65    data: Arc<Vec<f32>>,
66    cursor: usize,
67}
68
69impl AssetReaderNode {
70    pub fn new(data: Arc<Vec<f32>>) -> Self { Self { data, cursor: 0 } }
71}
72
73impl DspNode for AssetReaderNode {
74    fn process(&mut self, _inputs: &[f32], outputs: &mut [[f32; 2]], _config: &ConfigSnapshot, _ctx: &ProcessContext) {
75        if self.cursor + 1 < self.data.len() {
76            outputs[0] = [self.data[self.cursor], self.data[self.cursor+1]];
77            self.cursor += 2;
78        } else {
79            outputs[0] = [0.0, 0.0];
80        }
81    }
82    fn extract_state(&self) -> NodeState {
83        NodeState::from_json(self.cursor)
84    }
85    fn inject_state(&mut self, state: &NodeState) {
86        if let Some(cursor) = state.to_json::<usize>() {
87            self.cursor = cursor;
88        }
89    }
90}
91
92pub struct MidiInNode {
93    _rx: crossbeam_channel::Receiver<crate::nodes::MidiEvent>,
94}
95
96impl MidiInNode {
97    pub fn new(rx: crossbeam_channel::Receiver<crate::nodes::MidiEvent>) -> Self { Self { _rx: rx } }
98}
99
100impl DspNode for MidiInNode {
101    fn process(&mut self, _inputs: &[f32], outputs: &mut [[f32; 2]], _config: &ConfigSnapshot, _ctx: &ProcessContext) {
102        // Just a stub for now
103        outputs[0] = [0.0, 0.0];
104    }
105}