Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : 16 : #include "ModeFilter.h" 17 : 18 : // Constructor 19 : template <class T, uint8_t FILTER_SIZE> 20 16 : ModeFilter<T,FILTER_SIZE>::ModeFilter(uint8_t return_element) : 21 : FilterWithBuffer<T,FILTER_SIZE>(), 22 16 : _return_element(return_element), 23 16 : drop_high_sample(true) 24 : { 25 : // ensure we have a valid return_nth_element value. if not, revert to median 26 16 : if ( _return_element >= FILTER_SIZE ) { 27 4 : _return_element = FILTER_SIZE / 2; 28 : } 29 16 : } 30 : 31 : // Public Methods ////////////////////////////////////////////////////////////// 32 : 33 : template <class T, uint8_t FILTER_SIZE> 34 256348 : T ModeFilter<T,FILTER_SIZE>::apply(T sample) 35 : { 36 : // insert the new items into the samples buffer 37 256348 : isort(sample, drop_high_sample); 38 : 39 : // next time drop from the other end of the sample buffer 40 256348 : drop_high_sample = !drop_high_sample; 41 : 42 : // return results 43 256348 : if (FilterWithBuffer<T,FILTER_SIZE>::sample_index < FILTER_SIZE ) { 44 : // middle sample if buffer is not yet full 45 52 : return _output = FilterWithBuffer<T,FILTER_SIZE>::samples[(FilterWithBuffer<T,FILTER_SIZE>::sample_index / 2)]; 46 : } else { 47 : // return element specified by user in constructor 48 256296 : return _output = FilterWithBuffer<T,FILTER_SIZE>::samples[_return_element]; 49 : } 50 : } 51 : 52 : // 53 : // insertion sort - takes a new sample and pushes it into the sample array 54 : // drops either the highest or lowest sample depending on the 'drop_high_sample' parameter 55 : // 56 : template <class T, uint8_t FILTER_SIZE> 57 256348 : void ModeFilter<T,FILTER_SIZE>::isort(T new_sample, bool drop_high) 58 : { 59 : int8_t i; 60 : 61 : // if the buffer isn't full simply increase the #items in the buffer (i.e. sample_index) 62 : // the rest is the same as dropping the high sample 63 256348 : if ( FilterWithBuffer<T,FILTER_SIZE>::sample_index < FILTER_SIZE ) { 64 66 : FilterWithBuffer<T,FILTER_SIZE>::sample_index++; 65 66 : drop_high = true; 66 : } 67 : 68 256348 : if ( drop_high ) { // drop highest sample from the buffer to make room for our new sample 69 : 70 : // start from top. Note: sample_index always points to the next open space so we start from sample_index-1 71 128201 : i = FilterWithBuffer<T,FILTER_SIZE>::sample_index-1; 72 : 73 : // if the next element is higher than our new sample, push it up one position 74 145666 : while (i > 0 && FilterWithBuffer<T,FILTER_SIZE>::samples[i-1] > new_sample) { 75 17465 : FilterWithBuffer<T,FILTER_SIZE>::samples[i] = FilterWithBuffer<T,FILTER_SIZE>::samples[i-1]; 76 17465 : i--; 77 : } 78 : 79 : // add our new sample to the buffer 80 128201 : FilterWithBuffer<T,FILTER_SIZE>::samples[i] = new_sample; 81 : 82 : } else { // drop lowest sample from the buffer to make room for our new sample 83 : 84 : // start from the bottom 85 128147 : i = 0; 86 : 87 : // if the element is lower than our new sample, push it down one position 88 146366 : while ( i < FilterWithBuffer<T,FILTER_SIZE>::sample_index-1 && FilterWithBuffer<T,FILTER_SIZE>::samples[i+1] < new_sample ) { 89 18219 : FilterWithBuffer<T,FILTER_SIZE>::samples[i] = FilterWithBuffer<T,FILTER_SIZE>::samples[i+1]; 90 18219 : i++; 91 : } 92 : 93 : // add our new sample to the buffer 94 128147 : FilterWithBuffer<T,FILTER_SIZE>::samples[i] = new_sample; 95 : } 96 256348 : } 97 : 98 : // instantiate required implementations 99 : template class ModeFilter<float,5>; 100 : template class ModeFilter<int16_t,3>; 101 : template class ModeFilter<int16_t,5>; 102 : template class ModeFilter<uint16_t,3>;