Optimize block smoothing
This commit is contained in:
parent
cd02ebb839
commit
99437c6011
|
@ -333,7 +333,8 @@ impl<T: Smoothable> Smoother<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The same as [`next_block()`][Self::next_block()], but with a function applied to each
|
/// 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.
|
/// produced value. Useful when applying modulation to a smoothed parameter. The mapping
|
||||||
|
/// function is only applied once for the final target value.
|
||||||
pub fn next_block_mapped(&self, block_values: &mut [T], block_len: usize, f: impl Fn(T) -> T) {
|
pub fn next_block_mapped(&self, block_values: &mut [T], block_len: usize, f: impl Fn(T) -> T) {
|
||||||
self.next_block_exact_mapped(&mut block_values[..block_len], f)
|
self.next_block_exact_mapped(&mut block_values[..block_len], f)
|
||||||
}
|
}
|
||||||
|
@ -346,12 +347,34 @@ impl<T: Smoothable> Smoother<T> {
|
||||||
// values in `block_values` would require smoothing and the rest don't. Instead, we'll just
|
// values in `block_values` would require smoothing and the rest don't. Instead, we'll just
|
||||||
// smooth the values as necessary, and then reuse the target value for the rest of the
|
// smooth the values as necessary, and then reuse the target value for the rest of the
|
||||||
// block.
|
// block.
|
||||||
let num_smoothed_values = block_values
|
let steps_left = self.steps_left.load(Ordering::Relaxed) as usize;
|
||||||
.len()
|
let num_smoothed_values = block_values.len().min(steps_left);
|
||||||
.min(self.steps_left.load(Ordering::Relaxed) as usize);
|
if num_smoothed_values > 0 {
|
||||||
|
// This is the same as calling `next()` `num_smoothed_values` times, but with some
|
||||||
|
// conditionals optimized out
|
||||||
|
let mut current = self.current.load(Ordering::Relaxed);
|
||||||
|
let target = self.target.to_f32();
|
||||||
|
block_values[..num_smoothed_values].fill_with(|| {
|
||||||
|
current = self.style.next(current, target, self.step_size);
|
||||||
|
f(T::from_f32(current))
|
||||||
|
});
|
||||||
|
|
||||||
block_values[..num_smoothed_values].fill_with(|| f(self.next()));
|
// In `next()` the last step snaps the value to the target value. Since we're computing
|
||||||
block_values[num_smoothed_values..].fill(self.target);
|
// many values in a row, we'll just overwrite the last value with the target value
|
||||||
|
// instead to avoid the conditional.
|
||||||
|
if num_smoothed_values == steps_left {
|
||||||
|
current = target.to_f32();
|
||||||
|
block_values[num_smoothed_values - 1..].fill(f(self.target));
|
||||||
|
} else {
|
||||||
|
block_values[num_smoothed_values..].fill(f(self.target));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current.store(current, Ordering::Relaxed);
|
||||||
|
self.steps_left
|
||||||
|
.fetch_sub(num_smoothed_values as i32, Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
block_values.fill(f(self.target));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue