Add Source::periodic_access

This commit is contained in:
Pierre Krieger 2017-05-01 13:39:02 +02:00
parent f0fed7ccb9
commit 83bcd1c175
2 changed files with 99 additions and 0 deletions

View file

@ -11,6 +11,7 @@ pub use self::empty::Empty;
pub use self::fadein::FadeIn;
pub use self::mix::Mix;
pub use self::pausable::Pausable;
pub use self::periodic::PeriodicAccess;
pub use self::repeat::Repeat;
pub use self::samples_converter::SamplesConverter;
pub use self::sine::SineWave;
@ -28,6 +29,7 @@ mod empty;
mod fadein;
mod mix;
mod pausable;
mod periodic;
mod repeat;
mod samples_converter;
mod sine;
@ -191,6 +193,15 @@ pub trait Source: Iterator
fadein::fadein(self, duration)
}
/// Calls the `access` closure on `Self` every time `period` elapsed.
#[inline]
fn periodic_access<F>(self, period: Duration, access: F) -> PeriodicAccess<Self, F>
where Self: Sized,
F: FnMut(&mut Self)
{
periodic::periodic(self, period, access)
}
/// Changes the play speed of the sound. Does not adjust the samples, only the play speed.
#[inline]
fn speed(self, ratio: f32) -> Speed<Self>

88
src/source/periodic.rs Normal file
View file

@ -0,0 +1,88 @@
use std::time::Duration;
use Sample;
use Source;
/// Internal function that builds a `PeriodicAccess` object.
pub fn periodic<I, F>(source: I, period: Duration, modifier: F) -> PeriodicAccess<I, F>
where I: Source,
I::Item: Sample,
{
// TODO: handle the fact that the samples rate can change
// TODO: generally, just wrong
let update_ms = period.as_secs() as u32 * 1_000 + period.subsec_nanos() / 1_000_000;
let update_frequency = (update_ms * source.samples_rate()) / 1000;
PeriodicAccess {
input: source,
modifier: modifier,
update_frequency: update_frequency,
samples_until_update: update_frequency,
}
}
/// Calls a function on a source every time a period elapsed.
#[derive(Clone, Debug)]
pub struct PeriodicAccess<I, F> {
// The inner source.
input: I,
// Closure that gets access to `inner`.
modifier: F,
// The frequency with which local_volume should be updated by remote_volume
update_frequency: u32,
// How many samples remain until it is time to update local_volume with remote_volume.
samples_until_update: u32,
}
impl<I, F> Iterator for PeriodicAccess<I, F>
where I: Source,
I::Item: Sample,
F: FnMut(&mut I)
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
self.samples_until_update -= 1;
if self.samples_until_update == 0 {
(self.modifier)(&mut self.input);
self.samples_until_update = self.update_frequency;
}
self.input.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.input.size_hint()
}
}
impl<I, F> Source for PeriodicAccess<I, F>
where I: Source,
I::Item: Sample,
F: FnMut(&mut I)
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
self.input.current_frame_len()
}
#[inline]
fn channels(&self) -> u16 {
self.input.channels()
}
#[inline]
fn samples_rate(&self) -> u32 {
self.input.samples_rate()
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
self.input.total_duration()
}
}