Introduction #
Digital filtering is widely used to remove noise from signals in embedded systems, sensor readings, or any data acquisition application. Here, we present 11 common filtering algorithms with generic C++ implementations suitable for microcontrollers, desktop applications, or any C++ environment.
1. Clipping Filter (Limit Filter) #
Rejects abrupt changes beyond a defined threshold.
int filterValue = 300;
int getSample() {
return 295 + rand() % 11; // Simulate a sample around 300
}
int limitFilter(int value, int threshold = 1) {
int newVal = getSample();
if (abs(newVal - value) > threshold) return value;
return newVal;
}
void example() {
filterValue = limitFilter(filterValue);
}
2. Median Filter #
Sorts N consecutive samples and returns the middle value, effective for pulse noise.
#include <vector>
#include <algorithm>
int medianFilter(int N = 101) {
std::vector<int> buf(N);
for (int& v : buf) v = 295 + rand() % 11;
std::sort(buf.begin(), buf.end());
return buf[N / 2];
}
3. Arithmetic Mean Filter #
Averages N consecutive samples to reduce random noise.
int meanFilter(int N = 12) {
int sum = 0;
for (int i = 0; i < N; ++i) sum += 295 + rand() % 11;
return sum / N;
}
4. Recursive (Moving Average) Filter #
A sliding window average filter with efficient incremental updates.
#include <array>
constexpr int N = 12;
std::array<int, N> buf = {300};
int movingAverageFilter() {
int sum = 0;
int newSample = 295 + rand() % 11;
for (int i = 0; i < N - 1; ++i) {
buf[i] = buf[i + 1];
sum += buf[i];
}
buf[N - 1] = newSample;
sum += buf[N - 1];
return sum / N;
}
5. Median-Mean Filter #
Combines median and arithmetic mean to remove spikes while smoothing.
int medianMeanFilter(int N = 100) {
std::vector<int> buf(N);
for (int& v : buf) v = 295 + rand() % 11;
std::sort(buf.begin(), buf.end());
int sum = 0;
for (int i = 1; i < N - 1; ++i) sum += buf[i];
return sum / (N - 2);
}
6. Limit-Average Filter #
Applies limit filter before moving average to remove spikes and smooth signal.
int limitAverageFilter() {
int newSample = 295 + rand() % 11;
if (abs(newSample - buf[N-2]) > 1) newSample = buf[N-2];
for (int i = 0; i < N - 1; ++i) buf[i] = buf[i+1];
buf[N-1] = newSample;
int sum = 0;
for (int val : buf) sum += val;
return sum / N;
}
7. First-Order Lag Filter #
Implements an exponential smoothing filter:
double value = 300.0;
constexpr double alpha = 0.01;
double lagFilter() {
double newSample = 295 + rand() % 11;
value = alpha * newSample + (1.0 - alpha) * value;
return value;
}
8. Weighted Recursive Filter #
A moving average with weighted coefficients for recent samples.
int weightedFilter() {
std::array<int, N> weights;
for (int i = 0; i < N; ++i) weights[i] = i+1; // increasing weights
int newSample = 295 + rand() % 11;
buf[N] = newSample;
int sum = 0;
int weightSum = 0;
for (int i = 0; i < N; ++i) {
buf[i] = buf[i+1];
sum += buf[i] * weights[i];
weightSum += weights[i];
}
return sum / weightSum;
}
9. Debounce Filter #
Prevents rapid toggling by requiring N consecutive changes to confirm a new value.
int value = 300;
int counter = 0;
int debounceFilter(int N = 12) {
int newSample = 295 + rand() % 11;
if (newSample != value) {
if (++counter >= N) { value = newSample; counter = 0; }
} else counter = 0;
return value;
}
10. Limit-Debounce Filter #
Combines limit and debounce filtering for robust spike removal.
int limitDebounceFilter() {
int newSample = 295 + rand() % 11;
if (abs(newSample - value) > 1) newSample = value;
if (newSample != value) {
if (++counter > 5) { value = newSample; counter = 0; }
} else counter = 0;
return value;
}
11. Kalman Filter (Non-Extended) #
A state-space filter for sensor fusion or noisy measurements.
struct Kalman1D {
double x = 0; // estimated state
double p = 1; // estimated covariance
double q = 0.0025; // process noise
double r = 0.25; // measurement noise
double update(double measurement) {
// Prediction
p += q;
// Kalman gain
double k = p / (p + r);
// Update estimate
x += k * (measurement - x);
// Update covariance
p *= (1 - k);
return x;
}
};
Kalman1D kalmanX;
double filteredValue = kalmanX.update(295 + rand() % 11);
Conclusion #
These 11 algorithms cover a wide range of filtering needs:
- Clipping, median, mean, and moving average filters for simple noise removal.
- Limit-average and weighted filters for robust smoothing.
- Debounce and limit-debounce filters for digital signal stabilization.
- First-order lag and Kalman filters for real-time sensor fusion.
Using modern C++ idioms—vectors, arrays, and RAII—makes the filters safe, maintainable, and portable across embedded and desktop applications.