Here's a single-pole low-pass filter (moving average, with cutoff frequency = CutoffFrequency). Very simple, very fast, works great, and almost no memory overhead.
Note: All variables have scope beyond the filter function, except the passed in newInput
// One-time calculations (can be pre-calculated at compile-time and loaded with constants)
DecayFactor = exp(-2.0 * PI * CutoffFrequency / SampleRate);
AmplitudeFactor = (1.0 - DecayFactor);
// Filter Loop Function ----- THIS IS IT -----
double Filter(double newInput)
MovingAverage *= DecayFactor;
MovingAverage += AmplitudeFactor * newInput;
Note: This is a single stage filter. Multiple stages can be cascaded together to increase the sharpness of the filter. If you use more than one stage, you'll have to adjust DecayFactor (as relates to the Cutoff-Frequency) to compensate.
And obviously all you need is those two lines placed anywhere, they don't need their own function. This filter does have a ramp-up time before the moving average represents that of the input signal. If you need to bypass that ramp-up time, you can just initialize MovingAverage to the first value of newInput instead of 0, and hope the first newInput isn't an outlier.
(CutoffFrequency/SampleRate) has a range of between 0 and 0.5.
DecayFactor is a value between 0 and 1, usually close to 1.
Single-precision floats are good enough for most things, I just prefer doubles. If you need to stick with integers, you can convert DecayFactor and Amplitude Factor into fractional integers, in which the numerator is stored as the integer, and the denominator is an integer power of 2 (so you can bit-shift to the right as the denominator rather than having to divide during the filter loop). For example, if DecayFactor = 0.99, and you want to use integers, you can set DecayFactor = 0.99 * 65536 = 64881. And then anytime you multiply by DecayFactor in your filter loop, just shift the result >> 16.
For more information on this, an excellent book that's online, chapter 19 on recursive filters:
P.S. For the Moving Average paradigm, a different approach to setting DecayFactor and AmplitudeFactor that may be more relevant to your needs, let's say you want the previous, about 6 items averaged together, doing it discretely, you'd add 6 items and divide by 6, so you can set the AmplitudeFactor to 1/6, and DecayFactor to (1.0 - AmplitudeFactor).