From f2e679518040268e5d64ec857faef37c3d9a2cc0 Mon Sep 17 00:00:00 2001 From: ely-uf Date: Sat, 8 Aug 2020 19:26:33 +0300 Subject: [PATCH] Add SkipDuration. SkipDuration is a source that skips specified duration of the given source from it's current position. The already existing TakeDuration source allows to truncate the given source from the end. SkipDuration complements it, introducing the option of truncating the given source from it's current position. --- src/source/mod.rs | 10 ++++++ src/source/skip.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/source/skip.rs diff --git a/src/source/mod.rs b/src/source/mod.rs index a26544c..b03d3bb 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -21,6 +21,7 @@ pub use self::periodic::PeriodicAccess; pub use self::repeat::Repeat; pub use self::samples_converter::SamplesConverter; pub use self::sine::SineWave; +pub use self::skip::SkipDuration; pub use self::spatial::Spatial; pub use self::speed::Speed; pub use self::stoppable::Stoppable; @@ -45,6 +46,7 @@ mod periodic; mod repeat; mod samples_converter; mod sine; +mod skip; mod spatial; mod speed; mod stoppable; @@ -195,6 +197,14 @@ where delay::delay(self, duration) } + #[inline] + fn skip_duration(self, duration: Duration) -> SkipDuration + where + Self: Sized, + { + skip::skip_duration(self, duration) + } + /// Amplifies the sound by the given value. #[inline] fn amplify(self, value: f32) -> Amplify diff --git a/src/source/skip.rs b/src/source/skip.rs new file mode 100644 index 0000000..430fc13 --- /dev/null +++ b/src/source/skip.rs @@ -0,0 +1,76 @@ +use crate::{Sample, Source}; +use std::time::Duration; + +pub fn skip_duration(mut input: I, duration: Duration) -> SkipDuration +where + I: Source, + I::Item: Sample, +{ + let duration_ns = duration.as_nanos(); + let samples_to_skip = + duration_ns * input.sample_rate() as u128 / 1_000_000_000 * input.channels() as u128; + + for _ in 0..samples_to_skip { + if input.next().is_none() { + break; + } + } + + SkipDuration { + input, + skipped_duration: duration, + } +} + +#[derive(Clone, Debug)] +pub struct SkipDuration { + input: I, + skipped_duration: Duration, +} + +impl Iterator for SkipDuration +where + I: Source, + I::Item: Sample, +{ + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option { + self.input.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.input.size_hint() + } +} + +impl Source for SkipDuration +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().map(|val| { + val.checked_sub(self.skipped_duration) + .unwrap_or(Duration::from_secs(0)) + }) + } +}