1
0
Fork 0

Iterate in blocks in Crisp

I want to add a wet-only version, and this can help reduce per-sample
branching a bit.
This commit is contained in:
Robbert van der Helm 2022-03-09 19:35:12 +01:00
parent 5041f959b7
commit 9fc5b048ad

View file

@ -29,6 +29,8 @@ mod pcg;
/// The number of channels we support. Hardcoded to allow for easier SIMD-ifying in the future. /// The number of channels we support. Hardcoded to allow for easier SIMD-ifying in the future.
const NUM_CHANNELS: u32 = 2; const NUM_CHANNELS: u32 = 2;
/// The number of channels to iterate over at a time.
const BLOCK_SIZE: usize = 64;
/// These seeds being fixed makes bouncing deterministic. /// These seeds being fixed makes bouncing deterministic.
const INITIAL_PRNG_SEED: Pcg32iState = Pcg32iState::new(69, 420); const INITIAL_PRNG_SEED: Pcg32iState = Pcg32iState::new(69, 420);
@ -339,30 +341,45 @@ impl Plugin for Crisp {
buffer: &mut Buffer, buffer: &mut Buffer,
_context: &mut impl ProcessContext, _context: &mut impl ProcessContext,
) -> ProcessStatus { ) -> ProcessStatus {
for channel_samples in buffer.iter_mut() { for (_, mut block) in buffer.iter_blocks(BLOCK_SIZE) {
let amount = self.params.amount.smoothed.next() * AMOUNT_GAIN_MULTIPLIER; let mut rm_outputs = [[0.0; NUM_CHANNELS as usize]; BLOCK_SIZE];
let output_gain = self.params.output_gain.smoothed.next();
// Controls the pre-RM LPF and the HPF applied to the noise signal // Reduce per-sample branching a bit by iterating over smaller blocks and only then
self.maybe_update_filters(); // deciding what to dowith the output
for (channel_samples, rm_outputs) in block.iter_samples().zip(&mut rm_outputs) {
let amount = self.params.amount.smoothed.next() * AMOUNT_GAIN_MULTIPLIER;
// TODO: SIMD-ize this to process both channels at once // Controls the pre-RM LPF and the HPF applied to the noise signal
// TODO: Avoid branching twice here. Modern branch predictors are pretty good at this self.maybe_update_filters();
// though.
match self.params.stereo_mode.value() { // TODO: SIMD-ize this to process both channels at once
StereoMode::Mono => { // TODO: Avoid branching twice here. Modern branch predictors are pretty good at this
let noise = self.gen_noise(0); // though.
for (channel_idx, sample) in channel_samples.into_iter().enumerate() { match self.params.stereo_mode.value() {
*sample += self.do_ring_mod(*sample, channel_idx, noise) * amount; StereoMode::Mono => {
*sample *= output_gain; let noise = self.gen_noise(0);
for (channel_idx, (sample, rm_output)) in
channel_samples.into_iter().zip(rm_outputs).enumerate()
{
*rm_output = self.do_ring_mod(*sample, channel_idx, noise) * amount;
}
}
StereoMode::Stereo => {
for (channel_idx, (sample, rm_output)) in
channel_samples.into_iter().zip(rm_outputs).enumerate()
{
let noise = self.gen_noise(channel_idx);
*rm_output = self.do_ring_mod(*sample, channel_idx, noise) * amount;
}
} }
} }
StereoMode::Stereo => { }
for (channel_idx, sample) in channel_samples.into_iter().enumerate() {
let noise = self.gen_noise(channel_idx); for (channel_samples, rm_outputs) in block.iter_samples().zip(&mut rm_outputs) {
*sample += self.do_ring_mod(*sample, channel_idx, noise) * amount; let output_gain = self.params.output_gain.smoothed.next();
*sample *= output_gain;
} for (sample, rm_output) in channel_samples.into_iter().zip(rm_outputs) {
*sample = (*sample + *rm_output) * output_gain;
} }
} }
} }