pyxel_platform/
audio.rs

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}