diff --git a/dsp/RecursiveLinearFilter.cpp b/dsp/RecursiveLinearFilter.cpp index 7eb69b8..b056500 100644 --- a/dsp/RecursiveLinearFilter.cpp +++ b/dsp/RecursiveLinearFilter.cpp @@ -162,3 +162,20 @@ void recursive_linear_filter::HighShelf::SetParams(const recursive_linear_filter this->_AssignCoefficients(a0, a1, a2, b0, b1, b2); } + +void recursive_linear_filter::LowPassBiquad::SetParams(const recursive_linear_filter::BiquadParams& params) +{ + const double omega0 = params.GetOmega0(); + const double cosw0 = std::cos(omega0); + const double alpha = params.GetAlpha(omega0); + + const double b0 = (1.0 - cosw0) / 2.0; + const double b1 = 1.0 - cosw0; + const double b2 = (1.0 - cosw0) / 2.0; + const double a0 = 1.0 + alpha; + const double a1 = -2.0 * cosw0; + const double a2 = 1.0 - alpha; + + // Normalize the coefficients by a0 and assign them + this->_AssignCoefficients(a0, a1, a2, b0, b1, b2); +} diff --git a/dsp/RecursiveLinearFilter.h b/dsp/RecursiveLinearFilter.h index 737d297..a85acc7 100644 --- a/dsp/RecursiveLinearFilter.h +++ b/dsp/RecursiveLinearFilter.h @@ -202,4 +202,11 @@ class LowPass : public Base } }; +class LowPassBiquad : public Biquad +{ +public: + LowPassBiquad() : Biquad() {} + void SetParams(const BiquadParams& params) override; +}; + }; // namespace recursive_linear_filter diff --git a/dsp/ResamplingContainer/ResamplingContainer.h b/dsp/ResamplingContainer/ResamplingContainer.h index 4b8eb6c..f6477f1 100644 --- a/dsp/ResamplingContainer/ResamplingContainer.h +++ b/dsp/ResamplingContainer/ResamplingContainer.h @@ -54,6 +54,8 @@ iPlug 2 includes the following 3rd party libraries (see each license info): #include "Dependencies/WDL/ptrlist.h" #include "Dependencies/LanczosResampler.h" +#include "AudioDSPTools/dsp/RecursiveLinearFilter.h" + namespace dsp { @@ -133,6 +135,14 @@ class ResamplingContainer mResampler1 = std::make_unique(mInputSampleRate, mRenderingSampleRate); mResampler2 = std::make_unique(mRenderingSampleRate, mInputSampleRate); + + // Initialize the LowPassBiquad filter with appropriate parameters + double cutoffFrequency = std::min(mInputSampleRate, mRenderingSampleRate) / 2.0 * 0.9; // For example + double qualityFactor = 0.707; // A common choice for a Butterworth filter + double gainDB = 0; // Typically, no gain change for a low-pass filter + recursive_linear_filter::BiquadParams params(mRenderingSampleRate, cutoffFrequency, qualityFactor, gainDB); + mLowPassFilter.SetParams(params); + // Zeroes the scratch pointers so that we warm up with silence. ClearBuffers(); @@ -182,6 +192,9 @@ class ResamplingContainer { throw std::runtime_error("Got more encapsulated samples than the encapsulated DSP is prepared to handle!"); } + mLowPassFilter.Process(mEncapsulatedOutputPointers.GetList(), 1, populated1); + + func(mEncapsulatedInputPointers.GetList(), mEncapsulatedOutputPointers.GetList(), (int)populated1); // And push the results into the second resampler so that it has what the external context requires. mResampler2->PushBlock(mEncapsulatedOutputPointers.GetList(), populated1); @@ -201,6 +214,8 @@ class ResamplingContainer int GetLatency() const { return mLatency; } private: + recursive_linear_filter::LowPassBiquad mLowPassFilter; // Declaration of the LowPassBiquad filter + static inline int LinearInterpolate(T** inputs, T** outputs, int inputLen, double ratio, int maxOutputLen) { // FIXME check through this!