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.
pub trait Decoder {
/// Appends data to the voice.
///
/// Returns the number of nanoseconds after which new data will need to have been submitted.
/// Return `None` if the sound finished playing.
fn write(&mut self) -> Option<u64>;
/// Appends 17ms of data to the voice.
///
/// Returns false if the sound is over.
fn write(&mut self) -> bool;
/// Changes the volume of the sound.
fn set_volume(&mut self, f32);

View file

@ -44,18 +44,17 @@ impl VorbisDecoder {
}
impl Decoder for VorbisDecoder {
fn write(&mut self) -> Option<u64> {
fn write(&mut self) -> bool {
// 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);
}
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();
Some(duration)
true
}
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 {
fn write(&mut self) -> Option<u64> {
let (min, _) = self.reader.size_hint();
let min = cmp::min(min, 10240); // using a maximal value so that filters get applied
// 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);
}
fn write(&mut self) -> bool {
if let (0, _) = self.reader.size_hint() {
return false;
}
{
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);
}
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();
Some(duration)
true
}
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();
loop {
// polling for new sounds
// polling for new commands
if let Ok(command) = rx.try_recv() {
match command {
Command::Play(decoder) => {
@ -149,31 +149,16 @@ fn background(rx: Receiver<Command>) {
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
for decoder in &sounds {
if let Some(val) = 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 {
if !decoder.lock().unwrap().write() {
sounds_to_remove.push(decoder.clone());
}
}
// time taken to run the updates
let after_updates = time::precise_time_ns();
let updates_time_taken = after_updates - before_updates;
// 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);
}
// sleeping so that we get a loop every 17ms
let time_taken = time::precise_time_ns() - before_updates;
let sleep = 17000000u64.saturating_sub(time_taken);
thread::park_timeout_ms((sleep / 1000000) as u32);
}
}