Modify API to use a "samples" iterator
This commit is contained in:
parent
27c91645ad
commit
04d07c27dc
|
@ -20,7 +20,7 @@ fn main() {
|
||||||
loop {
|
loop {
|
||||||
let mut buffer = channel.append_data(1, cpal::SamplesRate(44100));
|
let mut buffer = channel.append_data(1, cpal::SamplesRate(44100));
|
||||||
|
|
||||||
for sample in buffer.iter_mut() {
|
for sample in buffer.samples() {
|
||||||
let value = data_source.next().unwrap();
|
let value = data_source.next().unwrap();
|
||||||
*sample = value;
|
*sample = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,26 @@ fn main() {
|
||||||
let mut decoder = vorbis::Decoder::new(BufReader::new(include_bin!("mozart_symfony_40.ogg")))
|
let mut decoder = vorbis::Decoder::new(BufReader::new(include_bin!("mozart_symfony_40.ogg")))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for packet in decoder.packets() {
|
'main: for packet in decoder.packets() {
|
||||||
let packet = packet.unwrap();
|
let packet = packet.unwrap();
|
||||||
|
let vorbis::Packet { channels, rate, data, .. } = packet;
|
||||||
|
|
||||||
let mut buffer = channel.append_data(packet.channels, cpal::SamplesRate(packet.rate as u32));
|
let mut data = data.iter();
|
||||||
|
|
||||||
// FIXME: data loss
|
loop {
|
||||||
for (i, o) in packet.data.into_iter().zip(buffer.iter_mut()) {
|
let mut buffer = channel.append_data(channels, cpal::SamplesRate(rate as u32));
|
||||||
*o = i as u16;
|
let mut buffer = buffer.samples();
|
||||||
|
|
||||||
|
for output in buffer {
|
||||||
|
match data.next() {
|
||||||
|
Some(sample) => {
|
||||||
|
*output = *sample as u16;
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
continue 'main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
60
src/lib.rs
60
src/lib.rs
|
@ -25,7 +25,18 @@ pub struct SamplesRate(pub u32);
|
||||||
/// Represents a buffer that must be filled with audio data.
|
/// Represents a buffer that must be filled with audio data.
|
||||||
///
|
///
|
||||||
/// A `Buffer` object borrows the channel.
|
/// A `Buffer` object borrows the channel.
|
||||||
pub struct Buffer<'a, T>(cpal_impl::Buffer<'a, T>, Option<RequiredConversion<T>>);
|
pub struct Buffer<'a, T> {
|
||||||
|
// also contains something, taken by `Drop`
|
||||||
|
target: Option<cpal_impl::Buffer<'a, T>>,
|
||||||
|
// if this is non-none, then the data will be written to `conversion.intermediate_buffer`
|
||||||
|
// instead of `target`, and the conversion will be done in buffer's destructor
|
||||||
|
conversion: Option<RequiredConversion<T>>,
|
||||||
|
// number of elements that have been written
|
||||||
|
elements_written: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterator over the samples of the buffer.
|
||||||
|
pub struct SamplesIter<'a, 'b, T: 'b>(&'b mut uint, std::slice::MutItems<'b, T>);
|
||||||
|
|
||||||
struct RequiredConversion<T> {
|
struct RequiredConversion<T> {
|
||||||
intermediate_buffer: Vec<T>,
|
intermediate_buffer: Vec<T>,
|
||||||
|
@ -134,9 +145,9 @@ impl Channel {
|
||||||
// TODO: adapt size to samples format too
|
// TODO: adapt size to samples format too
|
||||||
let mut intermediate_buffer = Vec::from_elem(intermediate_buffer_length, unsafe { std::mem::uninitialized() });
|
let mut intermediate_buffer = Vec::from_elem(intermediate_buffer_length, unsafe { std::mem::uninitialized() });
|
||||||
|
|
||||||
Buffer(
|
Buffer {
|
||||||
target_buffer,
|
target: Some(target_buffer),
|
||||||
Some(RequiredConversion {
|
conversion: Some(RequiredConversion {
|
||||||
intermediate_buffer: intermediate_buffer,
|
intermediate_buffer: intermediate_buffer,
|
||||||
from_sample_rate: samples_rate,
|
from_sample_rate: samples_rate,
|
||||||
to_sample_rate: target_samples_rate,
|
to_sample_rate: target_samples_rate,
|
||||||
|
@ -144,34 +155,44 @@ impl Channel {
|
||||||
to_format: target_samples_format,
|
to_format: target_samples_format,
|
||||||
from_channels: channels,
|
from_channels: channels,
|
||||||
to_channels: target_channels,
|
to_channels: target_channels,
|
||||||
})
|
}),
|
||||||
)
|
elements_written: 0,
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Buffer(self.0.append_data(), None)
|
Buffer {
|
||||||
|
target: Some(self.0.append_data()),
|
||||||
|
conversion: None,
|
||||||
|
elements_written: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Deref<[T]> for Buffer<'a, T> {
|
impl<'a, T> Buffer<'a, T> {
|
||||||
fn deref(&self) -> &[T] {
|
pub fn samples<'b>(&'b mut self) -> SamplesIter<'a, 'b, T> {
|
||||||
panic!()
|
let iter = if let Some(ref mut conversion) = self.conversion {
|
||||||
|
conversion.intermediate_buffer.as_mut_slice().iter_mut()
|
||||||
|
} else {
|
||||||
|
self.target.as_mut().unwrap().get_buffer().iter_mut()
|
||||||
|
};
|
||||||
|
|
||||||
|
SamplesIter(&mut self.elements_written, iter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> DerefMut<[T]> for Buffer<'a, T> {
|
/// Iterator over the samples of the buffer.
|
||||||
fn deref_mut(&mut self) -> &mut [T] {
|
impl<'a, 'b, T> Iterator<&'b mut T> for SamplesIter<'a, 'b, T> {
|
||||||
match self.1 {
|
fn next(&mut self) -> Option<&'b mut T> {
|
||||||
Some(ref mut conv) => conv.intermediate_buffer.as_mut_slice(),
|
*self.0 += 1;
|
||||||
None => self.0.get_buffer()
|
self.1.next()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<'a, T> Drop for Buffer<'a, T> where T: Sample {
|
impl<'a, T> Drop for Buffer<'a, T> where T: Sample {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(conversion) = self.1.take() {
|
if let Some(conversion) = self.conversion.take() {
|
||||||
let buffer = conversion.intermediate_buffer;
|
let buffer = conversion.intermediate_buffer;
|
||||||
|
|
||||||
let buffer = if conversion.from_channels != conversion.to_channels {
|
let buffer = if conversion.from_channels != conversion.to_channels {
|
||||||
|
@ -198,11 +219,14 @@ impl<'a, T> Drop for Buffer<'a, T> where T: Sample {
|
||||||
};*/
|
};*/
|
||||||
if conversion.from_format != conversion.to_format { unimplemented!() }
|
if conversion.from_format != conversion.to_format { unimplemented!() }
|
||||||
|
|
||||||
let output = self.0.get_buffer();
|
let output = self.target.as_mut().unwrap().get_buffer();
|
||||||
assert!(buffer.len() == output.len(), "Buffers length mismatch: {} vs {}", buffer.len(), output.len());
|
assert!(buffer.len() == output.len(), "Buffers length mismatch: {} vs {}", buffer.len(), output.len());
|
||||||
|
self.elements_written += buffer.len();
|
||||||
for (i, o) in buffer.into_iter().zip(output.iter_mut()) {
|
for (i, o) in buffer.into_iter().zip(output.iter_mut()) {
|
||||||
*o = i;
|
*o = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.target.take().unwrap().finish(self.elements_written);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,14 +108,11 @@ impl Drop for Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Buffer<'a, T> {
|
impl<'a, T> Buffer<'a, T> {
|
||||||
pub fn get_buffer(&mut self) -> &mut [T] {
|
pub fn get_buffer<'b>(&'b mut self) -> &'b mut [T] {
|
||||||
self.buffer.as_mut_slice()
|
self.buffer.as_mut_slice()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe_destructor]
|
pub fn finish(self, elements_written: uint) {
|
||||||
impl<'a, T> Drop for Buffer<'a, T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// releasing buffer
|
// releasing buffer
|
||||||
unsafe {
|
unsafe {
|
||||||
let f = self.render_client.as_mut().unwrap().lpVtbl.as_ref().unwrap().ReleaseBuffer;
|
let f = self.render_client.as_mut().unwrap().lpVtbl.as_ref().unwrap().ReleaseBuffer;
|
||||||
|
|
Loading…
Reference in New Issue