Skip to main content

macroquad_ply/
audio.rs

1//! Loading and playing sounds.
2
3#![allow(dead_code)]
4
5use crate::{file::load_file, get_context, Error};
6use std::sync::Arc;
7
8#[cfg(feature = "audio")]
9use quad_snd::{AudioContext as QuadSndContext, Sound as QuadSndSound};
10
11#[cfg(feature = "audio")]
12pub use quad_snd::PlaySoundParams;
13
14#[cfg(not(feature = "audio"))]
15mod dummy_audio {
16    use crate::audio::PlaySoundParams;
17
18    pub struct AudioContext {}
19
20    impl AudioContext {
21        pub fn new() -> AudioContext {
22            AudioContext {}
23        }
24
25        #[cfg(target_os = "android")]
26        pub fn pause(&mut self) {}
27
28        #[cfg(target_os = "android")]
29        pub fn resume(&mut self) {}
30    }
31
32    pub struct Sound {}
33
34    impl Sound {
35        pub fn load(_ctx: &mut AudioContext, _data: &[u8]) -> Sound {
36            Sound {}
37        }
38
39        pub fn play(&self, _ctx: &mut AudioContext, _params: PlaySoundParams) {
40            eprintln!("warn: macroquad's \"audio\" feature disabled.");
41        }
42
43        pub fn stop(&self, _ctx: &mut AudioContext) {}
44
45        pub fn set_volume(&self, _ctx: &mut AudioContext, _volume: f32) {}
46
47        #[allow(dead_code)]
48        pub fn is_loaded(&self) -> bool {
49            true
50        }
51
52        pub fn delete(&self, _ctx: &AudioContext) {}
53    }
54}
55
56#[cfg(not(feature = "audio"))]
57use dummy_audio::{AudioContext as QuadSndContext, Sound as QuadSndSound};
58
59#[cfg(not(feature = "audio"))]
60pub struct PlaySoundParams {
61    pub looped: bool,
62    pub volume: f32,
63}
64
65pub struct AudioContext {
66    native_ctx: QuadSndContext,
67}
68
69impl AudioContext {
70    pub fn new() -> AudioContext {
71        AudioContext {
72            native_ctx: QuadSndContext::new(),
73        }
74    }
75
76    #[cfg(target_os = "android")]
77    pub fn pause(&mut self) {
78        self.native_ctx.pause()
79    }
80
81    #[cfg(target_os = "android")]
82    pub fn resume(&mut self) {
83        self.native_ctx.resume()
84    }
85}
86
87struct QuadSndSoundGuarded(QuadSndSound);
88
89impl Drop for QuadSndSoundGuarded {
90    fn drop(&mut self) {
91        let ctx = &get_context().audio_context;
92        self.0.delete(&ctx.native_ctx);
93    }
94}
95
96#[derive(Clone)]
97pub struct Sound(Arc<QuadSndSoundGuarded>);
98
99impl std::fmt::Debug for Sound {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        f.debug_struct("Sound").finish()
102    }
103}
104
105/// Load audio file.
106///
107/// Attempts to automatically detect the format of the source of data.
108
109pub async fn load_sound(path: &str) -> Result<Sound, Error> {
110    let data = load_file(path).await?;
111
112    load_sound_from_bytes(&data).await
113}
114
115/// Load audio data.
116///
117/// Attempts to automatically detect the format of the source of data.
118pub async fn load_sound_from_bytes(data: &[u8]) -> Result<Sound, Error> {
119    let sound = {
120        let ctx = &mut get_context().audio_context;
121        QuadSndSound::load(&mut ctx.native_ctx, data)
122    };
123
124    // only on wasm the sound is not ready right away
125    #[cfg(target_arch = "wasm32")]
126    while sound.is_loaded() == false {
127        crate::window::next_frame().await;
128    }
129
130    Ok(Sound(Arc::new(QuadSndSoundGuarded(sound))))
131}
132
133pub fn play_sound_once(sound: &Sound) {
134    let ctx = &mut get_context().audio_context;
135
136    sound.0 .0.play(
137        &mut ctx.native_ctx,
138        PlaySoundParams {
139            looped: false,
140            volume: 1.0,
141        },
142    );
143}
144
145pub fn play_sound(sound: &Sound, params: PlaySoundParams) {
146    let ctx = &mut get_context().audio_context;
147    sound.0 .0.play(&mut ctx.native_ctx, params);
148}
149
150pub fn stop_sound(sound: &Sound) {
151    let ctx = &mut get_context().audio_context;
152    sound.0 .0.stop(&mut ctx.native_ctx);
153}
154
155pub fn set_sound_volume(sound: &Sound, volume: f32) {
156    let ctx = &mut get_context().audio_context;
157    sound.0 .0.set_volume(&mut ctx.native_ctx, volume);
158}