diff --git a/WECore/CarveDSP/CarveNoiseFilter.h b/WECore/CarveDSP/CarveNoiseFilter.h index 8a6830bb..1534f4dd 100644 --- a/WECore/CarveDSP/CarveNoiseFilter.h +++ b/WECore/CarveDSP/CarveNoiseFilter.h @@ -24,25 +24,7 @@ #pragma once -// DSPFilters sets off a lot of clang warnings - disable them for Butterworth.h only -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wfloat-equal" -#pragma clang diagnostic ignored "-Wunused-parameter" -#pragma clang diagnostic ignored "-Wignored-qualifiers" -#pragma clang diagnostic ignored "-Wold-style-cast" -#elif __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wignored-qualifiers" -#endif - -#include "DspFilters/Butterworth.h" - -#ifdef __clang__ -#pragma clang diagnostic pop -#elif __GNUC__ -#pragma GCC diagnostic pop -#endif +#include "WEFilters/TPTSVFilter.h" /** * A simple bandpass filter which can process mono or stereo signals. @@ -58,6 +40,7 @@ */ namespace WECore::Carve { + template class NoiseFilter { public: @@ -68,10 +51,7 @@ namespace WECore::Carve { * @param lowCutHz Everything below this frequency will be cut * @param highCutHz Everything above this frequency will be cut */ - NoiseFilter(float lowCutHz, float highCutHz) : _lowCutHz(lowCutHz), - _highCutHz(highCutHz) { - setSampleRate(44100); - } + NoiseFilter(double lowCutHz, double highCutHz); virtual ~NoiseFilter() {} @@ -96,7 +76,7 @@ namespace WECore::Carve { * @param inSample Pointer to the first sample of the buffer * @param numSamples Number of samples in the buffer */ - inline void Process1in1out(float* inSample, int numSamples); + inline void Process1in1out(T* inSample, int numSamples); /** * Applies the filtering to a stereo buffer of samples. @@ -107,45 +87,83 @@ namespace WECore::Carve { * @param numSamples Number of samples in the buffer. The left and right buffers * must be the same size. */ - inline void Process2in2out(float *inLeftSample, float *inRightSample, int numSamples); + inline void Process2in2out(T *inLeftSample, T *inRightSample, int numSamples); - private: - static constexpr int FILTER_ORDER {4}; - Dsp::SimpleFilter, 1> _monoHighCutFilter; - Dsp::SimpleFilter, 2> _stereoHighCutFilter; - - Dsp::SimpleFilter, 1> _monoLowCutFilter; - Dsp::SimpleFilter, 2> _stereoLowCutFilter; + private: + WECore::TPTSVF::TPTSVFilter _monoLowCutFilter; + WECore::TPTSVF::TPTSVFilter _leftLowCutFilter; + WECore::TPTSVF::TPTSVFilter _rightLowCutFilter; + + WECore::TPTSVF::TPTSVFilter _monoHighCutFilter; + WECore::TPTSVF::TPTSVFilter _leftHighCutFilter; + WECore::TPTSVF::TPTSVFilter _rightHighCutFilter; - float _lowCutHz, - _highCutHz; + double _lowCutHz, + _highCutHz; }; - void NoiseFilter::setSampleRate(double sampleRate) { - _monoLowCutFilter.setup(FILTER_ORDER, sampleRate, _lowCutHz); - _stereoLowCutFilter.setup(FILTER_ORDER, sampleRate, _lowCutHz); - _monoHighCutFilter.setup(FILTER_ORDER, sampleRate, _highCutHz); - _stereoHighCutFilter.setup(FILTER_ORDER, sampleRate, _highCutHz); + template + NoiseFilter::NoiseFilter(double lowCutHz, double highCutHz) : _lowCutHz(lowCutHz), + _highCutHz(highCutHz) { + setSampleRate(44100); + + auto setupLowCutFilter = [lowCutHz](TPTSVF::TPTSVFilter& filter) { + filter.setMode(WECore::TPTSVF::Parameters::ModeParameter::HIGHPASS); + filter.setCutoff(lowCutHz); + filter.setQ(1); + filter.setGain(1); + }; + + auto setupHighCutFilter = [highCutHz](TPTSVF::TPTSVFilter& filter) { + filter.setMode(WECore::TPTSVF::Parameters::ModeParameter::LOWPASS); + filter.setCutoff(highCutHz); + filter.setQ(1); + filter.setGain(1); + }; + + setupLowCutFilter(_monoLowCutFilter); + setupLowCutFilter(_leftLowCutFilter); + setupLowCutFilter(_rightLowCutFilter); + + setupHighCutFilter(_monoHighCutFilter); + setupHighCutFilter(_leftHighCutFilter); + setupHighCutFilter(_rightHighCutFilter); } - void NoiseFilter::reset() { + template + void NoiseFilter::setSampleRate(double sampleRate) { + _monoLowCutFilter.setSampleRate(sampleRate); + _leftLowCutFilter.setSampleRate(sampleRate); + _rightLowCutFilter.setSampleRate(sampleRate); + + _monoHighCutFilter.setSampleRate(sampleRate); + _leftHighCutFilter.setSampleRate(sampleRate); + _rightHighCutFilter.setSampleRate(sampleRate); + } + + template + void NoiseFilter::reset() { _monoLowCutFilter.reset(); + _leftLowCutFilter.reset(); + _rightLowCutFilter.reset(); + _monoHighCutFilter.reset(); - _stereoLowCutFilter.reset(); - _stereoHighCutFilter.reset(); + _leftHighCutFilter.reset(); + _rightHighCutFilter.reset(); } - void NoiseFilter::Process1in1out(float* inSample, int numSamples) { - _monoLowCutFilter.process(numSamples, &inSample); - _monoHighCutFilter.process(numSamples, &inSample); + template + void NoiseFilter::Process1in1out(T* inSample, int numSamples) { + _monoLowCutFilter.processBlock(inSample, numSamples); + _monoHighCutFilter.processBlock(inSample, numSamples); } - void NoiseFilter::Process2in2out(float *inLeftSample, float *inRightSample, int numSamples) { - float** channelsArray = new float*[2]; - channelsArray[0] = inLeftSample; - channelsArray[1] = inRightSample; - _stereoLowCutFilter.process(numSamples, channelsArray); - _stereoHighCutFilter.process(numSamples, channelsArray); - delete [] channelsArray; + template + void NoiseFilter::Process2in2out(T *inLeftSample, T *inRightSample, int numSamples) { + _leftLowCutFilter.processBlock(inLeftSample, numSamples); + _leftHighCutFilter.processBlock(inLeftSample, numSamples); + + _rightLowCutFilter.processBlock(inRightSample, numSamples); + _rightHighCutFilter.processBlock(inRightSample, numSamples); } } diff --git a/WECore/CarveDSP/Tests/CarveNoiseFilterTests.cpp b/WECore/CarveDSP/Tests/CarveNoiseFilterTests.cpp index b7c448af..e707a510 100644 --- a/WECore/CarveDSP/Tests/CarveNoiseFilterTests.cpp +++ b/WECore/CarveDSP/Tests/CarveNoiseFilterTests.cpp @@ -27,7 +27,7 @@ SCENARIO("CarveNoiseFilter: Silence in = silence out") { GIVEN("A CarveNoiseFilter and a buffer of silent samples") { std::vector buffer(1024); - WECore::Carve::NoiseFilter mFilter(20, 20000); + WECore::Carve::NoiseFilter mFilter(20, 20000); mFilter.setSampleRate(48000); WHEN("The silence samples are processed") { diff --git a/WECore/WEFilters/TPTSVFilter.h b/WECore/WEFilters/TPTSVFilter.h index 805a62d7..6849a056 100644 --- a/WECore/WEFilters/TPTSVFilter.h +++ b/WECore/WEFilters/TPTSVFilter.h @@ -50,10 +50,10 @@ namespace WECore::TPTSVF { _s1(0), _s2(0), _mode(Parameters::FILTER_MODE.BYPASS) {} - + TPTSVFilter(const TPTSVFilter& other) = default; virtual ~TPTSVFilter() = default; - + /** * Applies the filtering to a buffer of samples. * Expect seg faults or other memory issues if arguements passed are incorrect. @@ -62,7 +62,7 @@ namespace WECore::TPTSVF { * @param[in] numSamples Number of samples in the buffer */ void processBlock(T* inSamples, size_t numSamples); - + /** * Resets filter coefficients. * Call this whenever the audio stream is interrupted (ie. the playhead is moved) @@ -71,17 +71,17 @@ namespace WECore::TPTSVF { _s1 = 0; _s2 = 0; } - + /** @name Getter Methods */ /** @{ */ - + int getMode() const {return _mode;} double getCutoff() const {return _cutoffHz;} double getQ() const {return _Q;} double getGain() const {return _gain;} - + /** @} */ - + /** @name Setter Methods */ /** @{ */ @@ -90,10 +90,9 @@ namespace WECore::TPTSVF { void setQ(double val) {_Q = Parameters::Q.BoundsCheck(val);} void setGain(double val) {_gain = Parameters::GAIN.BoundsCheck(val);} void setSampleRate(double val) {_sampleRate = val;} - + /** @} */ - private: double _sampleRate, _cutoffHz, @@ -107,33 +106,33 @@ namespace WECore::TPTSVF { template void TPTSVFilter::processBlock(T* inSamples, size_t numSamples) { - + if (_mode != Parameters::FILTER_MODE.BYPASS) { - const T g {std::tan(CoreMath::DOUBLE_PI * _cutoffHz / _sampleRate)}; - const T h {1.0f / (1 + g / _Q + g * g)}; - + const T g {static_cast(std::tan(CoreMath::DOUBLE_PI * _cutoffHz / _sampleRate))}; + const T h {static_cast(1.0 / (1 + g / _Q + g * g))}; + for (size_t idx {0}; idx < numSamples; idx++) { const T sample {inSamples[idx]}; - - const T yH {h * (sample - (1.0f / _Q + g) * _s1 - _s2)}; - - const T yB {g * yH + _s1}; + + const T yH {static_cast(h * (sample - (1.0f / _Q + g) * _s1 - _s2))}; + + const T yB {static_cast(g * yH + _s1)}; _s1 = g * yH + yB; - - const T yL {g * yB + _s2}; + + const T yL {static_cast(g * yB + _s2)}; _s2 = g * yB + yL; - + switch (_mode) { case Parameters::ModeParameter::PEAK: - inSamples[idx] = yB * _gain; + inSamples[idx] = yB * static_cast(_gain); break; - + case Parameters::ModeParameter::HIGHPASS: - inSamples[idx] = yH * _gain; + inSamples[idx] = yH * static_cast(_gain); break; - + default: - inSamples[idx] = yL * _gain; + inSamples[idx] = yL * static_cast(_gain); break; } }