Merge pull request #31 from mitchmindtree/master

Fixed coreaudio callback to send proper buffersize, removed code in lib where sampleformat affected buffersize
This commit is contained in:
tomaka 2015-03-03 08:34:11 +01:00
commit f7c2949549
3 changed files with 32 additions and 30 deletions

View File

@ -1,3 +1,5 @@
#![feature(core, old_io)]
extern crate cpal; extern crate cpal;
extern crate vorbis; extern crate vorbis;
@ -34,7 +36,7 @@ fn main() {
if let Some(output) = buffer.next() { if let Some(output) = buffer.next() {
*output = next_sample as u16; *output = next_sample as u16;
data = data.slice_from(1); data = &data[1..];
} else { } else {
break; break;
} }

View File

@ -6,11 +6,12 @@ use std::mem;
use std::sync::mpsc::{channel, Sender, Receiver}; use std::sync::mpsc::{channel, Sender, Receiver};
type NumChannels = usize; type NumChannels = usize;
type NumFrames = usize;
#[allow(dead_code)] #[allow(dead_code)]
pub struct Voice { pub struct Voice {
audio_unit: AudioUnit, audio_unit: AudioUnit,
ready_receiver: Receiver<()>, ready_receiver: Receiver<(NumChannels, NumFrames)>,
samples_sender: Sender<(Vec<f32>, NumChannels)>, samples_sender: Sender<(Vec<f32>, NumChannels)>,
} }
@ -42,15 +43,20 @@ impl Voice {
::SampleFormat::F32 ::SampleFormat::F32
} }
pub fn append_data<'a, T>(&'a mut self, buffer_size: usize) -> Buffer<'a, T> where T: Clone { pub fn append_data<'a, T>(&'a mut self, max_elements: usize) -> Buffer<'a, T> where T: Clone {
while let None = self.ready_receiver.try_recv().ok() {} // Block until the audio callback is ready for more data.
Buffer { loop {
if let Ok((channels, frames)) = self.ready_receiver.try_recv() {
let buffer_size = ::std::cmp::min(channels * frames, max_elements);
return Buffer {
samples_sender: self.samples_sender.clone(), samples_sender: self.samples_sender.clone(),
samples: vec![unsafe{ mem::uninitialized() }; buffer_size], samples: vec![unsafe{ mem::uninitialized() }; buffer_size],
num_channels: 2, num_channels: channels as usize,
marker: ::std::marker::PhantomData, marker: ::std::marker::PhantomData,
} }
} }
}
}
pub fn play(&mut self) { pub fn play(&mut self) {
// TODO // TODO
@ -88,25 +94,24 @@ fn new_voice() -> Result<Voice, String> {
let audio_unit_result = AudioUnit::new(Type::Output, SubType::HalOutput) let audio_unit_result = AudioUnit::new(Type::Output, SubType::HalOutput)
.render_callback(box move |channels, num_frames| { .render_callback(box move |channels, num_frames| {
if let Err(_) = ready_sender.send((channels.len(), num_frames)) {
let (samples, num_channels) = match samples_receiver.try_recv() {
Ok((samples, num_channels)) => (samples, num_channels),
_ => (vec![0.0; num_frames * channels.len()], channels.len()),
};
if let Err(_) = ready_sender.send(()) {
return Err("Callback failed to send 'ready' message.".to_string()); return Err("Callback failed to send 'ready' message.".to_string());
} }
loop {
if let Ok((samples, num_channels)) = samples_receiver.try_recv() {
let samples: Vec<f32> = samples;
assert!(num_frames == (samples.len() / num_channels) as usize, assert!(num_frames == (samples.len() / num_channels) as usize,
"The number of input frames given differs from the number requested by the AudioUnit"); "The number of input frames given differs from the number \
requested by the AudioUnit: {:?} and {:?} respectively",
(samples.len() / num_channels as usize), num_frames);
for (i, frame) in samples.chunks(num_channels).enumerate() { for (i, frame) in samples.chunks(num_channels).enumerate() {
for (channel, sample) in channels.iter_mut().zip(frame.iter()) { for (channel, sample) in channels.iter_mut().zip(frame.iter()) {
channel[i] = *sample; channel[i] = *sample;
} }
} }
break;
};
}
Ok(()) Ok(())
}) })

View File

@ -192,8 +192,6 @@ impl Voice {
let max_elements = max_elements * target_channels as usize / channels as usize; let max_elements = max_elements * target_channels as usize / channels as usize;
let max_elements = max_elements * target_samples_rate.0 as usize / let max_elements = max_elements * target_samples_rate.0 as usize /
samples_rate.0 as usize; samples_rate.0 as usize;
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); let mut target_buffer = self.0.append_data(max_elements);
@ -203,9 +201,6 @@ impl Voice {
target_channels as usize; target_channels as usize;
let intermediate_buffer_length = intermediate_buffer_length * samples_rate.0 as usize / let intermediate_buffer_length = intermediate_buffer_length * samples_rate.0 as usize /
target_samples_rate.0 as usize; target_samples_rate.0 as usize;
let intermediate_buffer_length = intermediate_buffer_length *
source_samples_format.get_sample_size() /
target_samples_format.get_sample_size();
let intermediate_buffer = std::iter::repeat(unsafe { std::mem::uninitialized() }) let intermediate_buffer = std::iter::repeat(unsafe { std::mem::uninitialized() })
.take(intermediate_buffer_length).collect(); .take(intermediate_buffer_length).collect();