diff --git a/src/lib.rs b/src/lib.rs index c5202b9..2c75fa4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,10 @@ #[cfg(all(not(windows), not(unix)))] use this_platform_is_not_supported; +pub use samples_formats::{SampleFormat, Sample}; + mod conversions; +mod samples_formats; #[cfg(unix)] #[path="alsa/mod.rs"] @@ -46,59 +49,6 @@ struct RequiredConversion { to_channels: ChannelsCount, } -/// Format that each sample has. -#[deriving(Clone, Copy, Show, PartialEq, Eq)] -pub enum SampleFormat { - /// The value 0 corresponds to 0. - I16, - /// The value 0 corresponds to 32768. - U16, -} - -impl SampleFormat { - fn get_sample_size(&self) -> uint { - match self { - &SampleFormat::I16 => std::mem::size_of::(), - &SampleFormat::U16 => std::mem::size_of::(), - } - } -} - -/// Trait for containers that contain PCM data. -#[unstable = "Will be rewritten with associated types"] -pub trait Sample: Copy { - fn get_format(Option) -> SampleFormat; - - /// Turns the data into a `Vec` where each element is a sample. - fn to_vec_u16(&[Self]) -> Vec; -} - -impl Sample for u16 { - fn get_format(_: Option) -> SampleFormat { - SampleFormat::U16 - } - - fn to_vec_u16(input: &[u16]) -> Vec { - input.to_vec() - } -} - -impl Sample for i16 { - fn get_format(_: Option) -> SampleFormat { - SampleFormat::I16 - } - - fn to_vec_u16(input: &[i16]) -> Vec { - input.iter().map(|&value| { - if value < 0 { - (value + 32767) as u16 - } else { - (value as u16) + 32768 - } - }).collect() - } -} - impl Channel { pub fn new() -> Channel { let channel = cpal_impl::Channel::new(); @@ -243,12 +193,17 @@ impl<'a, T> Drop for Buffer<'a, T> where T: Sample { match conversion.to_format { SampleFormat::I16 => { - unimplemented!() + let buffer = Sample::to_vec_i16(buffer.as_slice()); + write_to_buf!(buffer, output, i16); }, SampleFormat::U16 => { let buffer = Sample::to_vec_u16(buffer.as_slice()); write_to_buf!(buffer, output, u16); }, + SampleFormat::F32 => { + let buffer = Sample::to_vec_f32(buffer.as_slice()); + write_to_buf!(buffer, output, f32); + }, } } diff --git a/src/samples_formats.rs b/src/samples_formats.rs new file mode 100644 index 0000000..c192ad0 --- /dev/null +++ b/src/samples_formats.rs @@ -0,0 +1,102 @@ +use std::mem; + +/// Format that each sample has. +#[deriving(Clone, Copy, Show, PartialEq, Eq)] +pub enum SampleFormat { + /// The value 0 corresponds to 0. + I16, + /// The value 0 corresponds to 32768. + U16, + F32, +} + +impl SampleFormat { + pub fn get_sample_size(&self) -> uint { + match self { + &SampleFormat::I16 => mem::size_of::(), + &SampleFormat::U16 => mem::size_of::(), + &SampleFormat::F32 => mem::size_of::(), + } + } +} + +/// Trait for containers that contain PCM data. +#[unstable = "Will be rewritten with associated types"] +pub trait Sample: Copy { + fn get_format(Option) -> SampleFormat; + + /// Turns the data into a `Vec` where each element is a sample. + fn to_vec_i16(&[Self]) -> Vec; + /// Turns the data into a `Vec` where each element is a sample. + fn to_vec_u16(&[Self]) -> Vec; + /// Turns the data into a `Vec` where each element is a sample. + fn to_vec_f32(&[Self]) -> Vec; +} + +impl Sample for u16 { + fn get_format(_: Option) -> SampleFormat { + SampleFormat::U16 + } + + fn to_vec_i16(input: &[u16]) -> Vec { + input.iter().map(|&value| { + if value >= 32768 { + (value - 32768) as i16 + } else { + (value as i16) - 32767 + } + }).collect() + } + + fn to_vec_u16(input: &[u16]) -> Vec { + input.to_vec() + } + + fn to_vec_f32(input: &[u16]) -> Vec { + Sample::to_vec_f32(Sample::to_vec_i16(input).as_slice()) + } +} + +impl Sample for i16 { + fn get_format(_: Option) -> SampleFormat { + SampleFormat::I16 + } + + fn to_vec_i16(input: &[i16]) -> Vec { + input.to_vec() + } + + fn to_vec_u16(input: &[i16]) -> Vec { + input.iter().map(|&value| { + if value < 0 { + (value + 32767) as u16 + } else { + (value as u16) + 32768 + } + }).collect() + } + + fn to_vec_f32(input: &[i16]) -> Vec { + input.iter().map(|&value| { + value as f32 / 32768.0 + }).collect() + } +} + +impl Sample for f32 { + fn get_format(_: Option) -> SampleFormat { + SampleFormat::F32 + } + + fn to_vec_i16(input: &[f32]) -> Vec { + unimplemented!() + } + + fn to_vec_u16(input: &[f32]) -> Vec { + unimplemented!() + } + + fn to_vec_f32(input: &[f32]) -> Vec { + input.to_vec() + } +}