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    num_channels: u8,
26    num_samples: u16,
27    audio_callback: Arc<Mutex<dyn AudioCallback>>,
28) {
29    let userdata = Box::into_raw(Box::new(audio_callback)).cast();
30
31    let desired = SDL_AudioSpec {
32        freq: sample_rate as i32,
33        format: AUDIO_S16 as u16,
34        channels: num_channels,
35        silence: 0,
36        samples: num_samples,
37        padding: 0,
38        size: 0,
39        callback: Some(c_audio_callback),
40        userdata,
41    };
42
43    let mut obtained = MaybeUninit::uninit();
44    platform().audio_device_id =
45        unsafe { SDL_OpenAudioDevice(null_mut(), 0, &desired, obtained.as_mut_ptr(), 0) };
46
47    if platform().audio_device_id == 0 {
48        println!("Failed to initialize audio device");
49    }
50
51    set_audio_enabled(true);
52}
53
54pub fn set_audio_enabled(enabled: bool) {
55    let pause_on = i32::from(!enabled);
56    let audio_device_id = platform().audio_device_id;
57
58    if audio_device_id != 0 {
59        unsafe {
60            SDL_PauseAudioDevice(audio_device_id, pause_on);
61        }
62    }
63}