diff --git a/examples/beep.rs b/examples/beep.rs index 935b0c2..478963c 100644 --- a/examples/beep.rs +++ b/examples/beep.rs @@ -20,7 +20,7 @@ fn main() { loop { 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(); *sample = value; } diff --git a/examples/music.rs b/examples/music.rs index 59eca8d..d6f5c19 100644 --- a/examples/music.rs +++ b/examples/music.rs @@ -9,14 +9,26 @@ fn main() { let mut decoder = vorbis::Decoder::new(BufReader::new(include_bin!("mozart_symfony_40.ogg"))) .unwrap(); - for packet in decoder.packets() { + 'main: for packet in decoder.packets() { 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 - for (i, o) in packet.data.into_iter().zip(buffer.iter_mut()) { - *o = i as u16; + loop { + let mut buffer = channel.append_data(channels, cpal::SamplesRate(rate as u32)); + let mut buffer = buffer.samples(); + + for output in buffer { + match data.next() { + Some(sample) => { + *output = *sample as u16; + }, + None => { + continue 'main; + } + } + } } } } diff --git a/src/lib.rs b/src/lib.rs index 97e78e3..1ca8dc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,18 @@ pub struct SamplesRate(pub u32); /// Represents a buffer that must be filled with audio data. /// /// A `Buffer` object borrows the channel. -pub struct Buffer<'a, T>(cpal_impl::Buffer<'a, T>, Option>); +pub struct Buffer<'a, T> { + // also contains something, taken by `Drop` + target: Option>, + // 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>, + // 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 { intermediate_buffer: Vec, @@ -134,9 +145,9 @@ impl Channel { // TODO: adapt size to samples format too let mut intermediate_buffer = Vec::from_elem(intermediate_buffer_length, unsafe { std::mem::uninitialized() }); - Buffer( - target_buffer, - Some(RequiredConversion { + Buffer { + target: Some(target_buffer), + conversion: Some(RequiredConversion { intermediate_buffer: intermediate_buffer, from_sample_rate: samples_rate, to_sample_rate: target_samples_rate, @@ -144,34 +155,44 @@ impl Channel { to_format: target_samples_format, from_channels: channels, to_channels: target_channels, - }) - ) + }), + elements_written: 0, + } } 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> { - fn deref(&self) -> &[T] { - panic!() +impl<'a, T> Buffer<'a, T> { + pub fn samples<'b>(&'b mut self) -> SamplesIter<'a, 'b, T> { + 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> { - fn deref_mut(&mut self) -> &mut [T] { - match self.1 { - Some(ref mut conv) => conv.intermediate_buffer.as_mut_slice(), - None => self.0.get_buffer() - } +/// Iterator over the samples of the buffer. +impl<'a, 'b, T> Iterator<&'b mut T> for SamplesIter<'a, 'b, T> { + fn next(&mut self) -> Option<&'b mut T> { + *self.0 += 1; + self.1.next() } } #[unsafe_destructor] impl<'a, T> Drop for Buffer<'a, T> where T: Sample { 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 = 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!() } - 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()); + self.elements_written += buffer.len(); for (i, o) in buffer.into_iter().zip(output.iter_mut()) { *o = i; } } + + self.target.take().unwrap().finish(self.elements_written); } } diff --git a/src/wasapi/mod.rs b/src/wasapi/mod.rs index d472958..3ae8ef7 100644 --- a/src/wasapi/mod.rs +++ b/src/wasapi/mod.rs @@ -108,14 +108,11 @@ impl Drop for Channel { } 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() } -} -#[unsafe_destructor] -impl<'a, T> Drop for Buffer<'a, T> { - fn drop(&mut self) { + pub fn finish(self, elements_written: uint) { // releasing buffer unsafe { let f = self.render_client.as_mut().unwrap().lpVtbl.as_ref().unwrap().ReleaseBuffer;