use std::convert::TryInto;
use crate::db_internal::{audio_alloc, audio_allocCompressed, audio_free, audio_getUsage, audio_queueSetParam_i, audio_queueSetParam_f, audio_queueStartVoice, audio_queueStopVoice, audio_getVoiceState, audio_getTime, audio_setReverbParams, audio_initSynth, audio_playMidi, audio_setMidiReverb, audio_setMidiVolume};
pub const VOICE_COUNT: usize = 32;
#[repr(C)]
#[derive(Clone)]
pub struct AudioSample {
pub handle: i32,
pub samplerate: i32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub enum AudioVoiceParam {
Volume,
Pitch,
Detune,
Pan,
SampleData,
Samplerate,
LoopEnabled,
LoopStart,
LoopEnd,
Reverb,
FadeInDuration,
FadeOutDuration,
Start,
Stop,
}
impl AudioSample {
pub fn create_s8(pcm_data: &[i8], samplerate: i32) -> Result<AudioSample,()> {
let handle = unsafe { audio_alloc(pcm_data.as_ptr().cast(), pcm_data.len().try_into().unwrap(), 0) };
if handle == -1 {
return Err(());
}
return Ok(AudioSample {
handle: handle,
samplerate: samplerate
});
}
pub fn create_s16(pcm_data: &[i16], samplerate: i32) -> Result<AudioSample,()> {
let handle = unsafe { audio_alloc(pcm_data.as_ptr().cast(), (pcm_data.len() * 2).try_into().unwrap(), 1) };
if handle == -1 {
return Err(());
}
return Ok(AudioSample {
handle: handle,
samplerate: samplerate
});
}
pub fn create_adpcm(adpcm_data: &[u8], chunk_size: i32, samplerate: i32) -> Result<AudioSample,()> {
let handle = unsafe { audio_allocCompressed(adpcm_data.as_ptr().cast(), adpcm_data.len().try_into().unwrap(), chunk_size) };
if handle == -1 {
return Err(());
}
return Ok(AudioSample {
handle: handle,
samplerate: samplerate
});
}
}
impl Drop for AudioSample {
fn drop(&mut self) {
unsafe { audio_free(self.handle); }
}
}
pub fn get_usage() -> i32 {
unsafe { return audio_getUsage(); }
}
pub fn queue_set_voice_param_i(slot: i32, param: AudioVoiceParam, value: i32, time: f64) {
assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to set parameter for invalid voice handle");
unsafe { audio_queueSetParam_i(slot, param, value, time); }
}
pub fn queue_set_voice_param_f(slot: i32, param: AudioVoiceParam, value: f32, time: f64) {
assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to set parameter for invalid voice handle");
unsafe { audio_queueSetParam_f(slot, param, value, time); }
}
pub fn queue_start_voice(slot: i32, time: f64) {
assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to start invalid voice handle");
unsafe { audio_queueStartVoice(slot, time) };
}
pub fn queue_stop_voice(slot: i32, time: f64) {
assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to stop invalid voice handle");
unsafe { audio_queueStopVoice(slot, time) };
}
pub fn get_voice_state(slot: i32) -> bool {
assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to get state of invalid voice handle");
unsafe { return audio_getVoiceState(slot) };
}
pub fn get_time() -> f64 {
unsafe { return audio_getTime(); }
}
pub fn set_reverb(room_size: f32, damping: f32, width: f32, wet: f32, dry: f32) {
unsafe { audio_setReverbParams(room_size, damping, width, wet, dry); }
}
pub fn init_synth(sf2_data: &[u8]) -> Result<(),()> {
unsafe {
let result = audio_initSynth(sf2_data.as_ptr(), sf2_data.len().try_into().unwrap());
if result {
return Ok(());
} else {
return Err(());
}
}
}
pub fn play_midi(midi_data: &[u8], looping: bool) -> Result<(),()> {
unsafe {
let result = audio_playMidi(midi_data.as_ptr(), midi_data.len().try_into().unwrap(), looping);
if result {
return Ok(());
} else {
return Err(());
}
}
}
pub fn set_midi_reverb(enabled: bool) {
unsafe { audio_setMidiReverb(enabled); }
}
pub fn set_midi_volume(volume: f32) {
unsafe { audio_setMidiVolume(volume); }
}