Reset Diopser filters when changing certain params
Parameters that cannot be interpolated might cause fun artifacts if we don't do this. Decreasing the number of stages would be fine without a reset though.
This commit is contained in:
parent
2f803915eb
commit
1d7a6a870b
|
@ -73,6 +73,13 @@ impl<T: SimdType> Biquad<T> {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the state to zero, useful after making making large, non-interpolatable changes to the
|
||||||
|
/// filter coefficients.
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.s1 = T::from_f32(0.0);
|
||||||
|
self.s2 = T::from_f32(0.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SimdType> BiquadCoefficients<T> {
|
impl<T: SimdType> BiquadCoefficients<T> {
|
||||||
|
|
|
@ -44,8 +44,6 @@ const MAX_AUTOMATION_STEP_SIZE: u32 = 512;
|
||||||
// improved). Other features I want to implement are:
|
// improved). Other features I want to implement are:
|
||||||
// - Briefly muting the output when changing the number of filters to get rid of the clicks
|
// - Briefly muting the output when changing the number of filters to get rid of the clicks
|
||||||
// - A GUI
|
// - A GUI
|
||||||
// - A panic switch (maybe also as a trigger-like parameter) to reset all filter states may also be
|
|
||||||
// useful
|
|
||||||
//
|
//
|
||||||
// TODO: Decide on whether to keep the scalar version or to just only support SIMD. Issue is that
|
// TODO: Decide on whether to keep the scalar version or to just only support SIMD. Issue is that
|
||||||
// packed_simd requires a nightly compiler.
|
// packed_simd requires a nightly compiler.
|
||||||
|
@ -321,16 +319,19 @@ impl Diopser {
|
||||||
/// Check if the filters need to be updated beased on [Self::should_update_filters] and the
|
/// Check if the filters need to be updated beased on [Self::should_update_filters] and the
|
||||||
/// smoothing interval, and update them as needed.
|
/// smoothing interval, and update them as needed.
|
||||||
fn maybe_update_filters(&mut self, smoothing_interval: u32) {
|
fn maybe_update_filters(&mut self, smoothing_interval: u32) {
|
||||||
let should_update_filters = self
|
// In addition to updating the filters, we should also clear the filter's state when
|
||||||
|
// changing a setting we can't neatly interpolate between.
|
||||||
|
let reset_filters = self
|
||||||
.should_update_filters
|
.should_update_filters
|
||||||
.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
|
.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
|
||||||
.is_ok()
|
.is_ok();
|
||||||
|
let should_update_filters = reset_filters
|
||||||
|| ((self.params.filter_frequency.smoothed.is_smoothing()
|
|| ((self.params.filter_frequency.smoothed.is_smoothing()
|
||||||
|| self.params.filter_resonance.smoothed.is_smoothing()
|
|| self.params.filter_resonance.smoothed.is_smoothing()
|
||||||
|| self.params.filter_spread_octaves.smoothed.is_smoothing())
|
|| self.params.filter_spread_octaves.smoothed.is_smoothing())
|
||||||
&& self.next_filter_smoothing_in <= 1);
|
&& self.next_filter_smoothing_in <= 1);
|
||||||
if should_update_filters {
|
if should_update_filters {
|
||||||
self.update_filters(smoothing_interval);
|
self.update_filters(smoothing_interval, reset_filters);
|
||||||
self.next_filter_smoothing_in = smoothing_interval as i32;
|
self.next_filter_smoothing_in = smoothing_interval as i32;
|
||||||
} else {
|
} else {
|
||||||
self.next_filter_smoothing_in -= 1;
|
self.next_filter_smoothing_in -= 1;
|
||||||
|
@ -339,7 +340,7 @@ impl Diopser {
|
||||||
|
|
||||||
/// Recompute the filter coefficients based on the smoothed paraetersm. We can skip forwardq in
|
/// Recompute the filter coefficients based on the smoothed paraetersm. We can skip forwardq in
|
||||||
/// larger steps to reduce the DSP load.
|
/// larger steps to reduce the DSP load.
|
||||||
fn update_filters(&mut self, smoothing_interval: u32) {
|
fn update_filters(&mut self, smoothing_interval: u32, reset_filters: bool) {
|
||||||
if self.filters.is_empty() {
|
if self.filters.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -382,11 +383,17 @@ impl Diopser {
|
||||||
#[cfg(feature = "simd")]
|
#[cfg(feature = "simd")]
|
||||||
{
|
{
|
||||||
self.filters[filter_idx].coefficients = coefficients;
|
self.filters[filter_idx].coefficients = coefficients;
|
||||||
|
if reset_filters {
|
||||||
|
self.filters[filter_idx].reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "simd"))]
|
#[cfg(not(feature = "simd"))]
|
||||||
for channel in self.filters.iter_mut() {
|
for channel in self.filters.iter_mut() {
|
||||||
channel[filter_idx].coefficients = coefficients;
|
channel[filter_idx].coefficients = coefficients;
|
||||||
|
if reset_filters {
|
||||||
|
channel[filter_idx].reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue