Use Cow for formats conversions to avoid an allocation and copy

This commit is contained in:
Pierre Krieger 2014-12-17 08:53:09 +01:00
parent f4ac8a5492
commit 9721004ad0
2 changed files with 37 additions and 24 deletions

View File

@ -184,10 +184,22 @@ impl<'a, T> Drop for Buffer<'a, T> where T: Sample {
macro_rules! write_to_buf( macro_rules! write_to_buf(
($buf:expr, $output:expr, $ty:ty) => ({ ($buf:expr, $output:expr, $ty:ty) => ({
use std::borrow::Cow;
let output: &mut [$ty] = unsafe { std::mem::transmute($output) }; let output: &mut [$ty] = unsafe { std::mem::transmute($output) };
for (i, o) in $buf.into_iter().zip(output.iter_mut()) {
match $buf {
Cow::Borrowed(buf) => {
for (i, o) in buf.iter().zip(output.iter_mut()) {
*o = *i;
}
},
Cow::Owned(buf) => {
for (i, o) in buf.into_iter().zip(output.iter_mut()) {
*o = i; *o = i;
} }
}
}
}) })
) )

View File

@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::mem; use std::mem;
/// Format that each sample has. /// Format that each sample has.
@ -26,11 +27,11 @@ pub trait Sample: Copy {
fn get_format(Option<Self>) -> SampleFormat; fn get_format(Option<Self>) -> SampleFormat;
/// Turns the data into a `Vec<i16>` where each element is a sample. /// Turns the data into a `Vec<i16>` where each element is a sample.
fn to_vec_i16(&[Self]) -> Vec<i16>; fn to_vec_i16(&[Self]) -> Cow<Vec<i16>, [i16]>;
/// Turns the data into a `Vec<u16>` where each element is a sample. /// Turns the data into a `Vec<u16>` where each element is a sample.
fn to_vec_u16(&[Self]) -> Vec<u16>; fn to_vec_u16(&[Self]) -> Cow<Vec<u16>, [u16]>;
/// Turns the data into a `Vec<f32>` where each element is a sample. /// Turns the data into a `Vec<f32>` where each element is a sample.
fn to_vec_f32(&[Self]) -> Vec<f32>; fn to_vec_f32(&[Self]) -> Cow<Vec<f32>, [f32]>;
} }
impl Sample for u16 { impl Sample for u16 {
@ -38,22 +39,22 @@ impl Sample for u16 {
SampleFormat::U16 SampleFormat::U16
} }
fn to_vec_i16(input: &[u16]) -> Vec<i16> { fn to_vec_i16(input: &[u16]) -> Cow<Vec<i16>, [i16]> {
input.iter().map(|&value| { Cow::Owned(input.iter().map(|&value| {
if value >= 32768 { if value >= 32768 {
(value - 32768) as i16 (value - 32768) as i16
} else { } else {
(value as i16) - 32767 (value as i16) - 32767
} }
}).collect() }).collect())
} }
fn to_vec_u16(input: &[u16]) -> Vec<u16> { fn to_vec_u16(input: &[u16]) -> Cow<Vec<u16>, [u16]> {
input.to_vec() Cow::Borrowed(input)
} }
fn to_vec_f32(input: &[u16]) -> Vec<f32> { fn to_vec_f32(input: &[u16]) -> Cow<Vec<f32>, [f32]> {
Sample::to_vec_f32(Sample::to_vec_i16(input).as_slice()) Cow::Owned(Sample::to_vec_f32(Sample::to_vec_i16(input).as_slice()).to_vec())
} }
} }
@ -62,24 +63,24 @@ impl Sample for i16 {
SampleFormat::I16 SampleFormat::I16
} }
fn to_vec_i16(input: &[i16]) -> Vec<i16> { fn to_vec_i16(input: &[i16]) -> Cow<Vec<i16>, [i16]> {
input.to_vec() Cow::Borrowed(input)
} }
fn to_vec_u16(input: &[i16]) -> Vec<u16> { fn to_vec_u16(input: &[i16]) -> Cow<Vec<u16>, [u16]> {
input.iter().map(|&value| { Cow::Owned(input.iter().map(|&value| {
if value < 0 { if value < 0 {
(value + 32767) as u16 (value + 32767) as u16
} else { } else {
(value as u16) + 32768 (value as u16) + 32768
} }
}).collect() }).collect())
} }
fn to_vec_f32(input: &[i16]) -> Vec<f32> { fn to_vec_f32(input: &[i16]) -> Cow<Vec<f32>, [f32]> {
input.iter().map(|&value| { Cow::Owned(input.iter().map(|&value| {
value as f32 / 32768.0 value as f32 / 32768.0
}).collect() }).collect())
} }
} }
@ -88,15 +89,15 @@ impl Sample for f32 {
SampleFormat::F32 SampleFormat::F32
} }
fn to_vec_i16(input: &[f32]) -> Vec<i16> { fn to_vec_i16(input: &[f32]) -> Cow<Vec<i16>, [i16]> {
unimplemented!() unimplemented!()
} }
fn to_vec_u16(input: &[f32]) -> Vec<u16> { fn to_vec_u16(input: &[f32]) -> Cow<Vec<u16>, [u16]> {
unimplemented!() unimplemented!()
} }
fn to_vec_f32(input: &[f32]) -> Vec<f32> { fn to_vec_f32(input: &[f32]) -> Cow<Vec<f32>, [f32]> {
input.to_vec() Cow::Borrowed(input)
} }
} }