1
0
Fork 0

Add an Iterator implementation for smoothers

This commit is contained in:
Robbert van der Helm 2022-04-04 17:51:51 +02:00
parent 6f01097b03
commit 98d725d24f

View file

@ -49,6 +49,14 @@ pub struct Smoother<T> {
block_values: AtomicRefCell<Vec<T>>,
}
/// An iterator that continuously produces smoothed values. Can be used as an alternative to the
/// built-in block-based smoothing API. Since the iterator itself is infinite, you can use
/// [`Smoother::is_smoothing()`] and [`Smoother::steps_left()`] to get information on the current
/// smoothing status.
pub struct SmootherIter<'a, T> {
smoother: &'a Smoother<T>,
}
impl<T: Default> Default for Smoother<T> {
fn default() -> Self {
Self {
@ -63,6 +71,27 @@ impl<T: Default> Default for Smoother<T> {
}
}
// We don't have a trait describing the smoother's functions so we need to duplicate this
// TODO: Maybe add a trait at some point so we can deduplicate some of the functions from this file.
// Needing a trait like that is not ideal though
impl Iterator for SmootherIter<'_, f32> {
type Item = f32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
Some(self.smoother.next())
}
}
impl Iterator for SmootherIter<'_, i32> {
type Item = i32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
Some(self.smoother.next())
}
}
impl<T: Default> Smoother<T> {
/// Use the specified style for the smoothing.
pub fn new(style: SmoothingStyle) -> Self {
@ -91,6 +120,11 @@ impl<T: Default> Smoother<T> {
self.steps_left() > 0
}
#[inline]
pub fn iter(&self) -> SmootherIter<T> {
SmootherIter { smoother: self }
}
/// Allocate memory to store smoothed values for an entire block of audio. Call this in
/// [`Plugin::initialize()`][crate::prelude::Plugin::initialize()] with the same max block size you are
/// going to pass to [`Buffer::iter_blocks()`][crate::prelude::Buffer::iter_blocks()].
@ -157,14 +191,12 @@ impl Smoother<f32> {
/// # Panics
///
/// Panics if this function is called again while another block value slice is still alive.
#[inline]
pub fn next_block(&self, block: &Block) -> Option<AtomicRefMut<[f32]>> {
self.next_block_mapped(block, |x| x)
}
/// The same as [`next_block()`][Self::next_block()], but with a function applied to each
/// produced value. Useful when applying modulation to a smoothed parameter.
#[inline]
pub fn next_block_mapped(
&self,
block: &Block,
@ -270,14 +302,12 @@ impl Smoother<i32> {
/// # Panics
///
/// Panics if this function is called again while another block value slice is still alive.
#[inline]
pub fn next_block(&self, block: &Block) -> Option<AtomicRefMut<[i32]>> {
self.next_block_mapped(block, |x| x)
}
/// The same as [`next_block()`][Self::next_block()], but with a function applied to each
/// produced value. Useful when applying modulation to a smoothed parameter.
#[inline]
pub fn next_block_mapped(
&self,
block: &Block,