changeset 180:2931089cda46 f0

Have a first go at reporting f0
author Chris Cannam
date Thu, 22 May 2014 16:59:12 +0100
parents 825193ef09d2
children
files .hgsubstate Makefile.inc src/Silvet.cpp src/Silvet.h
diffstat 4 files changed, 83 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsubstate	Thu May 22 15:06:37 2014 +0100
+++ b/.hgsubstate	Thu May 22 16:59:12 2014 +0100
@@ -1,2 +1,2 @@
 a2621605a8c2119bb063c59e83f4fe792a58e4ac bqvec
-c7d17fcd215cd2ab66b66c5b89651932cd22d355 constant-q-cpp
+c2af8467fce06b2cc259dc8ad279b5019aaf2fbe constant-q-cpp
--- a/Makefile.inc	Thu May 22 15:06:37 2014 +0100
+++ b/Makefile.inc	Thu May 22 16:59:12 2014 +0100
@@ -19,8 +19,8 @@
 
 PLUGIN	:= silvet$(PLUGIN_EXT)
 
-PLUGIN_HEADERS := $(SRC_DIR)/Silvet.h $(SRC_DIR)/EM.h $(SRC_DIR)/Instruments.h
-PLUGIN_SOURCES := $(SRC_DIR)/Silvet.cpp $(SRC_DIR)/EM.cpp $(SRC_DIR)/Instruments.cpp $(SRC_DIR)/libmain.cpp
+PLUGIN_HEADERS := $(SRC_DIR)/Silvet.h $(SRC_DIR)/EM.h $(SRC_DIR)/Instruments.h $(SRC_DIR)/MedianFilter.h $(SRC_DIR)/PeakInterpolator.h
+PLUGIN_SOURCES := $(SRC_DIR)/Silvet.cpp $(SRC_DIR)/EM.cpp $(SRC_DIR)/Instruments.cpp $(SRC_DIR)/PeakInterpolator.cpp $(SRC_DIR)/libmain.cpp
 
 BQVEC_HEADERS	:= $(BQVEC_DIR)/Allocators.h $(BQVEC_DIR)/Restrict.h $(BQVEC_DIR)/VectorOps.h
 BQVEC_SOURCES	:= $(BQVEC_DIR)/Allocators.cpp
@@ -49,7 +49,7 @@
 # DO NOT DELETE
 
 src/Silvet.o: src/Silvet.h src/MedianFilter.h src/Instruments.h src/EM.h
-src/Silvet.o: constant-q-cpp/src/dsp/Resampler.h
+src/Silvet.o: src/PeakInterpolator.h constant-q-cpp/src/dsp/Resampler.h
 src/EM.o: src/EM.h src/Instruments.h
 src/Instruments.o: src/Instruments.h data/include/templates.h
 src/Instruments.o: data/include/bassoon.h data/include/cello.h
@@ -58,6 +58,7 @@
 src/Instruments.o: data/include/oboe.h data/include/tenorsax.h
 src/Instruments.o: data/include/violin.h data/include/piano1.h
 src/Instruments.o: data/include/piano2.h data/include/piano3.h
+src/PeakInterpolator.o: src/PeakInterpolator.h
 src/libmain.o: src/Silvet.h src/MedianFilter.h src/Instruments.h
 bqvec/src/Allocators.o: bqvec/src/Allocators.h bqvec/src/VectorOps.h
 bqvec/src/Allocators.o: bqvec/src/Restrict.h
--- a/src/Silvet.cpp	Thu May 22 15:06:37 2014 +0100
+++ b/src/Silvet.cpp	Thu May 22 16:59:12 2014 +0100
@@ -19,6 +19,8 @@
 #include <cq/CQSpectrogram.h>
 
 #include "MedianFilter.h"
+#include "PeakInterpolator.h"
+
 #include "constant-q-cpp/src/dsp/Resampler.h"
 
 #include <vector>
@@ -241,6 +243,21 @@
     m_notesOutputNo = list.size();
     list.push_back(d);
 
