Skip to main content

dirtydata_runtime/nodes/
mod.rs

1pub mod base;
2pub use base::*;
3
4pub mod sources;
5pub use sources::*;
6
7pub mod processors;
8pub use processors::*;
9
10pub mod nonlinear;
11pub use nonlinear::*;
12
13pub mod destruction;
14pub use destruction::*;
15
16pub mod legacy;
17pub use legacy::MidiEvent;
18// pub use legacy::*; // Avoid glob export to prevent name collisions with base
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23    use legacy::EnvelopeNode;
24    use dirtydata_core::types::ConfigSnapshot;
25    use std::collections::BTreeMap;
26
27    fn dummy_ctx() -> ProcessContext<'static> {
28        ProcessContext {
29            sample_rate: 44100.0,
30            global_sample_index: 0,
31            crash_flag: None,
32            osc_tx: None,
33            convergence_info: None,
34            node_diagnostics: None,
35            node_id: None,
36        }
37    }
38
39    #[test]
40    fn test_oscillator_state_migration() {
41        let mut osc1 = OscillatorNode::new();
42        let mut outputs = [[0.0; 2]];
43        let config = ConfigSnapshot::new();
44        let ctx = dummy_ctx();
45
46        // 1. Run for a bit to move phase
47        for _ in 0..100 {
48            osc1.process(&[], &mut outputs, &config, &ctx);
49        }
50        let phase1 = osc1.phase;
51        assert!(phase1 > 0.0);
52
53        // 2. Extract state
54        let state = osc1.extract_state();
55
56        // 3. Inject into new node
57        let mut osc2 = OscillatorNode::new();
58        osc2.inject_state(&state);
59
60        // 4. Verify phase is restored
61        assert_eq!(osc1.phase, osc2.phase);
62        
63        // 5. Verify next sample matches
64        osc1.process(&[], &mut outputs, &config, &ctx);
65        let val1 = outputs[0][0];
66        osc2.process(&[], &mut outputs, &config, &ctx);
67        let val2 = outputs[0][0];
68        assert_eq!(val1, val2);
69    }
70
71    #[test]
72    fn test_envelope_state_migration() {
73        let mut env1 = EnvelopeNode::new();
74        let mut outputs = [[0.0; 2]];
75        let mut config = BTreeMap::new();
76        config.insert("attack".into(), dirtydata_core::types::ConfigValue::Float(0.1));
77        let snapshot = ConfigSnapshot::from(config);
78        let ctx = dummy_ctx();
79
80        // 1. Trigger and run into Attack phase
81        env1.process(&[1.0], &mut outputs, &snapshot, &ctx);
82        for _ in 0..10 {
83            env1.process(&[1.0], &mut outputs, &snapshot, &ctx);
84        }
85        assert!(env1.is_idle() == false);
86        let level1 = outputs[0][0];
87
88        // 2. Migrate
89        let state = env1.extract_state();
90        let mut env2 = EnvelopeNode::new();
91        env2.inject_state(&state);
92
93        // 3. Verify
94        env1.process(&[1.0], &mut outputs, &snapshot, &ctx);
95        let next_val1 = outputs[0][0];
96        env2.process(&[1.0], &mut outputs, &snapshot, &ctx);
97        let next_val2 = outputs[0][0];
98        
99        assert_eq!(level1, level1); // Just checking stability
100        assert_eq!(next_val1, next_val2);
101    }
102}