dbsdk_rs/
audio.rs

1use std::convert::TryInto;
2
3use 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};
4
5pub const VOICE_COUNT: usize = 32;
6
7#[repr(C)]
8#[derive(Clone)]
9pub struct AudioSample {
10    pub handle: i32,
11    pub samplerate: i32,
12}
13
14#[repr(C)]
15#[derive(Clone, Copy)]
16pub enum AudioVoiceParam {
17    Volume,
18    Pitch,
19    Detune,
20    Pan,
21    SampleData,
22    Samplerate,
23    LoopEnabled,
24    LoopStart,
25    LoopEnd,
26    Reverb,
27    FadeInDuration,
28    FadeOutDuration,
29    Start,
30    Stop,
31}
32
33impl AudioSample {
34    /// Create a new signed 8-bit PCM audio sample
35    pub fn create_s8(pcm_data: &[i8], samplerate: i32) -> Result<AudioSample,()> {
36        let handle = unsafe { audio_alloc(pcm_data.as_ptr().cast(), pcm_data.len().try_into().unwrap(), 0) };
37        if handle == -1 {
38            return Err(());
39        }
40
41        return Ok(AudioSample {
42            handle: handle,
43            samplerate: samplerate
44        });
45    }
46
47    /// Create a new signed 16-bit PCM audio sample
48    pub fn create_s16(pcm_data: &[i16], samplerate: i32) -> Result<AudioSample,()> {
49        let handle = unsafe { audio_alloc(pcm_data.as_ptr().cast(), (pcm_data.len() * 2).try_into().unwrap(), 1) };
50        if handle == -1 {
51            return Err(());
52        }
53
54        return Ok(AudioSample {
55            handle: handle,
56            samplerate: samplerate
57        });
58    }
59
60    /// Create a new IMA ADPCM encoded audio sample
61    pub fn create_adpcm(adpcm_data: &[u8], chunk_size: i32, samplerate: i32) -> Result<AudioSample,()> {
62        let handle = unsafe { audio_allocCompressed(adpcm_data.as_ptr().cast(), adpcm_data.len().try_into().unwrap(), chunk_size) };
63        if handle == -1 {
64            return Err(());
65        }
66
67        return Ok(AudioSample {
68            handle: handle,
69            samplerate: samplerate
70        });
71    }
72}
73
74impl Drop for AudioSample {
75    fn drop(&mut self) {
76        unsafe { audio_free(self.handle); }
77    }
78}
79
80/// Get the current sample memory usage in bytes
81pub fn get_usage() -> i32 {
82    unsafe { return audio_getUsage(); }
83}
84
85/// Schedule an audio voice integer parameter change at some point in the future
86pub fn queue_set_voice_param_i(slot: i32, param: AudioVoiceParam, value: i32, time: f64) {
87    assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to set parameter for invalid voice handle");
88    unsafe { audio_queueSetParam_i(slot, param, value, time); }
89}
90
91/// Schedule an audio voice float parameter change at some point in the future
92pub fn queue_set_voice_param_f(slot: i32, param: AudioVoiceParam, value: f32, time: f64) {
93    assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to set parameter for invalid voice handle");
94    unsafe { audio_queueSetParam_f(slot, param, value, time); }
95}
96
97/// Schedule an audio voice to start playing at some point in the future
98pub fn queue_start_voice(slot: i32, time: f64) {
99    assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to start invalid voice handle");
100    unsafe { audio_queueStartVoice(slot, time) };
101}
102
103/// Schedule an audio voice to stop playing at some point in the future
104pub fn queue_stop_voice(slot: i32, time: f64) {
105    assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to stop invalid voice handle");
106    unsafe { audio_queueStopVoice(slot, time) };
107}
108
109/// Gets whether the given voice is currently playing
110pub fn get_voice_state(slot: i32) -> bool {
111    assert!(slot >= 0 && slot < VOICE_COUNT.try_into().unwrap(), "Tried to get state of invalid voice handle");
112    unsafe { return audio_getVoiceState(slot) };
113}
114
115/// Get the current audio timer value for scheduling
116pub fn get_time() -> f64 {
117    unsafe { return audio_getTime(); }
118}
119
120/// Set the current reverb unit parameters
121pub fn set_reverb(room_size: f32, damping: f32, width: f32, wet: f32, dry: f32) {
122    unsafe { audio_setReverbParams(room_size, damping, width, wet, dry); }
123}
124
125/// Initialize the MIDI synth using the given soundfont data
126pub fn init_synth(sf2_data: &[u8]) -> Result<(),()> {
127    unsafe {
128        let result = audio_initSynth(sf2_data.as_ptr(), sf2_data.len().try_into().unwrap());
129        if result {
130            return Ok(());
131        } else {
132            return Err(());
133        }
134    }
135}
136
137/// Start playing a MIDI file using the initialized MIDI synth, optionally looping the file when it reaches the end
138pub fn play_midi(midi_data: &[u8], looping: bool) -> Result<(),()> {
139    unsafe {
140        let result = audio_playMidi(midi_data.as_ptr(), midi_data.len().try_into().unwrap(), looping);
141        if result {
142            return Ok(());
143        } else {
144            return Err(());
145        }
146    }
147}
148
149/// Set whether to route MIDI playback through the reverb unit
150pub fn set_midi_reverb(enabled: bool) {
151    unsafe { audio_setMidiReverb(enabled); }
152}
153
154/// Set the volume of MIDI playback
155pub fn set_midi_volume(volume: f32) {
156    unsafe { audio_setMidiVolume(volume); }
157}