+    d.identifier = "f0";
+    d.name = "Predominant fundamental frequency";
+    d.description = "Interpolated frequency of fundamental of most salient pitch at each time frame";
+    d.unit = "Hz";
+    d.hasFixedBinCount = true;
+    d.binCount = 1;
+    d.binNames.push_back("Frequency");
+    d.hasKnownExtents = false;
+    d.isQuantized = false;
+    d.sampleType = OutputDescriptor::FixedSampleRate;
+    d.sampleRate = m_colsPerSec;
+    d.hasDuration = false;
+    m_f0OutputNo = list.size();
+    list.push_back(d);
+
     d.identifier = "timefreq";
     d.name = "Time-frequency distribution";
     d.description = "Filtered constant-Q time-frequency distribution used as input to the expectation-maximisation algorithm";
@@ -521,6 +538,13 @@
         }
 
         postProcess(localPitches[i], localBestShifts[i], wantShifts);
+
+        FeatureList f0Features = convertF0Features(filtered[i], shiftCount);
+        
+        for (FeatureList::const_iterator fi = f0Features.begin();
+             fi != f0Features.end(); ++fi) {
+            fs[m_f0OutputNo].push_back(*fi);
+        }
         
         FeatureList noteFeatures = noteTrack(shiftCount);
 
@@ -654,6 +678,9 @@
     map<int, double> active;
     map<int, int> activeShifts;
 
+    m_predominantNote = -1;
+    m_predominantShift = -1;
+
     while (int(active.size()) < polyphony && si != strengths.begin()) {
 
         --si;
@@ -663,8 +690,17 @@
 
         active[j] = strength;
 
+        if (m_predominantNote < 0) {
+            m_predominantNote = j;
+        }
+
         if (wantShifts) {
+
             activeShifts[j] = bestShifts[j];
+
+            if (m_predominantShift < 0) {
+                m_predominantShift = bestShifts[j];
+            }
         }
     }
 
@@ -676,6 +712,43 @@
 }
 
 Vamp::Plugin::FeatureList
+Silvet::convertF0Features(const vector<double> &column, int shiftCount)
+{
+    FeatureList fl;
+
+    if (m_predominantNote < 0) {
+        Feature f;
+        f.hasTimestamp = false;
+        f.hasDuration = false;
+        f.values.push_back(0.f);
+        fl.push_back(f);
+        return fl;
+    }
+
+    int f0bin = m_predominantNote * shiftCount;
+
+    if (m_predominantShift >= 0) {
+        f0bin += (shiftCount - m_predominantShift) - int(shiftCount / 2) - 1;
+    }
+
+    PeakInterpolator pi;
+    float interpolated = (float)pi.findPeakLocation
+        (column.data(), column.size(), f0bin);
+
+    float f0 = m_cq->getBinFrequency
+        (m_instruments[0].templateHeight - interpolated - 1.f);
+
+    cerr << "note = " << m_predominantNote << " shift = " << m_predominantShift << " f0bin = " << f0bin << " interpolated = " << interpolated << " f0 = " << f0 << endl;
+    
+    Feature f;
+    f.hasTimestamp = false;
+    f.hasDuration = false;
+    f.values.push_back(f0);
+    fl.push_back(f);
+    return fl;
+}
+
+Vamp::Plugin::FeatureList
 Silvet::noteTrack(int shiftCount)
 {        
     // Minimum duration pruning, and conversion to notes. We can only
--- a/src/Silvet.h	Thu May 22 15:06:37 2014 +0100
+++ b/src/Silvet.h	Thu May 22 16:59:12 2014 +0100
@@ -86,6 +86,8 @@
     vector<MedianFilter<double> *> m_postFilter;
     vector<map<int, double> > m_pianoRoll;
     vector<map<int, int> > m_pianoRollShifts;
+    int m_predominantNote;
+    int m_predominantShift;
 
     Grid preProcess(const Grid &);
 
@@ -93,6 +95,8 @@
                      const vector<int> &bestShifts,
                      bool wantShifts); // -> piano roll column
 
+    FeatureList convertF0Features(const vector<double> &cq, int shiftCount);
+
     FeatureList noteTrack(int shiftCount);
 
     void emitNote(int start, int end, int note, int shiftCount,
@@ -109,6 +113,7 @@
 
     mutable int m_notesOutputNo;
     mutable int m_fcqOutputNo;
+    mutable int m_f0OutputNo;
 };
 
 #endif