1use std::collections::hash_map::Entry;
2
3use crate::*;
4
5pub fn play_sound_ex(id: &str, params: PlaySoundParams) {
6 play_sound_id_ex(sound_id(id), params);
7}
8
9pub fn play_sound_id_ex(sound: Sound, _params: PlaySoundParams) {
10 play_sound_id(sound);
11}
12
13pub fn play_music_id_ex(sound: Sound, params: PlaySoundParams) {
14 if params.looped {
15 println!("looped music not supported yet");
17 }
18 play_sound_id(sound);
19}
20
21pub fn play_sound(id: &str) {
22 play_sound_id(sound_id(id));
23}
24
25pub fn play_voice(id: &str) {
26 play_sound_id(sound_id(id));
27}
28
29pub fn play_random_sound_ex(
30 base_id: &str,
31 amount: i32,
32 settings: StaticSoundSettings,
33) {
34 let mut assets = ASSETS.borrow_mut();
35 let id = format!("{}-{}", base_id, gen_range(1, amount + 1));
36
37 AudioSystem::play_sound(
38 &mut assets,
39 sound_id(&id),
40 Some(settings),
41 AudioTrack::None,
42 );
43}
44
45pub fn play_random_sound(base_id: &str, amount: i32) {
46 let id = format!("{}-{}", base_id, gen_range(1, amount + 1));
47 play_sound_id(sound_id(&id));
48}
49
50pub fn play_music(id: &str) {
51 play_sound_id(sound_id(id));
52}
53
54pub fn play_sound_id(sound: Sound) {
55 GLOBAL_STATE.borrow_mut().play_sound_queue.push(sound);
56}
57
58pub fn stop_sound(sound: &str) {
59 stop_sound_id(sound_id(sound));
60}
61
62pub fn stop_sound_id(sound: Sound) {
63 GLOBAL_STATE.borrow_mut().stop_sound_queue.push(sound);
64}
65
66
67#[derive(Copy, Clone, Debug, Default)]
68pub struct PlaySoundParams {
69 pub looped: bool,
70}
71
72pub struct PlaySoundCommand {
73 pub sound: Sound,
74 pub settings: StaticSoundSettings,
75}
76
77thread_local! {
78 pub static AUDIO_SYSTEM: Lazy<RefCell<AudioSystem>> =
79 Lazy::new(|| RefCell::new(AudioSystem::new()));
80}
81
82pub fn change_master_volume(change: f64) {
83 AUDIO_SYSTEM.with(|audio| {
84 if let Some(system) = audio.borrow_mut().system.as_mut() {
85 system.master_volume =
86 (system.master_volume + change).clamp(0.0, 1.0);
87
88 system
89 .master_track
90 .set_volume(
93 Volume::Amplitude(system.master_volume),
94 kira::tween::Tween::default(),
95 )
96 .unwrap();
97 }
98 });
99}
100
101pub fn set_master_volume(value: f64) {
102 AUDIO_SYSTEM.with(|audio| {
103 if let Some(system) = audio.borrow_mut().system.as_mut() {
104 system.master_volume = value.clamp(0.0, 1.0);
105
106 system
107 .master_track
108 .set_volume(
111 Volume::Amplitude(system.master_volume),
112 kira::tween::Tween::default(),
113 )
114 .unwrap();
115 }
116 });
117}
118
119pub fn master_volume() -> f64 {
120 AUDIO_SYSTEM.with(|audio| {
121 if let Some(system) = audio.borrow_mut().system.as_ref() {
122 system.master_volume
123 } else {
124 0.0
125 }
126 })
127}
128
129
130pub enum AudioTrack {
131 None,
132 Filter,
133}
134
135pub struct AudioSystemImpl {
136 pub manager: AudioManager,
137 pub master_track: TrackHandle,
138 pub filter_track: TrackHandle,
139 pub filter_handle: FilterHandle,
140
141 pub master_volume: f64,
142}
143
144impl AudioSystemImpl {
145 pub fn new(mut manager: AudioManager) -> Self {
146 let mut builder = TrackBuilder::new();
147 let filter_handle =
148 builder.add_effect(FilterBuilder::new().cutoff(100.0));
149
150 let filter_track =
153 manager.add_sub_track(builder).expect("Failed to add filter track");
154
155 let master_track = manager
156 .add_sub_track(TrackBuilder::new())
157 .expect("Failed to add master track");
158
159 Self {
160 manager,
161 master_track,
162 filter_track,
163 filter_handle,
164 master_volume: 1.0,
165 }
166 }
167
168 pub fn play_sound(
169 &mut self,
170 assets: &mut Assets,
171 sound: Sound,
172 settings: Option<StaticSoundSettings>,
173 track: AudioTrack,
174 ) {
176 let sounds = assets.sounds.lock();
178
179 if let Some(mut sound_data) = sounds.get(&sound).cloned() {
180 if let Some(_settings) = settings {
182 match track {
183 AudioTrack::None => {}
184 AudioTrack::Filter => {
185 sound_data.settings = sound_data
186 .settings
187 .output_destination(&self.filter_track);
188 }
189 }
190 } else {
191 sound_data.settings =
192 sound_data.settings.output_destination(&self.master_track);
193 }
194
195 sound_data.settings =
196 sound_data.settings.output_destination(&self.master_track);
197
198 match self.manager.play(sound_data) {
199 Ok(handle) => {
200 match assets.sound_handles.entry(sound) {
201 Entry::Occupied(mut entry) => {
202 entry
203 .get_mut()
204 .stop(kira::tween::Tween::default())
205 .log_err();
206
207 entry.insert(handle);
208 }
209 Entry::Vacant(entry) => {
210 entry.insert(handle);
211 }
212 }
213 }
214 Err(err) => {
215 error!("Failed to play sound: {:?}", err);
216 }
217 }
218 } else {
219 error!("No sound data for {:?}", sound);
220 }
221 }
222
223 pub fn process_sounds(&mut self) {}
224}
225
226pub struct AudioSystem {
227 pub system: Option<AudioSystemImpl>,
228}
229
230impl AudioSystem {
231 pub fn new() -> Self {
232 let manager =
234 AudioManager::<kira::manager::backend::cpal::CpalBackend>::new(
235 AudioManagerSettings::default(),
236 )
237 .map_err(|err| {
238 error!("Failed to initialize audio manager: {:?}", err);
239 err
240 })
241 .ok();
242
243 let system = manager.map(AudioSystemImpl::new);
244
245 Self { system }
246 }
247
248 pub fn process_sounds() {
249 let _span = span!("process_sounds");
250
251 let mut assets = ASSETS.borrow_mut();
252
253 let stop_sound_queue =
254 GLOBAL_STATE.borrow_mut().stop_sound_queue.drain(..).collect_vec();
255
256 for sound in stop_sound_queue {
257 match assets.sound_handles.entry(sound) {
258 Entry::Occupied(mut entry) => {
259 entry
260 .get_mut()
261 .stop(kira::tween::Tween::default())
262 .log_err();
263 entry.remove();
264 }
265 Entry::Vacant(_) => {}
266 }
267 }
268
269 let play_sound_queue =
270 GLOBAL_STATE.borrow_mut().play_sound_queue.drain(..).collect_vec();
271
272 for sound in play_sound_queue {
273 AudioSystem::play_sound(&mut assets, sound, None, AudioTrack::None);
274 }
275 }
276
277 pub fn play_sound(
278 assets: &mut Assets,
279 sound: Sound,
280 settings: Option<StaticSoundSettings>,
281 track: AudioTrack,
282 ) {
283 AUDIO_SYSTEM.with(|audio| {
284 if let Some(system) = audio.borrow_mut().system.as_mut() {
285 system.play_sound(assets, sound, settings, track);
286 }
287 });
288 }
289}