From baee81d31dd2eb0a8992608da251a96980dc688f Mon Sep 17 00:00:00 2001 From: Patrik Ristrom Date: Wed, 30 Jan 2019 22:15:31 +0100 Subject: [PATCH 1/2] Added Elapsed filter --- examples/elapsed.rs | 26 +++++++++++++++ src/source/elapsed.rs | 76 +++++++++++++++++++++++++++++++++++++++++++ src/source/mod.rs | 23 +++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 examples/elapsed.rs create mode 100644 src/source/elapsed.rs diff --git a/examples/elapsed.rs b/examples/elapsed.rs new file mode 100644 index 00000000..965df42e --- /dev/null +++ b/examples/elapsed.rs @@ -0,0 +1,26 @@ +extern crate rodio; + +use rodio::Source; +use std::io::BufReader; +use std::time::{Duration}; +use std::sync::{Mutex, Arc}; +use std::thread; + +fn main() { + let device = rodio::default_output_device().unwrap(); + let sink = rodio::Sink::new(&device); + + let file = std::fs::File::open("examples/music.ogg").unwrap(); + let source = rodio::Decoder::new(BufReader::new(file)).unwrap(); + + let timer = Arc::new(Mutex::new(Duration::from_secs(0))); + let with_elapsed = source.buffered().elapsed(Arc::clone(&timer)); + sink.append(with_elapsed); + + while !sink.empty() { + let val = *timer.lock().unwrap(); + + println!("Music has played for {} seconds", val.as_secs()); + thread::sleep(Duration::from_secs(1)); + } +} diff --git a/src/source/elapsed.rs b/src/source/elapsed.rs new file mode 100644 index 00000000..adeb3790 --- /dev/null +++ b/src/source/elapsed.rs @@ -0,0 +1,76 @@ +use std::time::Duration; +use std::sync::{Mutex, Arc}; + +use Sample; +use Source; + +/// Internal function that builds a `Elapsed` object. +pub fn elapsed(input: I, duration: Arc>) -> Elapsed +where + I: Source, + I::Item: Sample, +{ + Elapsed { + input: input, + duration: duration, + } +} + +/// Filter that updates a `Duration` with the current elapsed time. +#[derive(Clone, Debug)] +pub struct Elapsed { + input: I, + duration: Arc>, +} + +impl Iterator for Elapsed +where + I: Source, + I::Item: Sample, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + let mut duration = self.duration.lock().unwrap(); + + // Calculate sample_time in nanoseconds + let sample_time = (1_000_000_000 / self.sample_rate()) / self.channels() as u32; + + let time_elapsed = Duration::from_nanos(sample_time as u64); + *duration += time_elapsed; + + self.input.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.input.size_hint() + } +} + +impl Source for Elapsed +where + I: Source, + I::Item: Sample, +{ + #[inline] + fn current_frame_len(&self) -> Option { + self.input.current_frame_len() + } + + #[inline] + fn channels(&self) -> u16 { + self.input.channels() + } + + #[inline] + fn sample_rate(&self) -> u32 { + self.input.sample_rate() + } + + #[inline] + fn total_duration(&self) -> Option { + self.input.total_duration() + } +} diff --git a/src/source/mod.rs b/src/source/mod.rs index 084a9f2c..6d5c5e8c 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -1,6 +1,7 @@ //! Sources of sound and various filters. use std::time::Duration; +use std::sync::{Arc, Mutex}; use Sample; @@ -12,6 +13,7 @@ pub use self::delay::Delay; pub use self::done::Done; pub use self::empty::Empty; pub use self::fadein::FadeIn; +pub use self::elapsed::Elapsed; pub use self::from_factory::{from_factory, FromFactoryIter}; pub use self::from_iter::{from_iter, FromIter}; pub use self::mix::Mix; @@ -35,6 +37,7 @@ mod delay; mod done; mod empty; mod fadein; +mod elapsed; mod from_factory; mod from_iter; mod mix; @@ -211,6 +214,26 @@ where fadein::fadein(self, duration) } + /// Updates the supplied `Duration` with the total elapsed time for the source + /// + /// This is handy when you need to precisely time stuff to a music track for instance. + /// + /// # Example + /// + /// ```ignore + /// use std::time::Duration; + /// + /// let duration = Arc::new(Mutex::new(Duration::from_secs(0))); + /// let source = source.buffered().elapsed(Arc::clone(&duration)); + /// ``` + #[inline] + fn elapsed(self, duration: Arc>) -> Elapsed + where + Self: Sized, + { + elapsed::elapsed(self, duration) + } + /// Calls the `access` closure on `Self` every time `period` elapsed. #[inline] fn periodic_access(self, period: Duration, access: F) -> PeriodicAccess From c571342bb59fe96f2e7e942cfae6de2631f09e98 Mon Sep 17 00:00:00 2001 From: PaddyCo Date: Sun, 1 Mar 2020 14:52:46 +0100 Subject: [PATCH 2/2] Some small changes to elapsed filter --- examples/elapsed.rs | 2 +- src/source/elapsed.rs | 2 +- src/source/mod.rs | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/elapsed.rs b/examples/elapsed.rs index 965df42e..38317118 100644 --- a/examples/elapsed.rs +++ b/examples/elapsed.rs @@ -20,7 +20,7 @@ fn main() { while !sink.empty() { let val = *timer.lock().unwrap(); - println!("Music has played for {} seconds", val.as_secs()); + println!("Music has played for {}.{} seconds", val.as_secs(), val.subsec_millis()); thread::sleep(Duration::from_secs(1)); } } diff --git a/src/source/elapsed.rs b/src/source/elapsed.rs index adeb3790..4c4e85fb 100644 --- a/src/source/elapsed.rs +++ b/src/source/elapsed.rs @@ -37,7 +37,7 @@ where // Calculate sample_time in nanoseconds let sample_time = (1_000_000_000 / self.sample_rate()) / self.channels() as u32; - let time_elapsed = Duration::from_nanos(sample_time as u64); + let time_elapsed = Duration::from_nanos(sample_time.into()); *duration += time_elapsed; self.input.next() diff --git a/src/source/mod.rs b/src/source/mod.rs index 62564e2c..cb92af90 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -230,8 +230,6 @@ where /// Updates the supplied `Duration` with the total elapsed time for the source /// - /// This is handy when you need to precisely time stuff to a music track for instance. - /// /// # Example /// /// ```ignore