Implement samples formats conversions

This commit is contained in:
Pierre Krieger 2014-12-17 08:39:00 +01:00
parent fbc0bad46f
commit d3d6dd94db
1 changed files with 51 additions and 17 deletions

View File

@ -1,3 +1,4 @@
#![feature(macro_rules)]
#![feature(unsafe_destructor)]
#[cfg(all(not(windows), not(unix)))]
@ -40,7 +41,6 @@ struct RequiredConversion<T> {
intermediate_buffer: Vec<T>,
from_sample_rate: SamplesRate,
to_sample_rate: SamplesRate,
from_format: SampleFormat,
to_format: SampleFormat,
from_channels: ChannelsCount,
to_channels: ChannelsCount,
@ -55,6 +55,15 @@ pub enum SampleFormat {
U16,
}
impl SampleFormat {
fn get_sample_size(&self) -> uint {
match self {
&SampleFormat::I16 => std::mem::size_of::<i16>(),
&SampleFormat::U16 => std::mem::size_of::<u16>(),
}
}
}
/// Trait for containers that contain PCM data.
#[unstable = "Will be rewritten with associated types"]
pub trait Sample: Copy {
@ -74,6 +83,22 @@ impl Sample for u16 {
}
}
impl Sample for i16 {
fn get_format(_: Option<i16>) -> SampleFormat {
SampleFormat::I16
}
fn to_vec_u16(input: &[i16]) -> Vec<u16> {
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();
@ -129,8 +154,10 @@ impl Channel {
source_samples_format != target_samples_format
{
let max_elements = max_elements * target_channels as uint / channels as uint;
let max_elements = max_elements * target_samples_rate.0 as uint / samples_rate.0 as uint;
// TODO: samples format
let max_elements = max_elements * target_samples_rate.0 as uint /
samples_rate.0 as uint;
let max_elements = max_elements * target_samples_format.get_sample_size() /
source_samples_format.get_sample_size();
let mut target_buffer = self.0.append_data(max_elements);
@ -140,7 +167,9 @@ impl Channel {
target_channels as uint;
let intermediate_buffer_length = intermediate_buffer_length * samples_rate.0 as uint /
target_samples_rate.0 as uint;
// TODO: adapt size to samples format too
let intermediate_buffer_length = intermediate_buffer_length *
source_samples_format.get_sample_size() /
target_samples_format.get_sample_size();
let intermediate_buffer = Vec::from_elem(intermediate_buffer_length, unsafe { std::mem::uninitialized() });
Buffer {
@ -149,7 +178,6 @@ impl Channel {
intermediate_buffer: intermediate_buffer,
from_sample_rate: samples_rate,
to_sample_rate: target_samples_rate,
from_format: source_samples_format,
to_format: target_samples_format,
from_channels: channels,
to_channels: target_channels,
@ -201,20 +229,26 @@ impl<'a, T> Drop for Buffer<'a, T> where T: Sample {
buffer
};
/*let buffer = if conversion.from_format != conversion.to_format {
match conversion.to_format {
SampleFormat::U16 => Sample::to_vec_u16(buffer.as_slice()),
_ => unimplemented!(),
}
} else {
buffer
};*/
if conversion.from_format != conversion.to_format { unimplemented!() }
let output = self.target.as_mut().unwrap().get_buffer();
assert!(buffer.len() == output.len(), "Buffers length mismatch: {} vs {}", buffer.len(), output.len());
for (i, o) in buffer.into_iter().zip(output.iter_mut()) {
*o = i;
macro_rules! write_to_buf(
($buf:expr, $output:expr, $ty:ty) => ({
let output: &mut [$ty] = unsafe { std::mem::transmute($output) };
for (i, o) in $buf.into_iter().zip(output.iter_mut()) {
*o = i;
}
})
)
match conversion.to_format {
SampleFormat::I16 => {
unimplemented!()
},
SampleFormat::U16 => {
let buffer = Sample::to_vec_u16(buffer.as_slice());
write_to_buf!(buffer, output, u16);
},
}
}