annotate src/MedianFilter.h @ 167:416b555df3b2 finetune

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