annotate Peaks.cpp @ 15:887c629502a9

refactor: pull method implementations into .cpp files
author Chris Cannam
date Wed, 12 Oct 2011 10:55:52 +0100
parents 4f6626f9ffac
children 55969570044e
rev   line source
Chris@4 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@4 2
Chris@4 3 /*
Chris@4 4 Vamp feature extraction plugin for the BeatRoot beat tracker.
Chris@4 5
Chris@4 6 Centre for Digital Music, Queen Mary, University of London.
Chris@4 7 This file copyright 2011 Simon Dixon, Chris Cannam and QMUL.
Chris@4 8
Chris@4 9 This program is free software; you can redistribute it and/or
Chris@4 10 modify it under the terms of the GNU General Public License as
Chris@4 11 published by the Free Software Foundation; either version 2 of the
Chris@4 12 License, or (at your option) any later version. See the file
Chris@4 13 COPYING included with this distribution for more information.
Chris@4 14 */
Chris@4 15
Chris@4 16 #include "Peaks.h"
Chris@4 17
Chris@9 18 int Peaks::pre = 3;
Chris@9 19 int Peaks::post = 1;
Chris@4 20
Chris@15 21
Chris@15 22 int Peaks::findPeaks(const vector<double> &data, vector<int> peaks, int width) {
Chris@15 23 int peakCount = 0;
Chris@15 24 int maxp = 0;
Chris@15 25 int mid = 0;
Chris@15 26 int end = data.size();
Chris@15 27 while (mid < end) {
Chris@15 28 int i = mid - width;
Chris@15 29 if (i < 0)
Chris@15 30 i = 0;
Chris@15 31 int stop = mid + width + 1;
Chris@15 32 if (stop > data.size())
Chris@15 33 stop = data.size();
Chris@15 34 maxp = i;
Chris@15 35 for (i++; i < stop; i++)
Chris@15 36 if (data[i] > data[maxp])
Chris@15 37 maxp = i;
Chris@15 38 if (maxp == mid) {
Chris@15 39 int j;
Chris@15 40 for (j = peakCount; j > 0; j--) {
Chris@15 41 if (data[maxp] <= data[peaks[j-1]])
Chris@15 42 break;
Chris@15 43 else if (j < peaks.size())
Chris@15 44 peaks[j] = peaks[j-1];
Chris@15 45 }
Chris@15 46 if (j != peaks.size())
Chris@15 47 peaks[j] = maxp;
Chris@15 48 if (peakCount != peaks.size())
Chris@15 49 peakCount++;
Chris@15 50 }
Chris@15 51 mid++;
Chris@15 52 }
Chris@15 53 return peakCount;
Chris@15 54 } // findPeaks()
Chris@15 55
Chris@15 56 vector<int> Peaks::findPeaks(const vector<double> &data, int width,
Chris@15 57 double threshold, double decayRate, bool isRelative) {
Chris@15 58 vector<int> peaks;
Chris@15 59 int maxp = 0;
Chris@15 60 int mid = 0;
Chris@15 61 int end = data.size();
Chris@15 62 double av = data[0];
Chris@15 63 while (mid < end) {
Chris@15 64 av = decayRate * av + (1 - decayRate) * data[mid];
Chris@15 65 if (av < data[mid])
Chris@15 66 av = data[mid];
Chris@15 67 int i = mid - width;
Chris@15 68 if (i < 0)
Chris@15 69 i = 0;
Chris@15 70 int stop = mid + width + 1;
Chris@15 71 if (stop > data.size())
Chris@15 72 stop = data.size();
Chris@15 73 maxp = i;
Chris@15 74 for (i++; i < stop; i++)
Chris@15 75 if (data[i] > data[maxp])
Chris@15 76 maxp = i;
Chris@15 77 if (maxp == mid) {
Chris@15 78 if (overThreshold(data, maxp, width, threshold, isRelative,av)){
Chris@15 79 peaks.push_back(maxp);
Chris@15 80 }
Chris@15 81 }
Chris@15 82 mid++;
Chris@15 83 }
Chris@15 84 return peaks;
Chris@15 85 } // findPeaks()
Chris@15 86
Chris@15 87 double Peaks::expDecayWithHold(double av, double decayRate,
Chris@15 88 const vector<double> &data, int start, int stop) {
Chris@15 89 while (start < stop) {
Chris@15 90 av = decayRate * av + (1 - decayRate) * data[start];
Chris@15 91 if (av < data[start])
Chris@15 92 av = data[start];
Chris@15 93 start++;
Chris@15 94 }
Chris@15 95 return av;
Chris@15 96 } // expDecayWithHold()
Chris@15 97
Chris@15 98 bool Peaks::overThreshold(const vector<double> &data, int index, int width,
Chris@15 99 double threshold, bool isRelative,
Chris@15 100 double av) {
Chris@15 101 if (data[index] < av)
Chris@15 102 return false;
Chris@15 103 if (isRelative) {
Chris@15 104 int iStart = index - pre * width;
Chris@15 105 if (iStart < 0)
Chris@15 106 iStart = 0;
Chris@15 107 int iStop = index + post * width;
Chris@15 108 if (iStop > data.size())
Chris@15 109 iStop = data.size();
Chris@15 110 double sum = 0;
Chris@15 111 int count = iStop - iStart;
Chris@15 112 while (iStart < iStop)
Chris@15 113 sum += data[iStart++];
Chris@15 114 return (data[index] > sum / count + threshold);
Chris@15 115 } else
Chris@15 116 return (data[index] > threshold);
Chris@15 117 } // overThreshold()
Chris@15 118
Chris@15 119 void Peaks::normalise(vector<double> &data) {
Chris@15 120 double sx = 0;
Chris@15 121 double sxx = 0;
Chris@15 122 for (int i = 0; i < data.size(); i++) {
Chris@15 123 sx += data[i];
Chris@15 124 sxx += data[i] * data[i];
Chris@15 125 }
Chris@15 126 double mean = sx / data.size();
Chris@15 127 double sd = sqrt((sxx - sx * mean) / data.size());
Chris@15 128 if (sd == 0)
Chris@15 129 sd = 1; // all data[i] == mean -> 0; avoids div by 0
Chris@15 130 for (int i = 0; i < data.size(); i++) {
Chris@15 131 data[i] = (data[i] - mean) / sd;
Chris@15 132 }
Chris@15 133 } // normalise()
Chris@15 134
Chris@15 135 /** Uses an n-point linear regression to estimate the slope of data.
Chris@15 136 * @param data input data
Chris@15 137 * @param hop spacing of data points
Chris@15 138 * @param n length of linear regression
Chris@15 139 * @param slope output data
Chris@15 140 */
Chris@15 141 void Peaks::getSlope(const vector<double> &data, double hop, int n,
Chris@15 142 vector<double> &slope) {
Chris@15 143 int i = 0, j = 0;
Chris@15 144 double t;
Chris@15 145 double sx = 0, sxx = 0, sy = 0, sxy = 0;
Chris@15 146 for ( ; i < n; i++) {
Chris@15 147 t = i * hop;
Chris@15 148 sx += t;
Chris@15 149 sxx += t * t;
Chris@15 150 sy += data[i];
Chris@15 151 sxy += t * data[i];
Chris@15 152 }
Chris@15 153 double delta = n * sxx - sx * sx;
Chris@15 154 for ( ; j < n / 2; j++)
Chris@15 155 slope[j] = (n * sxy - sx * sy) / delta;
Chris@15 156 for ( ; j < data.size() - (n + 1) / 2; j++, i++) {
Chris@15 157 slope[j] = (n * sxy - sx * sy) / delta;
Chris@15 158 sy += data[i] - data[i - n];
Chris@15 159 sxy += hop * (n * data[i] - sy);
Chris@15 160 }
Chris@15 161 for ( ; j < data.size(); j++)
Chris@15 162 slope[j] = (n * sxy - sx * sy) / delta;
Chris@15 163 } // getSlope()
Chris@15 164
Chris@15 165 int Peaks::imin(const vector<double> &arr) {
Chris@15 166 int i = 0;
Chris@15 167 for (int j = 1; j < arr.size(); j++)
Chris@15 168 if (arr[j] < arr[i])
Chris@15 169 i = j;
Chris@15 170 return i;
Chris@15 171 } // imin()
Chris@15 172
Chris@15 173 int Peaks::imax(const vector<double> &arr) {
Chris@15 174 int i = 0;
Chris@15 175 for (int j = 1; j < arr.size(); j++)
Chris@15 176 if (arr[j] > arr[i])
Chris@15 177 i = j;
Chris@15 178 return i;
Chris@15 179 } // imax()
Chris@15 180