diff --git a/src/sfizz/SfzFilter.cpp b/src/sfizz/SfzFilter.cpp index 3d9dedc1..55f2444c 100644 --- a/src/sfizz/SfzFilter.cpp +++ b/src/sfizz/SfzFilter.cpp @@ -105,6 +105,29 @@ void Filter::clear() dsp->instanceClear(); } +void Filter::prepare(float cutoff, float q, float pksh) +{ + sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType); + + if (!dsp) + return; + + // compute a dummy 1-frame cycle with smoothing off + + float buffer[Impl::maxChannels] = {0}; + float *inout[Impl::maxChannels]; + bool en = dsp->isSmoothingEnabled(); + + for (unsigned i = 0; i < Impl::maxChannels; ++i) + inout[i] = &buffer[i]; + + dsp->instanceClear(); + dsp->configureStandard(cutoff, q, pksh); + dsp->setSmoothingEnabled(false); + dsp->compute(1, inout, inout); + dsp->setSmoothingEnabled(en); +} + void Filter::process(const float *const in[], float *const out[], float cutoff, float q, float pksh, unsigned nframes) { unsigned channels = P->fChannels; @@ -274,6 +297,29 @@ void FilterEq::clear() dsp->instanceClear(); } +void FilterEq::prepare(float cutoff, float bw, float pksh) +{ + sfzFilterDsp *dsp = P->getDsp(P->fChannels); + + if (!dsp) + return; + + // compute a dummy 1-frame cycle with smoothing off + + float buffer[Impl::maxChannels] = {0}; + float *inout[Impl::maxChannels]; + bool en = dsp->isSmoothingEnabled(); + + for (unsigned i = 0; i < Impl::maxChannels; ++i) + inout[i] = &buffer[i]; + + dsp->instanceClear(); + dsp->configureEq(cutoff, bw, pksh); + dsp->setSmoothingEnabled(false); + dsp->compute(1, inout, inout); + dsp->setSmoothingEnabled(en); +} + void FilterEq::process(const float *const in[], float *const out[], float cutoff, float bw, float pksh, unsigned nframes) { unsigned channels = P->fChannels; diff --git a/src/sfizz/SfzFilter.h b/src/sfizz/SfzFilter.h index 7b9ac9ae..3fd71e25 100644 --- a/src/sfizz/SfzFilter.h +++ b/src/sfizz/SfzFilter.h @@ -36,6 +36,14 @@ public: */ void clear(); + /** + Clear the filter memory, and compute the initial coefficients unaffected + by any smoothing. + + Make sure to set the filter type and channel count first. + */ + void prepare(float cutoff, float q, float pksh); + /** Process one cycle of the filter without modulating cutoff or Q. `cutoff` is a frequency expressed in Hz. @@ -131,6 +139,14 @@ public: */ void clear(); + /** + Clear the filter memory, and compute the initial coefficients unaffected + by any smoothing. + + Make sure to set the channel count first. + */ + void prepare(float cutoff, float bw, float pksh); + /** Process one cycle of the filter without modulating cutoff or bandwidth. `cutoff` is a frequency expressed in Hz. diff --git a/src/sfizz/SfzFilterImpls.cxx b/src/sfizz/SfzFilterImpls.cxx index 31b755d7..39cdd3cd 100644 --- a/src/sfizz/SfzFilterImpls.cxx +++ b/src/sfizz/SfzFilterImpls.cxx @@ -20,6 +20,19 @@ public: virtual void configureStandard(float, float, float) {} virtual void configureEq(float, float, float) {} + + bool isSmoothingEnabled() const + { + return fSmoothEnable; + } + + void setSmoothingEnabled(bool smooth) + { + fSmoothEnable = smooth; + } + +protected: + bool fSmoothEnable = true; // external variable used from faust code }; #if defined(__GNUC__) || defined(__clang__) diff --git a/src/sfizz/dsp/filters/sfz_filters.dsp b/src/sfizz/dsp/filters/sfz_filters.dsp index 705e5266..07f3fcf9 100644 --- a/src/sfizz/dsp/filters/sfz_filters.dsp +++ b/src/sfizz/dsp/filters/sfz_filters.dsp @@ -146,4 +146,8 @@ bandwidth = vslider("[04] Bandwidth [unit:octave]", 1.0, 0.1, 10.0, 0.01); // smoothCoefs = _ ; // No smoothing applied at all // This applies a quicker smoothing but which may render the filter unstable -smoothCoefs = si.smooth(ba.tau2pole(0.001)) ; // time constant = 1ms +smoothCoefs = si.smooth(ba.if(smoothEnable, pole, 0.0)) with { + timeConstant = 1e-3; // time constant = 1ms + pole = ba.tau2pole(timeConstant); + smoothEnable = fvariable(int fSmoothEnable, ); +};