C++ Implementation
C++ Implementation
C++ Implementation
C++ Implementation
Pieter P
N −1
1
y[n] = ∑ x[n − i] (1)
N
i=0
A naive approach would be to implement the difference equation directly: keeping the last N − 1 inputs, and calculate the sum on
each iteration, calculating N − 1 additions at each time step.
However, we can do much better if we notice how only two terms of the sum change each time:
N −1
1
y[n + 1] = ∑ x[n + 1 − i]
N
i=0
N −1
1
= (x[n + 1] + ∑ x[n + 1 − i])
N
i=1
N −1
1
= (x[n + 1] + ∑ x[n + 1 − i] + x[n + 1 − N ] − x[n + 1 − N ])
N
i=1
N
1
= (x[n + 1] + ∑ x[n + 1 − i] − x[n + 1 − N ])
N
i=1
N −1
1
= (x[n + 1] + ∑ x[n − i] − x[n + 1 − N ])
N
i=0
1
= y[n] + (x[n + 1] − x[n + 1 − N ])
N
S[n] ≜ N ⋅ y[n]
N −1
= ∑ x[n − i]
i=0
⇔ y[n] = S[n]/N
To update the sum, each iteration now requires only one addition and one subtraction, as well as some housekeeping to remember
the previous inputs. To get the output y[n], a division by N is needed.
C++ Implementation
We can now implement Equation 2 directly, and we'll use a rounding division instead of truncating the quotient. Note that this
rounding operation is valid for unsigned integer types only.
The previous inputs x[n − i] are kept in a circular buffer.
SMA.cpp
1 #include <stdint.h>
2
3 template <uint8_t N, class input_t = uint16_t, class sum_t = uint32_t>
4 class SMA {
5 public:
6 input_t operator()(input_t input) {
7 sum -= previousInputs[index];
8 sum += input;
9 previousInputs[index] = input;
10 if (++index == N)
11 index = 0;
12 return (sum + (N / 2)) / N;
13 }
14
15 static_assert(
16 sum_t(0) < sum_t(-1), // Check that `sum_t` is an unsigned type
17 "Error: sum data type should be an unsigned integer, otherwise, "
18 "the rounding operation in the return statement is invalid.");
19
20 private:
21 uint8_t index = 0;
22 input_t previousInputs[N] = {};
23 sum_t sum = 0;
24 };
Arduino Example
As a basic example, you can use this filter for smoothing analog inputs on microcontrollers. Keep in mind that an exponential
moving average filter is often more appropriate than a simple moving average filter. The SMA uses much more memory, and is
much slower than the EMA. The exponential impulse response of the EMA may be better as well.
You can find an Arduino example using an EMA here.