annotate maths/MedianFilter.h @ 209:ccd2019190bf msvc

Some MSVC fixes, including (temporarily, probably) renaming the FFT source file to avoid getting it mixed up with the Vamp SDK one in our object dir
author Chris Cannam
date Thu, 01 Feb 2018 16:34:08 +0000
parents 5ec47007b873
children fa407c1d9923
rev   line source
Chris@164 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@164 2
Chris@165 3 /*
Chris@165 4 QM DSP Library
Chris@165 5
Chris@165 6 Centre for Digital Music, Queen Mary, University of London.
Chris@165 7 This file Copyright 2010 Chris Cannam.
Chris@165 8
Chris@165 9 This program is free software; you can redistribute it and/or
Chris@165 10 modify it under the terms of the GNU General Public License as
Chris@165 11 published by the Free Software Foundation; either version 2 of the
Chris@165 12 License, or (at your option) any later version. See the file
Chris@165 13 COPYING included with this distribution for more information.
Chris@165 14 */
Chris@165 15
Chris@164 16 #ifndef MEDIAN_FILTER_H
Chris@164 17 #define MEDIAN_FILTER_H
Chris@164 18
Chris@164 19 #include <algorithm>
Chris@164 20 #include <cassert>
Chris@164 21 #include <cmath>
Chris@164 22 #include <iostream>
Chris@167 23 #include <vector>
Chris@164 24
Chris@164 25 template <typename T>
Chris@164 26 class MedianFilter
Chris@164 27 {
Chris@164 28 public:
Chris@164 29 MedianFilter(int size, float percentile = 50.f) :
Chris@164 30 m_size(size),
Chris@164 31 m_frame(new T[size]),
Chris@164 32 m_sorted(new T[size]),
Chris@164 33 m_sortend(m_sorted + size - 1) {
Chris@164 34 setPercentile(percentile);
Chris@164 35 reset();
Chris@164 36 }
Chris@164 37
Chris@164 38 ~MedianFilter() {
Chris@164 39 delete[] m_frame;
Chris@164 40 delete[] m_sorted;
Chris@164 41 }
Chris@164 42
Chris@164 43 void setPercentile(float p) {
Chris@164 44 m_index = int((m_size * p) / 100.f);
Chris@164 45 if (m_index >= m_size) m_index = m_size-1;
Chris@164 46 if (m_index < 0) m_index = 0;
Chris@164 47 }
Chris@164 48
Chris@164 49 void push(T value) {
Chris@169 50 if (value != value) {
Chris@182 51 std::cerr << "WARNING: MedianFilter::push: attempt to push NaN, pushing zero instead" << std::endl;
Chris@182 52 // we do need to push something, to maintain the filter length
Chris@182 53 value = T();
Chris@169 54 }
Chris@164 55 drop(m_frame[0]);
Chris@164 56 const int sz1 = m_size-1;
Chris@164 57 for (int i = 0; i < sz1; ++i) m_frame[i] = m_frame[i+1];
Chris@164 58 m_frame[m_size-1] = value;
Chris@164 59 put(value);
Chris@164 60 }
Chris@164 61
Chris@164 62 T get() const {
Chris@164 63 return m_sorted[m_index];
Chris@164 64 }
Chris@164 65
Chris@168 66 int getSize() const {
Chris@168 67 return m_size;
Chris@168 68 }
Chris@168 69
Chris@164 70 T getAt(float percentile) {
Chris@164 71 int ix = int((m_size * percentile) / 100.f);
Chris@164 72 if (ix >= m_size) ix = m_size-1;
Chris@164 73 if (ix < 0) ix = 0;
Chris@164 74 return m_sorted[ix];
Chris@164 75 }
Chris@164 76
Chris@164 77 void reset() {
Chris@164 78 for (int i = 0; i < m_size; ++i) m_frame[i] = 0;
Chris@164 79 for (int i = 0; i < m_size; ++i) m_sorted[i] = 0;
Chris@164 80 }
Chris@164 81
Chris@167 82 static std::vector<T> filter(int size, const std::vector<T> &in) {
Chris@167 83 std::vector<T> out;
Chris@167 84 MedianFilter<T> f(size);
Chris@167 85 for (int i = 0; i < int(in.size()); ++i) {
Chris@167 86 f.push(in[i]);
Chris@167 87 T median = f.get();
Chris@167 88 if (i >= size/2) out.push_back(median);
Chris@167 89 }
Chris@167 90 while (out.size() < in.size()) {
Chris@167 91 f.push(T());
Chris@167 92 out.push_back(f.get());
Chris@167 93 }
Chris@167 94 return out;
Chris@167 95 }
Chris@167 96
Chris@164 97 private:
Chris@164 98 const int m_size;
Chris@164 99 T *const m_frame;
Chris@164 100 T *const m_sorted;
Chris@164 101 T *const m_sortend;
Chris@164 102 int m_index;
Chris@164 103
Chris@164 104 void put(T value) {
Chris@164 105 // precondition: m_sorted contains m_size-1 values, packed at start
Chris@164 106 // postcondition: m_sorted contains m_size values, one of which is value
Chris@164 107 T *point = std::lower_bound(m_sorted, m_sortend, value);
Chris@164 108 const int n = m_sortend - point;
Chris@164 109 for (int i = n; i > 0; --i) point[i] = point[i-1];
Chris@164 110 *point = value;
Chris@164 111 }
Chris@164 112
Chris@164 113 void drop(T value) {
Chris@164 114 // precondition: m_sorted contains m_size values, one of which is value
Chris@164 115 // postcondition: m_sorted contains m_size-1 values, packed at start
Chris@164 116 T *point = std::lower_bound(m_sorted, m_sortend + 1, value);
Chris@164 117 if (*point != value) {
Chris@164 118 std::cerr << "WARNING: MedianFilter::drop: *point is " << *point
Chris@164 119 << ", expected " << value << std::endl;
Chris@164 120 }
Chris@164 121 const int n = m_sortend - point;
Chris@164 122 for (int i = 0; i < n; ++i) point[i] = point[i+1];
Chris@164 123 *m_sortend = T(0);
Chris@164 124 }
Chris@165 125
Chris@165 126 MedianFilter(const MedianFilter &); // not provided
Chris@165 127 MedianFilter &operator=(const MedianFilter &); // not provided
Chris@164 128 };
Chris@164 129
Chris@164 130 #endif
Chris@164 131