1use std::mem::MaybeUninit;
2use std::os::raw::{c_int, c_void};
3use std::ptr::null_mut;
4use std::slice;
5use std::sync::Arc;
6
7use parking_lot::Mutex;
8
9use crate::platform::platform;
10use crate::sdl2_sys::*;
11
12pub trait AudioCallback {
13 fn update(&mut self, out: &mut [i16]);
14}
15
16extern "C" fn c_audio_callback(userdata: *mut c_void, stream: *mut u8, len: c_int) {
17 let audio_callback = unsafe { &*userdata.cast::<Arc<Mutex<dyn AudioCallback>>>() };
18 let stream: &mut [i16] =
19 unsafe { slice::from_raw_parts_mut(stream.cast::<i16>(), len as usize / 2) };
20 audio_callback.lock().update(stream);
21}
22
23pub fn start_audio(
24 sample_rate: u32,
25 buffer_size: u32,
26 audio_callback: Arc<Mutex<dyn AudioCallback>>,
27) {
28 let userdata = Box::into_raw(Box::new(audio_callback)).cast();
29 let desired = SDL_AudioSpec {
30 freq: sample_rate as i32,
31 format: AUDIO_S16 as u16,
32 channels: 1,
33 silence: 0,
34 samples: buffer_size as u16,
35 padding: 0,
36 size: 0,
37 callback: Some(c_audio_callback),
38 userdata,
39 };
40
41 let mut obtained = MaybeUninit::uninit();
42 platform().audio_device_id =
43 unsafe { SDL_OpenAudioDevice(null_mut(), 0, &raw const desired, obtained.as_mut_ptr(), 0) };
44
45 if platform().audio_device_id == 0 {
46 println!("Failed to initialize audio device");
47 }
48
49 set_audio_enabled(true);
50}
51
52pub fn set_audio_enabled(enabled: bool) {
53 let pause_on = i32::from(!enabled);
54 let audio_device_id = platform().audio_device_id;
55
56 if audio_device_id != 0 {
57 unsafe {
58 SDL_PauseAudioDevice(audio_device_id, pause_on);
59 }
60 }
61}