// /// @file LowPassFilter.cpp /// @brief A class to implement a low pass filter without losing precision even for int types /// the downside being that it's a little slower as it internally uses a float /// and it consumes an extra 4 bytes of memory to hold the constant gain #include "LowPassFilter.h" //////////////////////////////////////////////////////////////////////////////////////////// // DigitalLPF //////////////////////////////////////////////////////////////////////////////////////////// template DigitalLPF::DigitalLPF() { // built in initialization _output = T(); } // add a new raw value to the filter, retrieve the filtered result template T DigitalLPF::apply(const T &sample, float cutoff_freq, float dt) { if (cutoff_freq <= 0.0f || dt <= 0.0f) { _output = sample; return _output; } float rc = 1.0f/(M_2PI*cutoff_freq); alpha = constrain_float(dt/(dt+rc), 0.0f, 1.0f); _output += (sample - _output) * alpha; return _output; } template T DigitalLPF::apply(const T &sample) { _output += (sample - _output) * alpha; return _output; } template void DigitalLPF::compute_alpha(float sample_freq, float cutoff_freq) { if (cutoff_freq <= 0.0f || sample_freq <= 0.0f) { alpha = 1.0; } else { float dt = 1.0/sample_freq; float rc = 1.0f/(M_2PI*cutoff_freq); alpha = constrain_float(dt/(dt+rc), 0.0f, 1.0f); } } // get latest filtered value from filter (equal to the value returned by latest call to apply method) template const T &DigitalLPF::get() const { return _output; } template void DigitalLPF::reset(T value) { _output = value; } //////////////////////////////////////////////////////////////////////////////////////////// // LowPassFilter //////////////////////////////////////////////////////////////////////////////////////////// // constructors template LowPassFilter::LowPassFilter() : _cutoff_freq(0.0f) {} template LowPassFilter::LowPassFilter(float cutoff_freq) : _cutoff_freq(cutoff_freq) {} template LowPassFilter::LowPassFilter(float sample_freq, float cutoff_freq) { set_cutoff_frequency(sample_freq, cutoff_freq); } // change parameters template void LowPassFilter::set_cutoff_frequency(float cutoff_freq) { _cutoff_freq = cutoff_freq; } template void LowPassFilter::set_cutoff_frequency(float sample_freq, float cutoff_freq) { _cutoff_freq = cutoff_freq; _filter.compute_alpha(sample_freq, cutoff_freq); } // return the cutoff frequency template float LowPassFilter::get_cutoff_freq(void) const { return _cutoff_freq; } template T LowPassFilter::apply(T sample, float dt) { return _filter.apply(sample, _cutoff_freq, dt); } template T LowPassFilter::apply(T sample) { return _filter.apply(sample); } template const T &LowPassFilter::get() const { return _filter.get(); } template void LowPassFilter::reset(T value) { _filter.reset(value); } /* * Make an instances * Otherwise we have to move the constructor implementations to the header file :P */ template class LowPassFilter; template class LowPassFilter; template class LowPassFilter; template class LowPassFilter; template class LowPassFilter;