Revision 43:53260757fc9f PeakInterpolator.cpp
| PeakInterpolator.cpp | ||
|---|---|---|
| 57 | 57 |
double |
| 58 | 58 |
PeakInterpolator::findPeakLocation(const double *data, int size, int peakIndex) |
| 59 | 59 |
{
|
| 60 |
// std::cerr << "findPeakLocation: size " << size << ", peakIndex " << peakIndex << std::endl; |
|
| 60 |
// after jos, |
|
| 61 |
// https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html |
|
| 61 | 62 |
|
| 62 | 63 |
if (peakIndex < 1 || peakIndex > size - 2) {
|
| 63 |
// std::cerr << "returning " << peakIndex << ", data too short" << std::endl; |
|
| 64 | 64 |
return peakIndex; |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 |
double maxval = 0.0; |
|
| 68 |
double location = peakIndex; |
|
| 67 |
double alpha = data[peakIndex-1]; |
|
| 68 |
double beta = data[peakIndex]; |
|
| 69 |
double gamma = data[peakIndex+1]; |
|
| 69 | 70 |
|
| 70 |
const int divisions = 10; |
|
| 71 |
double y[4]; |
|
| 71 |
double denom = (alpha - 2*beta + gamma); |
|
| 72 | 72 |
|
| 73 |
y[0] = data[peakIndex-1]; |
|
| 74 |
y[1] = data[peakIndex]; |
|
| 75 |
y[2] = data[peakIndex+1]; |
|
| 76 |
if (peakIndex < size - 2) {
|
|
| 77 |
y[3] = data[peakIndex+2]; |
|
| 78 |
} else {
|
|
| 79 |
y[3] = y[2]; |
|
| 80 |
} |
|
| 81 |
// std::cerr << "a y: " << y[0] << " " << y[1] << " " << y[2] << " " << y[3] << std::endl; |
|
| 82 |
for (int i = 0; i < divisions; ++i) {
|
|
| 83 |
double probe = double(i) / double(divisions); |
|
| 84 |
double value = cubicInterpolate(y, probe); |
|
| 85 |
// std::cerr << "probe = " << probe << ", value = " << value << " for location " << peakIndex + probe << std::endl; |
|
| 86 |
if (value > maxval) {
|
|
| 87 |
maxval = value; |
|
| 88 |
location = peakIndex + probe; |
|
| 89 |
} |
|
| 73 |
if (denom == 0) {
|
|
| 74 |
// flat |
|
| 75 |
return peakIndex; |
|
| 90 | 76 |
} |
| 91 | 77 |
|
| 92 |
y[3] = y[2]; |
|
| 93 |
y[2] = y[1]; |
|
| 94 |
y[1] = y[0]; |
|
| 95 |
if (peakIndex > 1) {
|
|
| 96 |
y[0] = data[peakIndex-2]; |
|
| 97 |
} else {
|
|
| 98 |
y[0] = y[1]; |
|
| 99 |
} |
|
| 100 |
// std::cerr << "b y: " << y[0] << " " << y[1] << " " << y[2] << " " << y[3] << std::endl; |
|
| 101 |
for (int i = 0; i < divisions; ++i) {
|
|
| 102 |
double probe = double(i) / double(divisions); |
|
| 103 |
double value = cubicInterpolate(y, probe); |
|
| 104 |
// std::cerr << "probe = " << probe << ", value = " << value << " for location " << peakIndex - 1 + probe << std::endl; |
|
| 105 |
if (value > maxval) {
|
|
| 106 |
maxval = value; |
|
| 107 |
location = peakIndex - 1 + probe; |
|
| 108 |
} |
|
| 109 |
} |
|
| 78 |
double p = ((alpha - gamma) / denom) / 2.0; |
|
| 110 | 79 |
|
| 111 |
// std::cerr << "returning " << location << std::endl; |
|
| 112 |
|
|
| 113 |
return location; |
|
| 80 |
return double(peakIndex) + p; |
|
| 114 | 81 |
} |
| 115 | 82 |
|
Also available in: Unified diff