1
0
Fork 0

Refactor IIR crossover process loop, disable FIR

The FIR crossover will need to use FFT convolution, so it can't use the
same loop. Because of that we'll need to rework the FIR crossover to not
use channel SIMD and to work on channel slices instead.
This commit is contained in:
Robbert van der Helm 2022-06-07 16:13:39 +02:00
parent 7e3dfe904d
commit 2c48ceb392

View file

@ -21,7 +21,6 @@ compile_error!("Compiling without SIMD support is currently not supported");
use crossover::fir::{FirCrossover, FirCrossoverType};
use crossover::iir::{IirCrossover, IirCrossoverType};
use nih_plug::buffer::ChannelSamples;
use nih_plug::prelude::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
@ -201,7 +200,7 @@ impl Plugin for Crossover {
self.buffer_config = *buffer_config;
// Make sure the filter states match the current parameters
self.update_filters();
self.update_filters(1);
// The FIR filters are linear-phase and introduce latency
match self.params.crossover_type.value() {
@ -228,29 +227,23 @@ impl Plugin for Crossover {
// Right now both crossover types only do 24 dB/octave Linkwitz-Riley style crossovers
match self.params.crossover_type.value() {
CrossoverType::LinkwitzRiley24 => {
Self::do_process(buffer, aux, |main_channel_samples, bands| {
// Only update the filters when needed
self.maybe_update_filters();
self.iir_crossover.process(
self.params.num_bands.value as usize,
main_channel_samples,
bands,
);
})
self.process_iir(buffer, aux);
}
CrossoverType::LinkwitzRiley24LinearPhase => {
context.set_latency_samples(self.fir_crossover.latency());
Self::do_process(buffer, aux, |main_channel_samples, bands| {
self.maybe_update_filters();
todo!();
// Self::do_process(buffer, aux, |main_channel_samples, bands| {
// if self.should_update_filters() {
// self.update_filters(buffer.len() as u32);
// }
self.fir_crossover.process(
self.params.num_bands.value as usize,
main_channel_samples,
bands,
);
})
// self.fir_crossover.process(
// self.params.num_bands.value as usize,
// main_channel_samples,
// bands,
// );
// })
}
}
@ -263,11 +256,7 @@ impl Crossover {
/// friendly and SIMD-able interface for the processing function. Prevents havign to branch per
/// sample. The closure receives an input sample and it should write the output samples for each
/// band to the array.
fn do_process(
buffer: &mut Buffer,
aux: &mut AuxiliaryBuffers,
mut f: impl FnMut(&ChannelSamples, [ChannelSamples; NUM_BANDS]),
) {
fn process_iir(&mut self, buffer: &mut Buffer, aux: &mut AuxiliaryBuffers) {
let aux_outputs = &mut aux.outputs;
let (band_1_buffer, aux_outputs) = aux_outputs.split_first_mut().unwrap();
let (band_2_buffer, aux_outputs) = aux_outputs.split_first_mut().unwrap();
@ -302,7 +291,16 @@ impl Crossover {
band_5_channel_samples,
];
f(&main_channel_samples, bands);
// Only update the filters when needed
if self.should_update_filters() {
self.update_filters(1);
}
self.iir_crossover.process(
self.params.num_bands.value as usize,
&main_channel_samples,
bands,
);
// The main output should be silent as the signal is already evenly split over the other
// bands
@ -312,28 +310,29 @@ impl Crossover {
}
}
/// Update the filter coefficients for the crossovers, but only if it's needed.
fn maybe_update_filters(&mut self) {
if self
.should_update_filters
/// Returns whether the filters should be updated. There are different updating functions for
/// the IIR and FIR crossovers.
fn should_update_filters(&mut self) -> bool {
// Technically this would only require a &self since `should_update_filters` has interior
// mutability, but with the current setup this doesn't cause any problems and makes the
// former a bit more obvious
self.should_update_filters
.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed)
.is_ok()
|| self.params.crossover_1_freq.smoothed.is_smoothing()
|| self.params.crossover_2_freq.smoothed.is_smoothing()
|| self.params.crossover_3_freq.smoothed.is_smoothing()
|| self.params.crossover_4_freq.smoothed.is_smoothing()
{
self.update_filters();
}
}
/// Update the filter coefficients for the crossovers.
fn update_filters(&mut self) {
/// Update the filter coefficients for the crossovers. The step size can be used when the filter
/// coefficietns aren't updated every sample.
fn update_filters(&mut self, step_size: u32) {
let crossover_frequencies = [
self.params.crossover_1_freq.smoothed.next(),
self.params.crossover_2_freq.smoothed.next(),
self.params.crossover_3_freq.smoothed.next(),
self.params.crossover_4_freq.smoothed.next(),
self.params.crossover_1_freq.smoothed.next_step(step_size),
self.params.crossover_2_freq.smoothed.next_step(step_size),
self.params.crossover_3_freq.smoothed.next_step(step_size),
self.params.crossover_4_freq.smoothed.next_step(step_size),
];
match self.params.crossover_type.value() {