Revision 43:53260757fc9f PeakInterpolator.cpp

View differences:

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