From 1a556514b010252d8e4f774995e074c7ff8d6838 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Mon, 15 Dec 2014 16:26:55 +0100 Subject: [PATCH] Sound output now works correctly --- examples/beep.rs | 2 +- examples/music.rs | 26 ++++++++++++-------------- src/lib.rs | 14 +++++++++++--- src/wasapi/mod.rs | 11 ++++++++++- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/examples/beep.rs b/examples/beep.rs index 478963c..15ec10e 100644 --- a/examples/beep.rs +++ b/examples/beep.rs @@ -18,7 +18,7 @@ fn main() { }); loop { - let mut buffer = channel.append_data(1, cpal::SamplesRate(44100)); + let mut buffer = channel.append_data(1, cpal::SamplesRate(44100), 32768); for sample in buffer.samples() { let value = data_source.next().unwrap(); diff --git a/examples/music.rs b/examples/music.rs index ef822c6..57905b0 100644 --- a/examples/music.rs +++ b/examples/music.rs @@ -13,27 +13,25 @@ fn main() { let packet = packet.unwrap(); let vorbis::Packet { channels, rate, data, .. } = packet; - let mut data = data.iter(); - let mut next_sample = None; + let mut data = data.as_slice(); loop { - let mut buffer = channel.append_data(channels, cpal::SamplesRate(rate as u32)); + if data.len() == 0 { + continue 'main; + } + + let mut buffer = channel.append_data(channels, cpal::SamplesRate(rate as u32), data.len()); let mut buffer = buffer.samples(); loop { - if next_sample.is_none() { - match data.next() { - Some(sample) => { - next_sample = Some(*sample as u16) - }, - None => { - continue 'main; - } - } - } + let next_sample = match data.get(0) { + Some(s) => *s, + None => continue 'main + }; if let Some(output) = buffer.next() { - *output = next_sample.take().unwrap(); + *output = next_sample as u16; + data = data.slice_from(1); } else { break; } diff --git a/src/lib.rs b/src/lib.rs index 05141e0..2185128 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,10 +120,18 @@ impl Channel { /// This function returns a `Buffer` object that must be filled with the audio data. /// You can't know in advance the size of the buffer, as it depends on the current state /// of the backend. + /// + /// ## Panic + /// + /// Panics if `max_elements` is 0 or is not a multiple of `channels`. + /// pub fn append_data<'a, T>(&'a mut self, channels: ChannelsCount, - samples_rate: SamplesRate) + samples_rate: SamplesRate, max_elements: uint) -> Buffer<'a, T> where T: Sample + Clone { + assert!(max_elements != 0); + assert!(max_elements % channels as uint == 0); + let target_samples_rate = self.0.get_samples_rate(); let target_channels = self.0.get_channels(); @@ -134,7 +142,7 @@ impl Channel { if samples_rate != target_samples_rate || channels != target_channels || source_samples_format != target_samples_format { - let mut target_buffer = self.0.append_data(); + let mut target_buffer = self.0.append_data(max_elements); // computing the length of the intermediary buffer let intermediate_buffer_length = target_buffer.get_buffer().len(); @@ -161,7 +169,7 @@ impl Channel { } else { Buffer { - target: Some(self.0.append_data()), + target: Some(self.0.append_data(max_elements)), conversion: None, elements_written: 0, } diff --git a/src/wasapi/mod.rs b/src/wasapi/mod.rs index 2feaa77..7f269c4 100644 --- a/src/wasapi/mod.rs +++ b/src/wasapi/mod.rs @@ -21,6 +21,7 @@ pub struct Buffer<'a, T> { render_client: *mut winapi::IAudioRenderClient, buffer: CVec, frames: winapi::UINT32, + channels: winapi::WORD, start_on_drop: bool, } @@ -44,7 +45,7 @@ impl Channel { } } - pub fn append_data<'a, T>(&'a mut self) -> Buffer<'a, T> { + pub fn append_data<'a, T>(&'a mut self, max_elements: uint) -> Buffer<'a, T> { unsafe { loop { // @@ -63,6 +64,11 @@ impl Channel { continue; } + let frames_available = ::std::cmp::min(frames_available, + max_elements as u32 * mem::size_of::() as u32 / + self.bytes_per_frame as u32); + assert!(frames_available != 0); + // loading buffer let buffer: CVec = { let mut buffer: *mut winapi::BYTE = mem::uninitialized(); @@ -81,6 +87,7 @@ impl Channel { audio_client: self.audio_client, render_client: self.render_client, buffer: buffer, + channels: self.num_channels, frames: frames_available, start_on_drop: !self.started, }; @@ -114,6 +121,8 @@ impl<'a, T> Buffer<'a, T> { } pub fn finish(self, elements_written: uint) { + let elements_written = elements_written / self.channels as uint; + // releasing buffer unsafe { let f = self.render_client.as_mut().unwrap().lpVtbl.as_ref().unwrap().ReleaseBuffer;