craydate/sound/
audio_sample.rs1use alloc::vec::Vec;
2use core::mem::MaybeUninit;
3use core::ptr::NonNull;
4
5use crate::capi_state::CApiState;
6use crate::ctypes::*;
7use crate::null_terminated::ToNullTerminatedString;
8use crate::time::TimeTicks;
9
10#[derive(Debug)]
13pub struct AudioSample {
14  ptr: NonNull<CAudioSample>,
15  data: Vec<u8>,
16}
17impl AudioSample {
18  pub(crate) fn from_ptr(ptr: *mut CAudioSample) -> AudioSample {
19    AudioSample {
20      ptr: NonNull::new(ptr).unwrap(),
21      data: Vec::new(),
22    }
23  }
24
25  pub fn with_bytes(bytes: usize) -> Self {
28    let ptr = unsafe { Self::fns().newSampleBuffer.unwrap()(bytes as i32) };
29    Self::from_ptr(ptr)
30  }
31
32  pub fn from_file(path: &str) -> Option<AudioSample> {
35    let ptr = unsafe { Self::fns().load.unwrap()(path.to_null_terminated_utf8().as_ptr()) };
36    if ptr.is_null() {
37      None
38    } else {
39      Some(Self::from_ptr(ptr))
40    }
41  }
42
43  pub fn from_vec(data: Vec<u8>, format: SoundFormat, sample_rate: u32) -> AudioSample {
47    assert!(
48      format == SoundFormat::kSound8bitMono
49        || format == SoundFormat::kSound8bitStereo
50        || format == SoundFormat::kSound16bitMono
51        || format == SoundFormat::kSound16bitStereo
52        || format == SoundFormat::kSoundADPCMMono
53        || format == SoundFormat::kSound16bitStereo
54    );
55    let ptr = unsafe {
56      Self::fns().newSampleFromData.unwrap()(
57        data.as_ptr() as *mut u8, format,
59        sample_rate,
60        data.len() as i32,
61      )
62    };
63    let mut sample = Self::from_ptr(ptr);
64    sample.data = data;
65    sample
66  }
67
68  pub fn from_slice(data: &[u8], format: SoundFormat, sample_rate: u32) -> AudioSample {
72    assert!(
73      format == SoundFormat::kSound8bitMono
74        || format == SoundFormat::kSound8bitStereo
75        || format == SoundFormat::kSound16bitMono
76        || format == SoundFormat::kSound16bitStereo
77        || format == SoundFormat::kSoundADPCMMono
78        || format == SoundFormat::kSound16bitStereo
79    );
80    let ptr = unsafe {
81      Self::fns().newSampleFromData.unwrap()(
82        data.as_ptr() as *mut u8, format,
84        sample_rate,
85        data.len() as i32,
86      )
87    };
88    let mut sample = Self::from_ptr(ptr);
89    sample.data.reserve(data.len());
90    sample.data.extend(data.iter());
91    sample
92  }
93  pub fn load_file(&mut self, path: &str) {
95    unsafe {
96      Self::fns().loadIntoSample.unwrap()(self.cptr_mut(), path.to_null_terminated_utf8().as_ptr())
97    };
98  }
99
100  pub fn len(&self) -> TimeTicks {
102    TimeTicks::from_seconds_lossy(unsafe { Self::fns().getLength.unwrap()(self.cptr() as *mut _) })
104  }
105
106  fn all_data(&self) -> (*mut u8, SoundFormat, u32, u32) {
107    let mut ptr = MaybeUninit::uninit();
108    let mut format = MaybeUninit::uninit();
109    let mut sample_rate = MaybeUninit::uninit();
110    let mut bytes = MaybeUninit::uninit();
111    unsafe {
112    Self::fns().getData.unwrap()(
114        self.cptr() as *mut _,
115        ptr.as_mut_ptr(),
116        format.as_mut_ptr(),
117        sample_rate.as_mut_ptr(),
118        bytes.as_mut_ptr(),
119      )
120    };
121    unsafe {
122      (
123        ptr.assume_init(),
124        format.assume_init(),
125        sample_rate.assume_init(),
126        bytes.assume_init(),
127      )
128    }
129  }
130
131  pub fn data(&self) -> &[u8] {
135    let (ptr, _, _, bytes) = self.all_data();
136    unsafe { core::slice::from_raw_parts(ptr, bytes as usize) }
137  }
138
139  pub fn sound_format(&self) -> SoundFormat {
141    let (_, format, _, _) = self.all_data();
142    format
143  }
144  pub fn sample_rate(&self) -> u32 {
146    let (_, _, sample_rate, _) = self.all_data();
147    sample_rate
148  }
149
150  pub(crate) fn cptr(&self) -> *const CAudioSample {
151    self.ptr.as_ptr()
152  }
153  pub(crate) fn cptr_mut(&mut self) -> *mut CAudioSample {
154    self.ptr.as_ptr()
155  }
156  pub(crate) fn fns() -> &'static craydate_sys::playdate_sound_sample {
157    unsafe { &*CApiState::get().csound.sample }
158  }
159}
160
161impl Drop for AudioSample {
162  fn drop(&mut self) {
163    unsafe { Self::fns().freeSample.unwrap()(self.cptr_mut()) }
165  }
166}