Implement the block smoothers
This commit is contained in:
parent
17145a4482
commit
dffddfaf04
1 changed files with 48 additions and 2 deletions
|
@ -1,5 +1,5 @@
|
||||||
use atomic_float::AtomicF32;
|
use atomic_float::AtomicF32;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
||||||
use std::sync::atomic::{AtomicI32, Ordering};
|
use std::sync::atomic::{AtomicI32, Ordering};
|
||||||
|
|
||||||
/// Controls if and how parameters gets smoothed.
|
/// Controls if and how parameters gets smoothed.
|
||||||
|
@ -124,7 +124,7 @@ impl Smoother<f32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next value from this smoother. The value will be equal to the previous value once
|
/// Get the next value from this smoother. The value will be equal to the previous value once
|
||||||
// the smoothing period is over. This should be called exactly once per sample.
|
/// the smoothing period is over. This should be called exactly once per sample.
|
||||||
// Yes, Clippy, like I said, this was intentional
|
// Yes, Clippy, like I said, this was intentional
|
||||||
#[allow(clippy::should_implement_trait)]
|
#[allow(clippy::should_implement_trait)]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -132,6 +132,31 @@ impl Smoother<f32> {
|
||||||
self.next_step(1)
|
self.next_step(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Produce smoothed values for an entire block of audio. Used in conjunction with
|
||||||
|
/// [crate::Buffer::iter_blocks()]. Make sure to call
|
||||||
|
/// [crate::Plugin::initialize_block_smoothers()] with the same maximum buffer block size as the
|
||||||
|
/// one passed to `iter_blocks()` in your [crate::Plugin::initialize()] function first to
|
||||||
|
/// allocate memory for the block smoothing.
|
||||||
|
///
|
||||||
|
/// Returns a `None` value if the block length exceed's the allocated capacity.
|
||||||
|
#[inline]
|
||||||
|
pub fn next_block(&self, block_len: usize) -> Option<MappedMutexGuard<[f32]>> {
|
||||||
|
let mut block_values = self.block_values.lock();
|
||||||
|
if block_values.len() < block_len {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: As a small optimization we could split this up into two loops for the smoothed and
|
||||||
|
// unsmoothed parts. Another worthwhile optimization would be to remember if the
|
||||||
|
// buffer is already filled with the target value and [Self::is_smoothing()] is false.
|
||||||
|
// In that case we wouldn't need to do anything ehre.
|
||||||
|
(&mut block_values[..block_len]).fill_with(|| self.next());
|
||||||
|
|
||||||
|
Some(MutexGuard::map(block_values, |values| {
|
||||||
|
&mut values[..block_len]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
/// [Self::next()], but with the ability to skip forward in the smoother. [Self::next()] is
|
/// [Self::next()], but with the ability to skip forward in the smoother. [Self::next()] is
|
||||||
/// equivalent to calling this function with a `steps` value of 1. Calling this function with a
|
/// equivalent to calling this function with a `steps` value of 1. Calling this function with a
|
||||||
/// `steps` value of `n` means will cause you to skip the next `n - 1` values and return the
|
/// `steps` value of `n` means will cause you to skip the next `n - 1` values and return the
|
||||||
|
@ -204,6 +229,27 @@ impl Smoother<i32> {
|
||||||
self.next_step(1)
|
self.next_step(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Produce smoothed values for an entire block of audio. Used in conjunction with
|
||||||
|
/// [crate::Buffer::iter_blocks()]. Make sure to call
|
||||||
|
/// [crate::Plugin::initialize_block_smoothers()] with the same maximum buffer block size as the
|
||||||
|
/// one passed to `iter_blocks()` in your [crate::Plugin::initialize()] function first to
|
||||||
|
/// allocate memory for the block smoothing.
|
||||||
|
///
|
||||||
|
/// Returns a `None` value if the block length exceed's the allocated capacity.
|
||||||
|
#[inline]
|
||||||
|
pub fn next_block(&self, block_len: usize) -> Option<MappedMutexGuard<[i32]>> {
|
||||||
|
let mut block_values = self.block_values.lock();
|
||||||
|
if block_values.len() < block_len {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
(&mut block_values[..block_len]).fill_with(|| self.next());
|
||||||
|
|
||||||
|
Some(MutexGuard::map(block_values, |values| {
|
||||||
|
&mut values[..block_len]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
/// [Self::next()], but with the ability to skip forward in the smoother. [Self::next()] is
|
/// [Self::next()], but with the ability to skip forward in the smoother. [Self::next()] is
|
||||||
/// equivalent to calling this function with a `steps` value of 1. Calling this function with a
|
/// equivalent to calling this function with a `steps` value of 1. Calling this function with a
|
||||||
/// `steps` value of `n` means will cause you to skip the next `n - 1` values and return the
|
/// `steps` value of `n` means will cause you to skip the next `n - 1` values and return the
|
||||||
|
|
Loading…
Add table
Reference in a new issue