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.
This commit is contained in:
ely-uf 2020-08-08 19:26:33 +03:00
parent b376b91e9e
commit f2e6795180
2 changed files with 86 additions and 0 deletions

View file

@ -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<Self>
where
Self: Sized,
{
skip::skip_duration(self, duration)
}
/// Amplifies the sound by the given value.
#[inline]
fn amplify(self, value: f32) -> Amplify<Self>

76
src/source/skip.rs Normal file
View file

@ -0,0 +1,76 @@
use crate::{Sample, Source};
use std::time::Duration;
pub fn skip_duration<I>(mut input: I, duration: Duration) -> SkipDuration<I>
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<I> {
input: I,
skipped_duration: Duration,
}
impl<I> Iterator for SkipDuration<I>
where
I: Source,
I::Item: Sample,
{
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.input.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.input.size_hint()
}
}
impl<I> Source for SkipDuration<I>
where
I: Source,
I::Item: Sample,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
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<Duration> {
self.input.total_duration().map(|val| {
val.checked_sub(self.skipped_duration)
.unwrap_or(Duration::from_secs(0))
})
}
}