Merge pull request #275 from drbawb/feature/fix-audio-cvt

Restore the AudioCVT bindings
This commit is contained in:
Tony Aldridge
2015-01-13 09:25:53 +00:00
+94 -3
View File
@@ -1,9 +1,8 @@
//! Audio Functions
use std::borrow::ToOwned;
use std::ffi::{c_str_to_bytes, CString};
use std::num::FromPrimitive;
use libc::{c_int, c_void};
use libc::{uint8_t};
use libc::{self, c_int, c_void, size_t, uint8_t};
use std::ops::{Deref, DerefMut};
use get_error;
@@ -405,3 +404,95 @@ impl<'a, CB> Drop for AudioDeviceLockGuard<'a, CB> {
unsafe { ll::SDL_UnlockAudioDevice(self.device.device_id.id()) }
}
}
#[derive(PartialEq)] #[allow(raw_pointer_derive)]
pub struct AudioCVT {
raw: *mut ll::SDL_AudioCVT,
owned: bool,
}
impl_raw_accessors!( (AudioCVT, *mut ll::SDL_AudioCVT) );
impl_owned_accessors!( (AudioCVT, owned) );
impl Drop for AudioCVT {
fn drop(&mut self) {
if self.owned {
unsafe { libc::free(self.raw as *mut c_void) }
}
}
}
impl AudioCVT {
pub fn new(src_format: ll::SDL_AudioFormat, src_channels: u8, src_rate: i32,
dst_format: ll::SDL_AudioFormat, dst_channels: u8, dst_rate: i32) -> SdlResult<AudioCVT> {
use std::mem;
unsafe {
let c_cvt_p = libc::malloc(mem::size_of::<ll::SDL_AudioCVT>() as size_t) as *mut ll::SDL_AudioCVT;
let ret = ll::SDL_BuildAudioCVT(c_cvt_p,
src_format, src_channels, src_rate as c_int,
dst_format, dst_channels, dst_rate as c_int);
if ret == 1 || ret == 0 {
Ok(AudioCVT { raw: c_cvt_p, owned: true })
} else {
Err(get_error())
}
}
}
#[unstable="Certain conversions may cause buffer overflows. See AngryLawyer/rust-sdl2 issue #270."]
pub fn convert(&self, mut src: Vec<u8>) -> SdlResult<Vec<u8>> {
//! Convert audio data to a desired audio format.
//!
//! The `src` vector is adjusted to the capacity necessary to perform
//! the conversion in place; then it is passed to the SDL library.
unsafe {
if (*self.raw).needed != 1 {
return Err("no conversion needed!".to_owned())
}
// calculate the size of the dst buffer
(*self.raw).len = src.len() as c_int;
let dst_size = ( (*self.raw).len * (*self.raw).len_mult ) as usize;
let needed = dst_size - src.len();
src.reserve_exact(needed);
// perform the conversion in place
(*self.raw).buf = src.as_mut_ptr();
let ret = ll::SDL_ConvertAudio(self.raw);
// return original buffer back to caller
if ret == 0 {
debug_assert!( (*self.raw).len_cvt > 0 );
debug_assert!( (*self.raw).len_cvt as usize <= src.capacity() );
src.set_len((*self.raw).len_cvt as usize);
Ok(src)
} else {
Err(get_error())
}
}
}
}
#[cfg(test)]
mod test {
use super::{AudioCVT, AUDIOU8};
#[test]
fn test_audio_cvt() {
use std::iter::repeat;
// 0,1,2,3, ...
let buffer: Vec<u8> = range(0, 255).collect();
// 0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3, ...
let new_buffer_expected: Vec<u8> = range(0, 255).flat_map(|v| repeat(v).take(2)).collect();
let cvt = AudioCVT::new(AUDIOU8, 1, 44100, AUDIOU8, 2, 44100).unwrap();
let new_buffer = cvt.convert(buffer).unwrap();
assert_eq!(new_buffer.len(), new_buffer_expected.len());
assert_eq!(new_buffer, new_buffer_expected);
}
}