// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- // // This is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License as published by the // Free Software Foundation; either version 2.1 of the License, or (at // your option) any later version. // /// @file LowPassFilter.h /// @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 #ifndef LowPassFilter_h #define LowPassFilter_h #include #include // 1st parameter is the type of data being filtered. template class LowPassFilter : public Filter { public: // constructor LowPassFilter(float gain); // apply - Add a new raw value to the filter, retrieve the filtered result virtual T apply(T sample); // reset - clear the filter - next sample added will become the new base value virtual void reset() { _base_value_set = false; }; // reset - clear the filter and provide the new base value virtual void reset( T new_base_value ) { _base_value = new_base_value; _base_value_set = true;}; private: float _gain; // gain value (like 0.02) applied to each new value bool _base_value_set; // true if the base value has been set float _base_value; // the number of samples in the filter, maxes out at size of the filter }; // Typedef for convenience (1st argument is the data type, 2nd is a larger datatype to handle overflows, 3rd is buffer size) typedef LowPassFilter LowPassFilterInt8; typedef LowPassFilter LowPassFilterUInt8; typedef LowPassFilter LowPassFilterInt16; typedef LowPassFilter LowPassFilterUInt16; typedef LowPassFilter LowPassFilterInt32; typedef LowPassFilter LowPassFilterUInt32; typedef LowPassFilter LowPassFilterFloat; // Constructor ////////////////////////////////////////////////////////////// template LowPassFilter::LowPassFilter(float gain) : Filter(), _gain(gain), _base_value_set(false) { // bounds checking on _gain if( _gain > 1.0) { _gain = 1.0; }else if( _gain < 0.0 ) { _gain = 0.0; } }; // Public Methods ////////////////////////////////////////////////////////////// template T LowPassFilter::apply(T sample) { // initailise _base_value if required if( ! _base_value_set ) { _base_value = sample; _base_value_set = true; } // do the filtering _base_value = _gain * (float)sample + (1.0 - _gain) * _base_value; // return the value. Should be no need to check limits return (T)_base_value; } #endif