changeset 11:0c95dc49163a track

Some work on accepting/rejecting peaks
author Chris Cannam
date Tue, 26 Jun 2012 16:06:00 +0100
parents 960868d5f841
children cb88b9954eec
files CepstrumPitchTracker.cpp CepstrumPitchTracker.h
diffstat 2 files changed, 82 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/CepstrumPitchTracker.cpp	Tue Jun 26 15:30:12 2012 +0100
+++ b/CepstrumPitchTracker.cpp	Tue Jun 26 16:06:00 2012 +0100
@@ -43,7 +43,9 @@
     m_binFrom(0),
     m_binTo(0),
     m_bins(0),
-    m_history(0)
+    m_history(0),
+    m_prevpeak(0),
+    m_prevprop(0)
 {
 }
 
@@ -270,6 +272,41 @@
     }
 }
 
+double
+CepstrumPitchTracker::calculatePeakProportion(const double *data, double abstot, int n)
+{
+    double aroundPeak = data[n];
+    double peakProportion = 0.0;
+
+    int i = n - 1;
+    while (i > 0 && data[i] <= data[i+1]) {
+        aroundPeak += fabs(data[i]);
+        --i;
+    }
+    i = n + 1;
+    while (i < m_bins && data[i] <= data[i-1]) {
+        aroundPeak += fabs(data[i]);
+        ++i;
+    }
+    peakProportion = aroundPeak / abstot;
+
+    return peakProportion;
+}
+
+bool
+CepstrumPitchTracker::acceptPeak(int n, double peakProportion)
+{
+    bool accept = false;
+
+    if (abs(n - m_prevpeak) < 10) { //!!! should depend on bin count
+        accept = true;
+    } else if (peakProportion > m_prevprop * 2) {
+        accept = true;
+    }
+
+    return accept;
+}
+
 CepstrumPitchTracker::FeatureSet
 CepstrumPitchTracker::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
 {
@@ -307,40 +344,60 @@
     filter(rawcep, data);
     delete[] rawcep;
 
+    double abstot = 0.0;
+
+    for (int i = 0; i < n; ++i) {
+	abstot += fabs(data[i]);
+    }
+
     double maxval = 0.0;
-    int maxbin = 0;
-    double abstot = 0.0;
+    int maxbin = -1;
 
     for (int i = 0; i < n; ++i) {
         if (data[i] > maxval) {
             maxval = data[i];
             maxbin = i;
         }
-	abstot += fabs(data[i]);
     }
 
-    double aroundPeak = 0.0;
-    double peakProportion = 0.0;
-    if (maxval > 0.0) {
-        aroundPeak += fabs(maxval);
-        int i = maxbin - 1;
-        while (i > 0 && data[i] <= data[i+1]) {
-            aroundPeak += fabs(data[i]);
-            --i;
+    bool accepted = false;
+
+    if (maxbin >= 0) {
+        double pp = calculatePeakProportion(data, abstot, maxbin);
+        if (acceptPeak(maxbin, pp)) {
+            accepted = true;
+        } else {
+            // try a secondary peak
+            maxval = 0.0;
+            int secondbin = 0;
+            for (int i = 1; i < n-1; ++i) {
+                if (i != maxbin &&
+                    data[i] > data[i-1] &&
+                    data[i] > data[i+1] &&
+                    data[i] > maxval) {
+                    maxval = data[i];
+                    secondbin = i;
+                }
+            }
+            double spp = calculatePeakProportion(data, abstot, secondbin);
+            if (acceptPeak(secondbin, spp)) {
+                maxbin = secondbin;
+                pp = spp;
+                accepted = true;
+            }
         }
-        i = maxbin + 1;
-        while (i < n && data[i] <= data[i-1]) {
-            aroundPeak += fabs(data[i]);
-            ++i;
+        if (accepted) {
+            m_prevpeak = maxbin;
+            m_prevprop = pp;
         }
     }
-    peakProportion = aroundPeak / abstot;
-
+            
 //    std::cerr << "peakProportion = " << peakProportion << std::endl;
 //    std::cerr << "peak = " << m_inputSampleRate / (maxbin + m_binFrom) << std::endl;
 //    std::cerr << "bins = " << m_bins << std::endl;
 
-    if (peakProportion >= (0.00006 * m_bins)) {
+//    if (peakProportion >= (0.00006 * m_bins)) {
+    if (accepted) {
 	Feature f;
 	f.hasTimestamp = true;
 	f.timestamp = timestamp;
--- a/CepstrumPitchTracker.h	Tue Jun 26 15:30:12 2012 +0100
+++ b/CepstrumPitchTracker.h	Tue Jun 26 16:06:00 2012 +0100
@@ -77,6 +77,12 @@
 
     double **m_history;
     
+    int m_prevpeak;
+    double m_prevprop;
+
+    double calculatePeakProportion(const double *data, double abstot, int n);
+    bool acceptPeak(int n, double peakProportion);
+
     void filter(const double *in, double *out);
     void fft(unsigned int n, bool inverse,
              double *ri, double *ii, double *ro, double *io);