arduino-audio-tools
MedianFilter.h
1 #pragma once
2 #include "Filter.h"
3 
4 namespace audio_tools {
5 
13 template <typename T>
14 class MedianFilter : public Filter<T> {
15  public:
16  MedianFilter(int size = 7) {
17  medianBuffer.resize(size);
18  medianFilter.numNodes = size;
19  medianFilter.medianBuffer = medianBuffer.data();
20  init(&medianFilter);
21  };
22 
23  virtual T process(T in) override { return insert(&medianFilter, in); }
24 
25  protected:
26  struct MedianNode_t {
27  T value = 0; // sample value
28  struct MedianNode_t *nextAge = nullptr; // pointer to next oldest value
29  struct MedianNode_t *nextValue = nullptr; // pointer to next smallest value
30  struct MedianNode_t *prevValue =
31  nullptr; // pointer to previous smallest value
32  };
33 
34  struct MedianFilter_t {
35  unsigned int numNodes = 0; // median node buffer length
36  MedianNode_t *medianBuffer = nullptr; // median node buffer
37  MedianNode_t *ageHead = nullptr; // pointer to oldest value
38  MedianNode_t *valueHead = nullptr; // pointer to smallest value
39  MedianNode_t *medianHead = nullptr; // pointer to median value
40  };
41 
42  MedianFilter_t medianFilter;
43  Vector<MedianNode_t> medianBuffer{0};
44 
45  int init(MedianFilter_t *medianFilter) {
46  if (medianFilter && medianFilter->medianBuffer &&
47  (medianFilter->numNodes % 2) && (medianFilter->numNodes > 1)) {
48  // initialize buffer nodes
49  for (unsigned int i = 0; i < medianFilter->numNodes; i++) {
50  medianFilter->medianBuffer[i].value = 0;
51  medianFilter->medianBuffer[i].nextAge =
52  &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
53  medianFilter->medianBuffer[i].nextValue =
54  &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
55  medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes].prevValue =
56  &medianFilter->medianBuffer[i];
57  }
58  // initialize heads
59  medianFilter->ageHead = medianFilter->medianBuffer;
60  medianFilter->valueHead = medianFilter->medianBuffer;
61  medianFilter->medianHead =
62  &medianFilter->medianBuffer[medianFilter->numNodes / 2];
63 
64  return 0;
65  }
66 
67  return -1;
68  }
69 
70  int insert(MedianFilter_t *medianFilter, T sample) {
71  unsigned int i;
72  MedianNode_t *newNode=nullptr, *it=nullptr;
73 
74  if (medianFilter->ageHead == medianFilter->valueHead) {
75  // if oldest node is also the smallest node, increment value head
76  medianFilter->valueHead = medianFilter->valueHead->nextValue;
77  }
78 
79  if ((medianFilter->ageHead == medianFilter->medianHead) ||
80  (medianFilter->ageHead->value > medianFilter->medianHead->value)) {
81  // prepare for median correction
82  medianFilter->medianHead = medianFilter->medianHead->prevValue;
83  }
84 
85  // replace age head with new sample
86  newNode = medianFilter->ageHead;
87  newNode->value = sample;
88 
89  // remove age head from list
90  medianFilter->ageHead->nextValue->prevValue =
91  medianFilter->ageHead->prevValue;
92  medianFilter->ageHead->prevValue->nextValue =
93  medianFilter->ageHead->nextValue;
94  // increment age head
95  medianFilter->ageHead = medianFilter->ageHead->nextAge;
96 
97  // find new node position
98  it = medianFilter->valueHead; // set iterator as value head
99  for (i = 0; i < medianFilter->numNodes - 1; i++) {
100  if (sample < it->value) {
101  if (i == 0) { // replace value head if new node is the smallest
102  medianFilter->valueHead = newNode;
103  }
104  break;
105  }
106  it = it->nextValue;
107  }
108 
109  // insert new node in list
110  it->prevValue->nextValue = newNode;
111  newNode->prevValue = it->prevValue;
112  it->prevValue = newNode;
113  newNode->nextValue = it;
114 
115  // adjust median node
116  if (i >= (medianFilter->numNodes / 2)) {
117  medianFilter->medianHead = medianFilter->medianHead->nextValue;
118  }
119 
120  return medianFilter->medianHead->value;
121  }
122 };
123 
124 } // namespace audio_tools
Abstract filter interface definition;.
Definition: Filter.h:28
An embedded friendly, fast one-dimensional median filter algorithm implementation in C and C++ Useful...
Definition: MedianFilter.h:14
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
Definition: MedianFilter.h:34
Definition: MedianFilter.h:26