From 7fd3c31a0f31756c20c0cf5240e4176b361a3b7a Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Fri, 4 Mar 2022 12:49:36 +0100 Subject: [PATCH] Remove support for the non-SIMD Diopser version --- plugins/diopser/Cargo.toml | 3 +- plugins/diopser/README.md | 12 +---- plugins/diopser/src/filter.rs | 3 -- plugins/diopser/src/lib.rs | 84 +++++++---------------------------- 4 files changed, 21 insertions(+), 81 deletions(-) diff --git a/plugins/diopser/Cargo.toml b/plugins/diopser/Cargo.toml index a270c3a9..57965fc9 100644 --- a/plugins/diopser/Cargo.toml +++ b/plugins/diopser/Cargo.toml @@ -10,7 +10,8 @@ crate-type = ["cdylib"] [features] default = ["simd"] -# Make it go fast, vroom. Requires a nightly compiler. +# Make it go fast, vroom. Requires a nightly compiler. Support for the non-SIMD +# version has been removed at the moment. simd = ["nih_plug/simd"] [dependencies] diff --git a/plugins/diopser/README.md b/plugins/diopser/README.md index bb6fe30a..0ff2a1e8 100644 --- a/plugins/diopser/README.md +++ b/plugins/diopser/README.md @@ -34,17 +34,9 @@ on macOS. ### Building -After installing [Rust](https://rustup.rs/) with the nightly toolchain you can -compile Diopser as follows +After installing [Rust](https://rustup.rs/) with the nightly toolchain (because +of the use of SIMD), you can compile Diopser as follows ```shell cargo +nightly xtask bundle gain --release ``` - -If you don't have access to a nightly compiler (`rustup default nightly && rustup update`), -then you can compile a version without SIMD at a 2x penalty by disabling the -SIMD feature: - -```shell -cargo xtask bundle gain --release --no-default-features -``` diff --git a/plugins/diopser/src/filter.rs b/plugins/diopser/src/filter.rs index ca06dd1d..2836358b 100644 --- a/plugins/diopser/src/filter.rs +++ b/plugins/diopser/src/filter.rs @@ -16,8 +16,6 @@ use std::f32::consts; use std::ops::{Add, Mul, Sub}; - -#[cfg(feature = "simd")] use std::simd::f32x2; /// A simple biquad filter with functions for generating coefficients for an all-pass filter. @@ -136,7 +134,6 @@ impl SimdType for f32 { } } -#[cfg(feature = "simd")] impl SimdType for f32x2 { fn from_f32(value: f32) -> Self { f32x2::splat(value) diff --git a/plugins/diopser/src/lib.rs b/plugins/diopser/src/lib.rs index 988b8eae..b9583602 100644 --- a/plugins/diopser/src/lib.rs +++ b/plugins/diopser/src/lib.rs @@ -16,17 +16,18 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] +#[cfg(not(feature = "simd"))] +compile_error!("Compiling without SIMD support is currently not supported"); + #[macro_use] extern crate nih_plug; use nih_plug::prelude::*; use std::pin::Pin; +use std::simd::f32x2; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -#[cfg(feature = "simd")] -use std::simd::f32x2; - mod filter; /// How many all-pass filters we can have in series at most. The filter stages parameter determines @@ -54,10 +55,7 @@ struct Diopser { /// All of the all-pass filters, with vectorized coefficients so they can be calculated for /// multiple channels at once. [`DiopserParams::num_stages`] controls how many filters are /// actually active. - #[cfg(feature = "simd")] filters: [filter::Biquad; MAX_NUM_FILTERS], - #[cfg(not(feature = "simd"))] - filters: Vec<[filter::Biquad; MAX_NUM_FILTERS]>, /// If this is set at the start of the processing cycle, then the filter coefficients should be /// updated. For the regular filter parameters we can look at the smoothers, but this is needed @@ -118,10 +116,7 @@ impl Default for Diopser { sample_rate: 1.0, - #[cfg(feature = "simd")] filters: [filter::Biquad::default(); MAX_NUM_FILTERS], - #[cfg(not(feature = "simd"))] - filters: Vec::new(), should_update_filters, next_filter_smoothing_in: 1, @@ -227,17 +222,8 @@ impl Plugin for Diopser { } fn accepts_bus_config(&self, config: &BusConfig) -> bool { - // The scalar version can handle any channel config, while the SIMD version can only do - // stereo - #[cfg(feature = "simd")] - { - config.num_input_channels == config.num_output_channels - && config.num_input_channels == 2 - } - #[cfg(not(feature = "simd"))] - { - config.num_input_channels == config.num_output_channels && config.num_input_channels > 0 - } + // The SIMD version only supports stereo + config.num_input_channels == config.num_output_channels && config.num_input_channels == 2 } fn initialize( @@ -246,14 +232,6 @@ impl Plugin for Diopser { buffer_config: &BufferConfig, _context: &mut impl ProcessContext, ) -> bool { - #[cfg(not(feature = "simd"))] - { - self.filters = vec![ - [Default::default(); MAX_NUM_FILTERS]; - _bus_config.num_input_channels as usize - ]; - } - // Initialize the filters on the first process call self.sample_rate = buffer_config.sample_rate; self.should_update_filters.store(true, Ordering::Release); @@ -277,32 +255,17 @@ impl Plugin for Diopser { // We can compute the filters for both channels at once. The SIMD version thus now only // supports steroo audio. - #[cfg(feature = "simd")] + let mut samples = unsafe { channel_samples.to_simd_unchecked() }; + + for filter in self + .filters + .iter_mut() + .take(self.params.filter_stages.value as usize) { - let mut samples = unsafe { channel_samples.to_simd_unchecked() }; - - for filter in self - .filters - .iter_mut() - .take(self.params.filter_stages.value as usize) - { - samples = filter.process(samples); - } - - unsafe { channel_samples.from_simd_unchecked(samples) }; + samples = filter.process(samples); } - #[cfg(not(feature = "simd"))] - // We get better cache locality by iterating over the filters and then over the channels - for filter_idx in 0..self.params.filter_stages.value as usize { - for (channel_idx, filters) in self.filters.iter_mut().enumerate() { - // We can also use `channel_samples.iter_mut()`, but the compiler isn't able to - // optmize that iterator away and it would add a ton of overhead over indexing - // the buffer directly - let sample = unsafe { channel_samples.get_unchecked_mut(channel_idx) }; - *sample = filters[filter_idx].process(*sample); - } - } + unsafe { channel_samples.from_simd_unchecked(samples) }; } ProcessStatus::Normal @@ -381,23 +344,10 @@ impl Diopser { } .clamp(MIN_FREQUENCY, max_frequency); - let coefficients = + self.filters[filter_idx].coefficients = filter::BiquadCoefficients::allpass(self.sample_rate, filter_frequency, resonance); - - #[cfg(feature = "simd")] - { - self.filters[filter_idx].coefficients = coefficients; - if reset_filters { - self.filters[filter_idx].reset(); - } - } - - #[cfg(not(feature = "simd"))] - for channel in self.filters.iter_mut() { - channel[filter_idx].coefficients = coefficients; - if reset_filters { - channel[filter_idx].reset(); - } + if reset_filters { + self.filters[filter_idx].reset(); } } }