mirror of
https://github.com/RustAudio/rodio
synced 2025-03-04 15:07:18 +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.
|
/// 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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue