use std::{ffi::CString, time::Duration};
use crate::ffi;
#[derive(Debug)]
pub struct AudioDevice(());
impl AudioDevice {
#[inline]
pub fn init() -> Option<Self> {
unsafe {
ffi::InitAudioDevice();
}
if unsafe { ffi::IsAudioDeviceReady() } {
Some(Self(()))
} else {
None
}
}
#[inline]
pub fn set_master_volume(&mut self, volume: f32) {
unsafe { ffi::SetMasterVolume(volume) }
}
}
impl Drop for AudioDevice {
#[inline]
fn drop(&mut self) {
unsafe { ffi::CloseAudioDevice() }
}
}
#[derive(Debug)]
pub struct Wave {
raw: ffi::Wave,
}
impl Wave {
#[inline]
pub fn frame_count(&self) -> u32 {
self.raw.frameCount
}
#[inline]
pub fn sample_rate(&self) -> u32 {
self.raw.sampleRate
}
#[inline]
pub fn sample_size(&self) -> u32 {
self.raw.sampleSize
}
#[inline]
pub fn channels(&self) -> u32 {
self.raw.channels
}
#[inline]
pub fn from_file(file_name: &str) -> Option<Self> {
let file_name = CString::new(file_name).unwrap();
let raw = unsafe { ffi::LoadWave(file_name.as_ptr()) };
if unsafe { ffi::IsWaveReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn from_memory(file_type: &str, file_data: &[u8]) -> Option<Self> {
let file_type = CString::new(file_type).unwrap();
let raw = unsafe {
ffi::LoadWaveFromMemory(file_type.as_ptr(), file_data.as_ptr(), file_data.len() as _)
};
if unsafe { ffi::IsWaveReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn export(&self, file_name: &str) -> bool {
let file_name = CString::new(file_name).unwrap();
unsafe { ffi::ExportWave(self.raw.clone(), file_name.as_ptr()) }
}
#[inline]
pub fn export_as_code(&self, file_name: &str) -> bool {
let file_name = CString::new(file_name).unwrap();
unsafe { ffi::ExportWaveAsCode(self.raw.clone(), file_name.as_ptr()) }
}
#[inline]
pub fn crop(&mut self, init_sample: u32, final_sample: u32) {
unsafe { ffi::WaveCrop(&mut self.raw as *mut _, init_sample as _, final_sample as _) }
}
#[inline]
pub fn convert_to_format(&mut self, sample_rate: u32, sample_size: u32, channels: u32) {
unsafe {
ffi::WaveFormat(
&mut self.raw as *mut _,
sample_rate as _,
sample_size as _,
channels as _,
)
}
}
#[inline]
pub fn load_samples(&self) -> Vec<f32> {
let samples = unsafe { ffi::LoadWaveSamples(self.raw.clone()) };
let mut vec = Vec::new();
let len = (self.frame_count() * self.channels()) as usize;
for i in 0..len {
vec.push(unsafe { samples.add(i).read() });
}
unsafe {
ffi::UnloadWaveSamples(samples);
}
vec
}
}
impl Clone for Wave {
#[inline]
fn clone(&self) -> Self {
Self {
raw: unsafe { ffi::WaveCopy(self.raw.clone()) },
}
}
}
impl Drop for Wave {
#[inline]
fn drop(&mut self) {
unsafe { ffi::UnloadWave(self.raw.clone()) }
}
}
#[derive(Debug)]
pub struct AudioStream {
raw: ffi::AudioStream,
}
impl AudioStream {
#[inline]
pub fn sample_rate(&self) -> u32 {
self.raw.sampleRate
}
#[inline]
pub fn sample_size(&self) -> u32 {
self.raw.sampleSize
}
#[inline]
pub fn channels(&self) -> u32 {
self.raw.channels
}
#[inline]
pub fn new(sample_rate: u32, sample_size: u32, channels: u32) -> Option<Self> {
let raw = unsafe { ffi::LoadAudioStream(sample_rate, sample_size, channels) };
if unsafe { ffi::IsAudioStreamReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn update(&mut self, data: &[u8], frame_count: u32) {
unsafe {
ffi::UpdateAudioStream(
self.raw.clone(),
data.as_ptr() as *const _,
frame_count as _,
)
}
}
#[inline]
pub fn is_processed(&self) -> bool {
unsafe { ffi::IsAudioStreamProcessed(self.raw.clone()) }
}
#[inline]
pub fn play(&self, _device: &mut AudioDevice) {
unsafe { ffi::PlayAudioStream(self.raw.clone()) }
}
#[inline]
pub fn pause(&self, _device: &mut AudioDevice) {
unsafe { ffi::PauseAudioStream(self.raw.clone()) }
}
#[inline]
pub fn resume(&self, _device: &mut AudioDevice) {
unsafe { ffi::ResumeAudioStream(self.raw.clone()) }
}
#[inline]
pub fn is_playing(&self, _device: &mut AudioDevice) -> bool {
unsafe { ffi::IsAudioStreamPlaying(self.raw.clone()) }
}
#[inline]
pub fn stop(&self, _device: &mut AudioDevice) {
unsafe { ffi::StopAudioStream(self.raw.clone()) }
}
#[inline]
pub fn set_volume(&self, volume: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetAudioStreamVolume(self.raw.clone(), volume) }
}
#[inline]
pub fn set_pitch(&self, pitch: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetAudioStreamPitch(self.raw.clone(), pitch) }
}
#[inline]
pub fn set_pan(&self, pan: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetAudioStreamPan(self.raw.clone(), pan) }
}
#[inline]
pub fn set_default_buffer_size(size: usize) {
unsafe { ffi::SetAudioStreamBufferSizeDefault(size as _) }
}
}
impl Drop for AudioStream {
#[inline]
fn drop(&mut self) {
unsafe { ffi::UnloadAudioStream(self.raw.clone()) }
}
}
#[derive(Debug)]
pub struct Sound {
raw: ffi::Sound,
}
impl Sound {
#[inline]
pub fn frame_count(&self) -> u32 {
self.raw.frameCount
}
#[inline]
pub fn from_file(filname: &str) -> Option<Self> {
let file_name = CString::new(filname).unwrap();
let raw = unsafe { ffi::LoadSound(file_name.as_ptr()) };
if unsafe { ffi::IsSoundReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn from_wave(wave: &Wave) -> Option<Self> {
let raw = unsafe { ffi::LoadSoundFromWave(wave.raw.clone()) };
if unsafe { ffi::IsSoundReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn update(&mut self, data: &[u8], sample_count: u32) {
unsafe {
ffi::UpdateSound(
self.raw.clone(),
data.as_ptr() as *const _,
sample_count as _,
)
}
}
#[inline]
pub fn play(&self, _device: &mut AudioDevice) {
unsafe { ffi::PlaySound(self.raw.clone()) }
}
#[inline]
pub fn stop(&self, _device: &mut AudioDevice) {
unsafe { ffi::StopSound(self.raw.clone()) }
}
#[inline]
pub fn pause(&self, _device: &mut AudioDevice) {
unsafe { ffi::PauseSound(self.raw.clone()) }
}
#[inline]
pub fn resume(&self, _device: &mut AudioDevice) {
unsafe { ffi::ResumeSound(self.raw.clone()) }
}
#[inline]
pub fn is_playing(&self, _device: &mut AudioDevice) -> bool {
unsafe { ffi::IsSoundPlaying(self.raw.clone()) }
}
#[inline]
pub fn set_volume(&self, volume: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetSoundVolume(self.raw.clone(), volume) }
}
#[inline]
pub fn set_pitch(&self, pitch: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetSoundPitch(self.raw.clone(), pitch) }
}
#[inline]
pub fn set_pan(&self, pan: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetSoundPan(self.raw.clone(), pan) }
}
}
impl Drop for Sound {
#[inline]
fn drop(&mut self) {
unsafe { ffi::UnloadSound(self.raw.clone()) }
}
}
#[derive(Debug)]
pub struct Music {
raw: ffi::Music,
}
impl Music {
#[inline]
pub fn frame_count(&self) -> u32 {
self.raw.frameCount
}
#[inline]
pub fn looping(&self) -> bool {
self.raw.looping
}
#[inline]
pub fn set_looping(&mut self, looping: bool) {
self.raw.looping = looping;
}
#[inline]
pub fn from_file(file_name: &str) -> Option<Self> {
let file_name = CString::new(file_name).unwrap();
let raw = unsafe { ffi::LoadMusicStream(file_name.as_ptr()) };
if unsafe { ffi::IsMusicReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn from_memory(file_type: &str, data: &[u8]) -> Option<Self> {
let file_type = CString::new(file_type).unwrap();
let raw = unsafe {
ffi::LoadMusicStreamFromMemory(file_type.as_ptr(), data.as_ptr(), data.len() as _)
};
if unsafe { ffi::IsMusicReady(raw.clone()) } {
Some(Self { raw })
} else {
None
}
}
#[inline]
pub fn play(&self, _device: &mut AudioDevice) {
unsafe { ffi::PlayMusicStream(self.raw.clone()) }
}
#[inline]
pub fn is_playing(&self, _device: &mut AudioDevice) -> bool {
unsafe { ffi::IsMusicStreamPlaying(self.raw.clone()) }
}
#[inline]
pub fn update(&self, _device: &mut AudioDevice) {
unsafe { ffi::UpdateMusicStream(self.raw.clone()) }
}
#[inline]
pub fn stop(&self, _device: &mut AudioDevice) {
unsafe { ffi::StopMusicStream(self.raw.clone()) }
}
#[inline]
pub fn pause(&self, _device: &mut AudioDevice) {
unsafe { ffi::PauseMusicStream(self.raw.clone()) }
}
#[inline]
pub fn resume(&self, _device: &mut AudioDevice) {
unsafe { ffi::ResumeMusicStream(self.raw.clone()) }
}
#[inline]
pub fn seek(&self, position: Duration, _device: &mut AudioDevice) {
unsafe { ffi::SeekMusicStream(self.raw.clone(), position.as_secs_f32()) }
}
#[inline]
pub fn set_volume(&self, volume: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetMusicVolume(self.raw.clone(), volume) }
}
#[inline]
pub fn set_pitch(&self, pitch: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetMusicPitch(self.raw.clone(), pitch) }
}
#[inline]
pub fn set_pan(&self, pan: f32, _device: &mut AudioDevice) {
unsafe { ffi::SetMusicPan(self.raw.clone(), pan) }
}
#[inline]
pub fn get_time_length(&self, _device: &mut AudioDevice) -> Duration {
Duration::from_secs_f32(unsafe { ffi::GetMusicTimeLength(self.raw.clone()) })
}
#[inline]
pub fn get_time_played(&self, _device: &mut AudioDevice) -> Duration {
Duration::from_secs_f32(unsafe { ffi::GetMusicTimePlayed(self.raw.clone()) })
}
}
impl Drop for Music {
#[inline]
fn drop(&mut self) {
unsafe { ffi::UnloadMusicStream(self.raw.clone()) }
}
}