From 6f01097b031f49fc229f950192837ac056ee9d01 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 4 Apr 2022 17:44:49 +0200 Subject: [PATCH] Add mapped next_block() functions for smoothers --- src/param/smoothing.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/param/smoothing.rs b/src/param/smoothing.rs index c74faecc..e0aa025d 100644 --- a/src/param/smoothing.rs +++ b/src/param/smoothing.rs @@ -159,6 +159,17 @@ impl Smoother { /// Panics if this function is called again while another block value slice is still alive. #[inline] pub fn next_block(&self, block: &Block) -> Option> { + 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, + mut f: impl FnMut(f32) -> f32, + ) -> Option> { let mut block_values = self.block_values.borrow_mut(); if block_values.len() < block.len() { return None; @@ -168,7 +179,7 @@ impl Smoother { // 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()); + (&mut block_values[..block.len()]).fill_with(|| f(self.next())); Some(AtomicRefMut::map(block_values, |values| { &mut values[..block.len()] @@ -261,12 +272,26 @@ impl Smoother { /// Panics if this function is called again while another block value slice is still alive. #[inline] pub fn next_block(&self, block: &Block) -> Option> { + 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, + mut f: impl FnMut(i32) -> i32, + ) -> Option> { let mut block_values = self.block_values.borrow_mut(); if block_values.len() < block.len() { return None; } - (&mut block_values[..block.len()]).fill_with(|| self.next()); + // TODO: Might be useful to apply this function before rounding to an integer, but the f32 + // version is not available here without some hacks (i.e. grabbing it from + // `self.current`) + (&mut block_values[..block.len()]).fill_with(|| f(self.next())); Some(AtomicRefMut::map(block_values, |values| { &mut values[..block.len()]