Skip to main content

mittens_engine/engine/ecs/component/
audio_oscillator.rs

1use super::Component;
2use crate::engine::ecs::ComponentId;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
5#[serde(rename_all = "lowercase")]
6pub enum OscillatorType {
7    Sin,
8    Triangle,
9    Square,
10    #[serde(rename = "square_3")]
11    Square3,
12    Drum,
13    Saw,
14    Noise,
15}
16
17#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
18pub struct AudioOscillator {
19    #[serde(rename = "type")]
20    pub oscillator_type: OscillatorType,
21    pub frequency: f32,
22    pub amplitude: f32,
23    pub enabled: bool,
24}
25
26impl AudioOscillator {
27    pub fn new(oscillator_type: OscillatorType) -> Self {
28        Self {
29            oscillator_type,
30            ..Self::default()
31        }
32    }
33
34    pub fn sin() -> Self {
35        Self::new(OscillatorType::Sin)
36    }
37
38    pub fn triangle() -> Self {
39        Self::new(OscillatorType::Triangle)
40    }
41
42    pub fn square() -> Self {
43        Self::new(OscillatorType::Square)
44    }
45
46    pub fn saw() -> Self {
47        Self::new(OscillatorType::Saw)
48    }
49
50    pub fn noise() -> Self {
51        Self::new(OscillatorType::Noise)
52    }
53
54    pub fn drum() -> Self {
55        Self::new(OscillatorType::Drum)
56    }
57
58    /// Builder-style: set oscillator frequency in Hz.
59    pub fn with_frequency(mut self, frequency_hz: f32) -> Self {
60        self.frequency = frequency_hz;
61        self
62    }
63
64    /// Builder-style: set amplitude (linear 0..1-ish).
65    pub fn with_amplitude(mut self, amplitude: f32) -> Self {
66        self.amplitude = amplitude;
67        self
68    }
69
70    /// Builder-style: set enabled state.
71    pub fn with_enabled(mut self, enabled: bool) -> Self {
72        self.enabled = enabled;
73        self
74    }
75}
76
77impl Default for AudioOscillator {
78    fn default() -> Self {
79        Self {
80            oscillator_type: OscillatorType::Sin,
81            frequency: 440.0,
82            amplitude: 0.2,
83            enabled: true,
84        }
85    }
86}
87
88#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
89pub struct AudioOscillatorComponent {
90    pub oscillators: Vec<AudioOscillator>,
91
92    #[serde(skip)]
93    component: Option<ComponentId>,
94}
95
96impl AudioOscillatorComponent {
97    pub fn new(oscillators: Vec<AudioOscillator>) -> Self {
98        Self {
99            oscillators,
100            component: None,
101        }
102    }
103
104    pub fn single(osc: AudioOscillator) -> Self {
105        Self::new(vec![osc])
106    }
107
108    pub fn id(&self) -> Option<ComponentId> {
109        self.component
110    }
111}
112
113impl Default for AudioOscillatorComponent {
114    fn default() -> Self {
115        Self::new(vec![AudioOscillator::default()])
116    }
117}
118
119impl Component for AudioOscillatorComponent {
120    fn set_id(&mut self, component: ComponentId) {
121        self.component = Some(component);
122    }
123
124    fn name(&self) -> &'static str {
125        "audio_oscillator"
126    }
127
128    fn init(&mut self, emit: &mut dyn crate::engine::ecs::SignalEmitter, component: ComponentId) {
129        emit.push_intent_now(
130            component,
131            crate::engine::ecs::IntentValue::RegisterAudioOscillator {
132                component_ids: vec![component],
133            },
134        );
135        emit.push_intent_now(
136            component,
137            crate::engine::ecs::IntentValue::AudioGraphDirtyImmediate {
138                component_ids: vec![component],
139            },
140        );
141    }
142
143    fn as_any(&self) -> &dyn std::any::Any {
144        self
145    }
146
147    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
148        self
149    }
150
151    fn encode(&self) -> std::collections::HashMap<String, serde_json::Value> {
152        let mut map = std::collections::HashMap::new();
153        map.insert(
154            "oscillators".to_string(),
155            serde_json::to_value(&self.oscillators).unwrap_or_else(|_| serde_json::json!([])),
156        );
157        map
158    }
159
160    fn decode(
161        &mut self,
162        data: &std::collections::HashMap<String, serde_json::Value>,
163    ) -> Result<(), String> {
164        if let Some(v) = data.get("oscillators") {
165            self.oscillators = serde_json::from_value(v.clone())
166                .map_err(|e| format!("Failed to decode oscillators: {}", e))?;
167        }
168        Ok(())
169    }
170}