Use loops of 17ms

This commit is contained in:
Pierre Krieger 2015-09-27 08:58:40 +02:00
parent a5c0d6673c
commit a6b5197a59
4 changed files with 20 additions and 52 deletions

View file

@ -9,11 +9,10 @@ mod wav;
/// Trait for objects that produce an audio stream. /// Trait for objects that produce an audio stream.
pub trait Decoder { pub trait Decoder {
/// Appends data to the voice. /// Appends 17ms of data to the voice.
/// ///
/// Returns the number of nanoseconds after which new data will need to have been submitted. /// Returns false if the sound is over.
/// Return `None` if the sound finished playing. fn write(&mut self) -> bool;
fn write(&mut self) -> Option<u64>;
/// Changes the volume of the sound. /// Changes the volume of the sound.
fn set_volume(&mut self, f32); fn set_volume(&mut self, f32);

View file

@ -44,18 +44,17 @@ impl VorbisDecoder {
} }
impl Decoder for VorbisDecoder { impl Decoder for VorbisDecoder {
fn write(&mut self) -> Option<u64> { fn write(&mut self) -> bool {
// TODO: handle end // TODO: handle end
{ {
let mut buffer = self.voice.append_data(32768); let samples = self.voice.get_samples_rate().0 * self.voice.get_channels() as u32;
let mut buffer = self.voice.append_data(samples as usize);
conversions::convert_and_write(self.reader.by_ref(), &mut buffer); conversions::convert_and_write(self.reader.by_ref(), &mut buffer);
} }
let duration = self.voice.get_pending_samples() as u64 * 1000000000 /
(self.voice.get_samples_rate().0 as u64 * self.voice.get_channels() as u64);
self.voice.play(); self.voice.play();
Some(duration) true
} }
fn set_volume(&mut self, value: f32) { fn set_volume(&mut self, value: f32) {

View file

@ -116,34 +116,19 @@ fn is_wave<R>(mut data: R) -> bool where R: Read + Seek {
} }
impl Decoder for WavDecoder { impl Decoder for WavDecoder {
fn write(&mut self) -> Option<u64> { fn write(&mut self) -> bool {
let (min, _) = self.reader.size_hint(); if let (0, _) = self.reader.size_hint() {
let min = cmp::min(min, 10240); // using a maximal value so that filters get applied return false;
// quickly
if min == 0 {
// finished playing
let remaining_time = self.voice.get_pending_samples() as u64 * 1000000000 /
(self.voice.get_samples_rate().0 as u64 * self.voice.get_channels() as u64);
if remaining_time == 0 {
return None;
} else {
return Some(remaining_time);
}
} }
{ {
let mut buffer = self.voice.append_data(min); let samples = self.voice.get_samples_rate().0 * self.voice.get_channels() as u32;
let mut buffer = self.voice.append_data(samples as usize);
conversions::convert_and_write(self.reader.by_ref(), &mut buffer); conversions::convert_and_write(self.reader.by_ref(), &mut buffer);
} }
let duration = self.voice.get_pending_samples() as u64 * 1000000000 /
(self.voice.get_samples_rate().0 as u64 * self.voice.get_channels() as u64);
self.voice.play(); self.voice.play();
true
Some(duration)
} }
fn set_volume(&mut self, value: f32) { fn set_volume(&mut self, value: f32) {

View file

@ -116,7 +116,7 @@ fn background(rx: Receiver<Command>) {
let mut sounds_to_remove: Vec<Arc<Mutex<Decoder + Send>>> = Vec::new(); let mut sounds_to_remove: Vec<Arc<Mutex<Decoder + Send>>> = Vec::new();
loop { loop {
// polling for new sounds // polling for new commands
if let Ok(command) = rx.try_recv() { if let Ok(command) = rx.try_recv() {
match command { match command {
Command::Play(decoder) => { Command::Play(decoder) => {
@ -149,31 +149,16 @@ fn background(rx: Receiver<Command>) {
let before_updates = time::precise_time_ns(); let before_updates = time::precise_time_ns();
// stores the time when this thread will have to be woken up
let mut next_step_ns = before_updates + 1000000000; // 1s
// updating the existing sounds // updating the existing sounds
for decoder in &sounds { for decoder in &sounds {
if let Some(val) = decoder.lock().unwrap().write() { if !decoder.lock().unwrap().write() {
let val = time::precise_time_ns() + val;
next_step_ns = cmp::min(next_step_ns, val); // updating next_step_ns
} else {
sounds_to_remove.push(decoder.clone()); sounds_to_remove.push(decoder.clone());
} }
} }
// time taken to run the updates // sleeping so that we get a loop every 17ms
let after_updates = time::precise_time_ns(); let time_taken = time::precise_time_ns() - before_updates;
let updates_time_taken = after_updates - before_updates; let sleep = 17000000u64.saturating_sub(time_taken);
thread::park_timeout_ms((sleep / 1000000) as u32);
// sleeping a bit if we can
let sleep = next_step_ns as i64 - after_updates as i64;
// the sleep duration is equal
// to `time_until_overflow - time_it_takes_to_write_data - 200µs`
// we remove 200µs to handle variations in the time it takes to write
let sleep = sleep - updates_time_taken as i64 - 200000;
if sleep >= 0 {
thread::park_timeout_ms((sleep / 1000000) as u32);
}
} }
} }