dirtydata_runtime/nodes/
sources.rs1use 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 outputs[0] = [0.0, 0.0];
104 }
105}