1use super::*;
2
3impl GameAudioContext {
5 pub fn create() -> Option<GameAudioContext> {
12 let Ok(context) = AudioContext::new() else {
13 return None;
14 };
15 let Ok(master_gain) = context.create_gain() else {
16 return None;
17 };
18 let _: Result<AudioNode, JsValue> =
19 master_gain.connect_with_audio_node(&context.destination());
20 master_gain.gain().set_value(AUDIO_DEFAULT_VOLUME as f32);
21 Some(GameAudioContext::new(
22 context,
23 master_gain,
24 AUDIO_DEFAULT_VOLUME,
25 ))
26 }
27
28 pub fn apply_master_volume(&self, volume: f64) {
34 let clamped: f64 = Numeric::clamp(volume, 0.0, 1.0);
35 self.get_master_gain().gain().set_value(clamped as f32);
36 }
37
38 pub fn resume(&self) {
40 let _: Result<Promise, JsValue> = self.get_context().resume();
41 }
42
43 pub fn suspend(&self) {
45 let _: Result<Promise, JsValue> = self.get_context().suspend();
46 }
47
48 pub fn close(&self) {
50 let _: Result<Promise, JsValue> = self.get_context().close();
51 }
52
53 pub fn sample_rate(&self) -> f64 {
59 self.get_context().sample_rate() as f64
60 }
61
62 pub fn current_time(&self) -> f64 {
68 self.get_context().current_time()
69 }
70}
71
72impl AudioClip {
74 pub fn create(buffer: AudioBuffer, name: String) -> AudioClip {
85 AudioClip::new(
86 buffer,
87 name,
88 AudioPlayState::Stopped,
89 AUDIO_DEFAULT_LOOP,
90 AUDIO_DEFAULT_VOLUME,
91 AUDIO_DEFAULT_PLAYBACK_RATE,
92 )
93 }
94
95 pub fn play(&mut self, audio_context: &GameAudioContext) {
104 if self.get_state() == AudioPlayState::Playing {
105 return;
106 }
107 let Ok(source) = audio_context.get_context().create_buffer_source() else {
108 return;
109 };
110 source.set_buffer(Some(self.get_buffer()));
111 source.set_loop(self.get_looping());
112 source
113 .playback_rate()
114 .set_value(self.get_playback_rate() as f32);
115 let Ok(gain) = audio_context.get_context().create_gain() else {
116 return;
117 };
118 gain.gain().set_value(self.get_volume() as f32);
119 let _: Result<AudioNode, JsValue> = source.connect_with_audio_node(&gain);
120 let _: Result<AudioNode, JsValue> =
121 gain.connect_with_audio_node(audio_context.get_master_gain());
122 let _: Result<(), JsValue> = source.start();
123 self.set_source_node(Some(source));
124 self.set_state(AudioPlayState::Playing);
125 }
126
127 pub fn stop(&mut self) {
129 if let Some(source) = self.get_mut_source_node().take() {
130 let scheduled: &AudioScheduledSourceNode = source.as_ref();
131 let _: Result<(), JsValue> = scheduled.stop_with_when(0.0);
132 let _: Result<(), JsValue> = source.disconnect();
133 }
134 self.set_state(AudioPlayState::Stopped);
135 }
136
137 pub fn update_looping(&mut self, looping: bool) {
143 self.set_looping(looping);
144 if let Some(source) = self.get_mut_source_node() {
145 source.set_loop(looping);
146 }
147 }
148
149 pub fn update_volume(&mut self, volume: f64) {
155 self.set_volume(Numeric::clamp(volume, 0.0, 1.0));
156 }
157
158 pub fn update_playback_rate(&mut self, rate: f64) {
164 self.set_playback_rate(rate);
165 if let Some(source) = self.get_mut_source_node() {
166 source.playback_rate().set_value(rate as f32);
167 }
168 }
169
170 pub fn duration(&self) -> f64 {
176 self.get_buffer().duration()
177 }
178
179 pub fn channel_count(&self) -> u32 {
185 self.get_buffer().number_of_channels()
186 }
187}