mirror of
https://github.com/RustAudio/rodio
synced 2024-12-13 05:32:32 +00:00
Use loops of 17ms
This commit is contained in:
parent
a5c0d6673c
commit
a6b5197a59
4 changed files with 20 additions and 52 deletions
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue