annotate Peaks.cpp @ 37:1f175ae200a6 tip

Update RDF
author Chris Cannam
date Wed, 25 Jun 2014 13:48:49 +0100
parents 6afcb5edd7ab
children
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@22 32 if (stop > (int)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@22 43 else if (j < (int)peaks.size())
Chris@15 44 peaks[j] = peaks[j-1];
Chris@15 45 }
Chris@22 46 if (j != (int)peaks.size())
Chris@15 47 peaks[j] = maxp;
Chris@22 48 if (peakCount != (int)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@18 61 if (data.empty()) return peaks;
Chris@15 62 int end = data.size();
Chris@15 63 double av = data[0];
Chris@15 64 while (mid < end) {
Chris@15 65 av = decayRate * av + (1 - decayRate) * data[mid];
Chris@15 66 if (av < data[mid])
Chris@15 67 av = data[mid];
Chris@15 68 int i = mid - width;
Chris@15 69 if (i < 0)
Chris@15 70 i = 0;
Chris@15 71 int stop = mid + width + 1;
Chris@22 72 if (stop > (int)data.size())
Chris@15 73 stop = data.size();
Chris@15 74 maxp = i;
Chris@15 75 for (i++; i < stop; i++)
Chris@15 76 if (data[i] > data[maxp])
Chris@15 77 maxp = i;
Chris@15 78 if (maxp == mid) {
Chris@15 79 if (overThreshold(data, maxp, width, threshold, isRelative,av)){
Chris@15 80 peaks.push_back(maxp);
Chris@15 81 }
Chris@15 82 }
Chris@15 83 mid++;
Chris@15 84 }
Chris@15 85 return peaks;
Chris@15 86 } // findPeaks()
Chris@15 87
Chris@15 88 double Peaks::expDecayWithHold(double av, double decayRate,
Chris@15 89 const vector<double> &data, int start, int stop) {
Chris@15 90 while (start < stop) {
Chris@15 91 av = decayRate * av + (1 - decayRate) * data[start];
Chris@15 92 if (av < data[start])
Chris@15 93 av = data[start];
Chris@15 94 start++;
Chris@15 95 }
Chris@15 96 return av;
Chris@15 97 } // expDecayWithHold()
Chris@15 98
Chris@15 99 bool Peaks::overThreshold(const vector<double> &data, int index, int width,
Chris@15 100 double threshold, bool isRelative,
Chris@15 101 double av) {
Chris@15 102 if (data[index] < av)
Chris@15 103 return false;
Chris@15 104 if (isRelative) {
Chris@15 105 int iStart = index - pre * width;
Chris@15 106 if (iStart < 0)
Chris@15 107 iStart = 0;
Chris@15 108 int iStop = index + post * width;
Chris@22 109 if (iStop > (int)data.size())
Chris@15 110 iStop = data.size();
Chris@15 111 double sum = 0;
Chris@15 112 int count = iStop - iStart;
Chris@15 113 while (iStart < iStop)
Chris@15 114 sum += data[iStart++];
Chris@15 115 return (data[index] > sum / count + threshold);
Chris@15 116 } else
Chris@15 117 return (data[index] > threshold);
Chris@15 118 } // overThreshold()
Chris@15 119
Chris@15 120 void Peaks::normalise(vector<double> &data) {
Chris@15 121 double sx = 0;
Chris@15 122 double sxx = 0;
Chris@22 123 for (int i = 0; i < (int)data.size(); i++) {
Chris@15 124 sx += data[i];
Chris@15 125 sxx += data[i] * data[i];
Chris@15 126 }
Chris@15 127 double mean = sx / data.size();
Chris@15 128 double sd = sqrt((sxx - sx * mean) / data.size());
Chris@15 129 if (sd == 0)
Chris@15 130 sd = 1; // all data[i] == mean -> 0; avoids div by 0
Chris@22 131 for (int i = 0; i < (int)data.size(); i++) {
Chris@15 132 data[i] = (data[i] - mean) / sd;
Chris@15 133 }
Chris@15 134 } // normalise()
Chris@15 135
Chris@15 136 /** Uses an n-point linear regression to estimate the slope of data.
Chris@15 137 * @param data input data
Chris@15 138 * @param hop spacing of data points
Chris@15 139 * @param n length of linear regression
Chris@15 140 * @param slope output data
Chris@15 141 */
Chris@15 142 void Peaks::getSlope(const vector<double> &data, double hop, int n,
Chris@15 143 vector<double> &slope) {
Chris@15 144 int i = 0, j = 0;
Chris@15 145 double t;
Chris@15 146 double sx = 0, sxx = 0, sy = 0, sxy = 0;
Chris@15 147 for ( ; i < n; i++) {
Chris@15 148 t = i * hop;
Chris@15 149 sx += t;
Chris@15 150 sxx += t * t;
Chris@15 151 sy += data[i];
Chris@15 152 sxy += t * data[i];
Chris@15 153 }
Chris@15 154 double delta = n * sxx - sx * sx;
Chris@15 155 for ( ; j < n / 2; j++)
Chris@15 156 slope[j] = (n * sxy - sx * sy) / delta;
Chris@22 157 for ( ; j < (int)data.size() - (n + 1) / 2; j++, i++) {
Chris@15 158 slope[j] = (n * sxy - sx * sy) / delta;
Chris@15 159 sy += data[i] - data[i - n];
Chris@15 160 sxy += hop * (n * data[i] - sy);
Chris@15 161 }
Chris@22 162 for ( ; j < (int)data.size(); j++)
Chris@15 163 slope[j] = (n * sxy - sx * sy) / delta;
Chris@15 164 } // getSlope()
Chris@15 165
Chris@15 166 int Peaks::imin(const vector<double> &arr) {
Chris@15 167 int i = 0;
Chris@22 168 for (int j = 1; j < (int)arr.size(); j++)
Chris@15 169 if (arr[j] < arr[i])
Chris@15 170 i = j;
Chris@15 171 return i;
Chris@15 172 } // imin()
Chris@15 173
Chris@15 174 int Peaks::imax(const vector<double> &arr) {
Chris@15 175 int i = 0;
Chris@22 176 for (int j = 1; j < (int)arr.size(); j++)
Chris@15 177 if (arr[j] > arr[i])
Chris@15 178 i = j;
Chris@15 179 return i;
Chris@15 180 } // imax()
Chris@15 181