To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / Peaks.cpp

History | View | Annotate | Download (5.32 KB)

1 4:c06cf6f7cb04 Chris
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2
3
/*
4
  Vamp feature extraction plugin for the BeatRoot beat tracker.
5

6
  Centre for Digital Music, Queen Mary, University of London.
7
  This file copyright 2011 Simon Dixon, Chris Cannam and QMUL.
8

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