changeset 114:7ef7f6e90966 tony

Merge from branch notes_refinement. Still need to restore the "precise" mode option.
author Chris Cannam
date Mon, 23 Mar 2015 15:58:40 +0000
parents 992e31b26377 (current diff) ae827f6c46c8 (diff)
children 50e39363a3cb
files .hgignore Makefile.inc Makefile.linux64 MonoNoteParameters.cpp MonoPitchHMM.cpp PYinVamp.cpp PYinVamp.h Yin.cpp Yin.h YinVampFreqConstrained.cpp YinVampFreqConstrained.h libmain.cpp
diffstat 22 files changed, 203 insertions(+), 482 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Jan 26 17:32:02 2015 +0000
+++ b/.hgignore	Mon Mar 23 15:58:40 2015 +0000
@@ -1,3 +1,6 @@
 syntax: glob
 *.o
 *.so
+*~
+*.dll
+
--- a/Makefile.inc	Mon Jan 26 17:32:02 2015 +0000
+++ b/Makefile.inc	Mon Mar 23 15:58:40 2015 +0000
@@ -12,7 +12,6 @@
 SOURCES := PYinVamp.cpp \
            YinVamp.cpp \
            LocalCandidatePYIN.cpp \
-           YinVampFreqConstrained.cpp \
            Yin.cpp \
            YinUtil.cpp \
            MonoNote.cpp \
@@ -65,18 +64,37 @@
 
 # DO NOT DELETE
 
-PYinVamp.o: PYinVamp.h
-YinVamp.o: YinVamp.h
-YinVampFreqConstrained.o: YinVampFreqConstrained.h
-LocalCandidatePYIN.o: LocalCandidatePYIN.h
-Yin.o: Yin.h
+libmain.o: PYinVamp.h Yin.h MeanFilter.h YinVamp.h LocalCandidatePYIN.h
+libmain.o: YinVampFreqConstrained.h
+LocalCandidatePYIN.o: LocalCandidatePYIN.h Yin.h MeanFilter.h MonoPitch.h
+LocalCandidatePYIN.o: MonoPitchHMM.h SparseHMM.h YinUtil.h
+MonoNote.o: MonoNote.h MonoNoteHMM.h MonoNoteParameters.h SparseHMM.h
+MonoNoteHMM.o: MonoNoteHMM.h MonoNoteParameters.h SparseHMM.h
 MonoNoteParameters.o: MonoNoteParameters.h
-MonoNote.o: MonoNote.h
-MonoPitch.o: MonoPitch.h
-MonoPitchHMM.o: MonoPitchHMM.h
+MonoPitch.o: MonoPitch.h MonoPitchHMM.h SparseHMM.h
+MonoPitchHMM.o: MonoPitchHMM.h SparseHMM.h
+PYinVamp.o: PYinVamp.h Yin.h MeanFilter.h MonoNote.h MonoNoteHMM.h
+PYinVamp.o: MonoNoteParameters.h SparseHMM.h MonoPitch.h MonoPitchHMM.h
 SparseHMM.o: SparseHMM.h
-MonoNoteHMM.o: MonoNoteHMM.h
-libmain.o: PYinVamp.h YinVamp.h LocalCandidatePYIN.h
+Yin.o: Yin.h MeanFilter.h YinUtil.h
+YinUtil.o: YinUtil.h MeanFilter.h
+YinVamp.o: YinVamp.h Yin.h MeanFilter.h MonoNote.h MonoNoteHMM.h
+YinVamp.o: MonoNoteParameters.h SparseHMM.h
+YinVampFreqConstrained.o: YinVampFreqConstrained.h Yin.h MeanFilter.h
+YinVampFreqConstrained.o: MonoNote.h MonoNoteHMM.h MonoNoteParameters.h
+YinVampFreqConstrained.o: SparseHMM.h
 test/TestMeanFilter.o: MeanFilter.h
-test/TestYin.o: Yin.h
-
+test/TestMonoNote.o: MonoNote.h MonoNoteHMM.h MonoNoteParameters.h
+test/TestMonoNote.o: SparseHMM.h
+test/TestYin.o: Yin.h MeanFilter.h
+test/TestYinUtil.o: YinUtil.h MeanFilter.h
+LocalCandidatePYIN.o: Yin.h MeanFilter.h
+MonoNote.o: MonoNoteHMM.h MonoNoteParameters.h SparseHMM.h
+MonoNoteHMM.o: MonoNoteParameters.h SparseHMM.h
+MonoPitch.o: MonoPitchHMM.h SparseHMM.h
+MonoPitchHMM.o: SparseHMM.h
+PYinVamp.o: Yin.h MeanFilter.h
+Yin.o: MeanFilter.h
+YinUtil.o: MeanFilter.h
+YinVampFreqConstrained.o: Yin.h MeanFilter.h
+YinVamp.o: Yin.h MeanFilter.h
--- a/Makefile.linux64	Mon Jan 26 17:32:02 2015 +0000
+++ b/Makefile.linux64	Mon Mar 23 15:58:40 2015 +0000
@@ -1,10 +1,9 @@
 
-CFLAGS := -Wall -O3 -fPIC -I../vamp-plugin-sdk/ -I../../vamp-plugin-sdk/
-#CFLAGS := -g -Wall -fPIC -I../vamp-plugin-sdk
+CFLAGS := $(CFLAGS) -Wall -O3 -fPIC -I../vamp-plugin-sdk/ -I../../vamp-plugin-sdk/
 
-CXXFLAGS := $(CFLAGS)
+CXXFLAGS := $(CXXFLAGS) $(CFLAGS)
 
-PLUGIN_LDFLAGS := -shared -Wl,-Bstatic -L../vamp-plugin-sdk -L../../vamp-plugin-sdk -lvamp-sdk -Wl,-Bdynamic -Wl,--version-script=vamp-plugin.map
+PLUGIN_LDFLAGS := $(LDFLAGS) -shared -Wl,-Bstatic -L../vamp-plugin-sdk -L../../vamp-plugin-sdk -lvamp-sdk -Wl,-Bdynamic -Wl,--version-script=vamp-plugin.map
 TEST_LDFLAGS := -Wl,-Bstatic -L../vamp-plugin-sdk -L../../vamp-plugin-sdk -lvamp-sdk -Wl,-Bdynamic -lboost_unit_test_framework
 
 PLUGIN_EXT := .so
--- a/Makefile.mingw32	Mon Jan 26 17:32:02 2015 +0000
+++ b/Makefile.mingw32	Mon Mar 23 15:58:40 2015 +0000
@@ -1,10 +1,15 @@
 
-CXX	:= i486-mingw32-g++
-CC	:= i486-mingw32-gcc
+TOOLPREFIX     ?= i586-mingw32msvc-
+CXX		= $(TOOLPREFIX)g++
+CC		= $(TOOLPREFIX)gcc
+LD		= $(TOOLPREFIX)g++
+AR		= $(TOOLPREFIX)ar
+RANLIB		= $(TOOLPREFIX)ranlib
 
-CFLAGS    := -Wall -O2
-CXXFLAGS  := $(CFLAGS) -I../include -I../boost_1_53_0
-PLUGIN_LDFLAGS	  := -shared -L../lib -lvamp-sdk -Wl,-Bsymbolic -static-libgcc -Wl,--version-script=vamp-plugin.map -fno-exceptions $(shell $(CXX) -print-file-name=libstdc++.a)
+CFLAGS    += -Wall -O2
+CXXFLAGS  += $(CFLAGS) -I../include -I../boost_1_53_0
+
+PLUGIN_LDFLAGS	  := $(LDFLAGS) -static -shared -L../lib -lvamp-sdk -Wl,-Bsymbolic -static-libgcc -Wl,--retain-symbols-file=vamp-plugin.list -fno-exceptions $(shell $(CXX) -print-file-name=libstdc++.a)
 
 PLUGIN_EXT   := .dll
 
--- a/MonoNoteHMM.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ b/MonoNoteHMM.cpp	Mon Mar 23 15:58:40 2015 +0000
@@ -49,7 +49,7 @@
     double tempProbSum = 0;
     for (size_t i = 0; i < par.n; ++i)
     {
-        if (i % 4 != 2)
+        if (i % par.nSPP != 2)
         {
             // std::cerr << getMidiPitch(i) << std::endl;
             double tempProb = 0;
@@ -68,7 +68,9 @@
                         minDistCandidate = iCandidate;
                     }
                 }
-                tempProb = std::pow(minDistProb, par.yinTrust) * boost::math::pdf(pitchDistr[i], pitchProb[minDistCandidate].first);
+                tempProb = std::pow(minDistProb, par.yinTrust) * 
+                           boost::math::pdf(pitchDistr[i], 
+                                            pitchProb[minDistCandidate].first);
             } else {
                 tempProb = 1;
             }
@@ -79,7 +81,7 @@
     
     for (size_t i = 0; i < par.n; ++i)
     {
-        if (i % 4 != 2)
+        if (i % par.nSPP != 2)
         {
             if (tempProbSum > 0) 
             {
@@ -101,16 +103,15 @@
     //    0. attack state
     //    1. stable state
     //    2. silent state
-    //    3. inter state
-    // 4-6. second-lowest pitch
-    //    4. attack state
+    // 3-5. second-lowest pitch
+    //    3. attack state
     //    ...
     
     // observation distributions
     for (size_t iState = 0; iState < par.n; ++iState)
     {
         pitchDistr.push_back(boost::math::normal(0,1));
-        if (iState % 4 == 2)
+        if (iState % par.nSPP == 2)
         {
             // silent state starts tracking
             init.push_back(1.0/(par.nS * par.nPPS));
@@ -126,7 +127,6 @@
         pitchDistr[index] = boost::math::normal(mu, par.sigmaYinPitchAttack);
         pitchDistr[index+1] = boost::math::normal(mu, par.sigmaYinPitchStable);
         pitchDistr[index+2] = boost::math::normal(mu, 1.0); // dummy
-        pitchDistr[index+3] = boost::math::normal(mu, par.sigmaYinPitchInter);
     }
     
     boost::math::normal noteDistanceDistr(0, par.sigma2Note);
@@ -154,54 +154,43 @@
         to.push_back(index+2); // to silent
         transProb.push_back(par.pStable2Silent);
 
-        from.push_back(index+1);
-        to.push_back(index+3); // to inter-note
-        transProb.push_back(1-par.pStableSelftrans-par.pStable2Silent);
-
         // the "easy" transitions from silent state
         from.push_back(index+2);
         to.push_back(index+2);
         transProb.push_back(par.pSilentSelftrans);
         
-        // the "easy" inter state transition
-        from.push_back(index+3);
-        to.push_back(index+3);
-        transProb.push_back(par.pInterSelftrans);
         
-        // the more complicated transitions from the silent and inter state
+        // the more complicated transitions from the silent
         double probSumSilent = 0;
-        double probSumInter = 0;
-        vector<double> tempTransProbInter;
+
         vector<double> tempTransProbSilent;
         for (size_t jPitch = 0; jPitch < (par.nS * par.nPPS); ++jPitch)
         {
             int fromPitch = iPitch;
             int toPitch = jPitch;
-            double semitoneDistance = std::abs(fromPitch - toPitch) * 1.0 / par.nPPS;
+            double semitoneDistance = 
+                std::abs(fromPitch - toPitch) * 1.0 / par.nPPS;
             
             // if (std::fmod(semitoneDistance, 1) == 0 && semitoneDistance > par.minSemitoneDistance)
-            if (semitoneDistance == 0 || (semitoneDistance > par.minSemitoneDistance && semitoneDistance < par.maxJump))
+            if (semitoneDistance == 0 || 
+                (semitoneDistance > par.minSemitoneDistance 
+                 && semitoneDistance < par.maxJump))
             {
                 size_t toIndex = jPitch * par.nSPP; // note attack index
 
-                double tempWeightSilent = boost::math::pdf(noteDistanceDistr, semitoneDistance);
-                double tempWeightInter = semitoneDistance == 0 ? 0 : tempWeightSilent;
+                double tempWeightSilent = boost::math::pdf(noteDistanceDistr, 
+                                                           semitoneDistance);
                 probSumSilent += tempWeightSilent;
-                probSumInter += tempWeightInter;
 
                 tempTransProbSilent.push_back(tempWeightSilent);
-                tempTransProbInter.push_back(tempWeightInter);
 
                 from.push_back(index+2);
                 to.push_back(toIndex);
-                from.push_back(index+3);
-                to.push_back(toIndex);                
             }
         }
         for (size_t i = 0; i < tempTransProbSilent.size(); ++i)
         {
             transProb.push_back((1-par.pSilentSelftrans) * tempTransProbSilent[i]/probSumSilent);
-            transProb.push_back((1-par.pInterSelftrans) * tempTransProbInter[i]/probSumInter);
         }
     }
 }
--- a/MonoNoteParameters.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ b/MonoNoteParameters.cpp	Mon Mar 23 15:58:40 2015 +0000
@@ -16,17 +16,17 @@
 MonoNoteParameters::MonoNoteParameters() :
     minPitch(35), 
     nPPS(3), 
-    nS(68), 
-    nSPP(4), // states per pitch
+    nS(69), 
+    nSPP(3), // states per pitch
     n(0),
     initPi(0), 
-    pAttackSelftrans(0.99),
-    pStableSelftrans(0.999),
-    pStable2Silent(0.005),
+    pAttackSelftrans(0.9),
+    pStableSelftrans(0.99),
+    pStable2Silent(0.01),
     pSilentSelftrans(0.9999), 
     sigma2Note(0.7),
     maxJump(13),
-    pInterSelftrans(0.99),
+    pInterSelftrans(0.0),
     priorPitchedProb(.7),
     priorWeight(0.5),
     minSemitoneDistance(.5),
--- a/MonoPitchHMM.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ b/MonoPitchHMM.cpp	Mon Mar 23 15:58:40 2015 +0000
@@ -22,8 +22,7 @@
 using std::pair;
 
 MonoPitchHMM::MonoPitchHMM() :
-m_minFreq(61.735), // b 1
-// m_minFreq(110),
+m_minFreq(61.735),
 m_nBPS(5),
 m_nPitch(0),
 m_transitionWidth(0),
@@ -31,7 +30,7 @@
 m_yinTrust(.5),
 m_freqs(0)
 {
-    m_transitionWidth = 9*(m_nBPS/2) + 1;
+    m_transitionWidth = 5*(m_nBPS/2) + 1;
     m_nPitch = 69 * m_nBPS;
     m_freqs = vector<double>(2*m_nPitch);
     for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch)
--- a/PYinVamp.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ b/PYinVamp.cpp	Mon Mar 23 15:58:40 2015 +0000
@@ -47,8 +47,11 @@
     m_outputUnvoiced(0.0f),
     m_preciseTime(0.0f),
     m_lowAmp(0.1),
+    m_onsetSensitivity(0.6f),
+    m_pruneThresh(0.07f),
     m_pitchProb(0),
-    m_timestamp(0)
+    m_timestamp(0),
+    m_level(0)
 {
 }
 
@@ -188,6 +191,28 @@
     d.isQuantized = false;
     list.push_back(d);
 
+    d.identifier = "onsetsensitivity";
+    d.valueNames.clear();
+    d.name = "Onset sensitivity";
+    d.description = "Adds additional note onsets when RMS increases.";
+    d.unit = "";
+    d.minValue = 0.0f;
+    d.maxValue = 1.0f;
+    d.defaultValue = 0.5f;
+    d.isQuantized = false;
+    list.push_back(d);
+
+    d.identifier = "prunethresh";
+    d.valueNames.clear();
+    d.name = "Duration pruning threshold.";
+    d.description = "Prune notes that are shorter than this value.";
+    d.unit = "";
+    d.minValue = 0.0f;
+    d.maxValue = 0.2f;
+    d.defaultValue = 0.05f;
+    d.isQuantized = false;
+    list.push_back(d);
+
     return list;
 }
 
@@ -206,6 +231,12 @@
     if (identifier == "lowampsuppression") {
             return m_lowAmp;
     }
+    if (identifier == "onsetsensitivity") {
+            return m_onsetSensitivity;
+    }
+    if (identifier == "prunethresh") {
+            return m_pruneThresh;
+    }
     return 0.f;
 }
 
@@ -228,6 +259,14 @@
     {
         m_lowAmp = value;
     }
+    if (identifier == "onsetsensitivity")
+    {
+        m_onsetSensitivity = value;
+    }
+    if (identifier == "prunethresh")
+    {
+        m_pruneThresh = value;
+    }
 }
 
 PYinVamp::ProgramList
@@ -379,10 +418,13 @@
 {    
     m_yin.setThresholdDistr(m_threshDistr);
     m_yin.setFrameSize(m_blockSize);
-    m_yin.setFast(!m_preciseTime);
+
+    //TODO: Restore this! (MM)
+    //!!! m_yin.setFast(!m_preciseTime);
     
     m_pitchProb.clear();
     m_timestamp.clear();
+    m_level.clear();
 /*    
     std::cerr << "PYinVamp::reset"
           << ", blockSize = " << m_blockSize
@@ -415,6 +457,8 @@
     Yin::YinOutput yo = m_yin.processProbabilisticYin(dInputBuffers);
     delete [] dInputBuffers;
 
+    m_level.push_back(yo.rms);
+
     // First, get the things out of the way that we don't want to output 
     // immediately, but instead save for later.
     vector<pair<double, double> > tempPitchProb;
@@ -523,31 +567,41 @@
     bool isVoiced = 0;
     bool oldIsVoiced = 0;
     size_t nFrame = m_pitchProb.size();
+
+    float minNoteFrames = (m_inputSampleRate*m_pruneThresh) / m_stepSize;
     
     std::vector<float> notePitchTrack; // collects pitches for one note at a time
     for (size_t iFrame = 0; iFrame < nFrame; ++iFrame)
     {
-        isVoiced = mnOut[iFrame].noteState < 3 && smoothedPitch[iFrame].size() > 0;
+        isVoiced = mnOut[iFrame].noteState < 3
+                   && smoothedPitch[iFrame].size() > 0
+                   && (iFrame >= nFrame-2
+                       || ((m_level[iFrame]/m_level[iFrame+2]) > m_onsetSensitivity));
+        // std::cerr << m_level[iFrame]/m_level[iFrame-1] << " " << isVoiced << std::endl;
         if (isVoiced && iFrame != nFrame-1)
         {
             if (oldIsVoiced == 0) // beginning of a note
             {
                 onsetFrame = iFrame;
-                notePitchTrack.clear();
             }
             float pitch = smoothedPitch[iFrame][0].first;
             notePitchTrack.push_back(pitch); // add to the note's pitch track
         } else { // not currently voiced
-            if (oldIsVoiced == 1 && notePitchTrack.size() > 4) // end of the note
+            if (oldIsVoiced == 1) // end of note
             {
-                std::sort(notePitchTrack.begin(), notePitchTrack.end());
-                float medianPitch = notePitchTrack[notePitchTrack.size()/2];
-                float medianFreq = std::pow(2,(medianPitch - 69) / 12) * 440;
-                f.values.clear();
-                f.values.push_back(medianFreq);
-                f.timestamp = m_timestamp[onsetFrame];
-                f.duration = m_timestamp[iFrame] - m_timestamp[onsetFrame];
-                fs[m_oNotes].push_back(f);
+                // std::cerr << notePitchTrack.size() << " " << minNoteFrames << std::endl;
+                if (notePitchTrack.size() >= minNoteFrames)
+                {
+                    std::sort(notePitchTrack.begin(), notePitchTrack.end());
+                    float medianPitch = notePitchTrack[notePitchTrack.size()/2];
+                    float medianFreq = std::pow(2,(medianPitch - 69) / 12) * 440;
+                    f.values.clear();
+                    f.values.push_back(medianFreq);
+                    f.timestamp = m_timestamp[onsetFrame];
+                    f.duration = m_timestamp[iFrame] - m_timestamp[onsetFrame];
+                    fs[m_oNotes].push_back(f);
+                }
+                notePitchTrack.clear();
             }
         }
         oldIsVoiced = isVoiced;
--- a/PYinVamp.h	Mon Jan 26 17:32:02 2015 +0000
+++ b/PYinVamp.h	Mon Mar 23 15:58:40 2015 +0000
@@ -74,8 +74,11 @@
     float m_outputUnvoiced;
     float m_preciseTime;
     float m_lowAmp;
+    float m_onsetSensitivity;
+    float m_pruneThresh;
     vector<vector<pair<double, double> > > m_pitchProb;
     vector<Vamp::RealTime> m_timestamp;
+    vector<float> m_level;
 };
 
 #endif
--- a/Yin.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ b/Yin.cpp	Mon Mar 23 15:58:40 2015 +0000
@@ -25,13 +25,12 @@
 
 using std::vector;
 
-Yin::Yin(size_t frameSize, size_t inputSampleRate, double thresh, bool fast) : 
+Yin::Yin(size_t frameSize, size_t inputSampleRate, double thresh) : 
     m_frameSize(frameSize),
     m_inputSampleRate(inputSampleRate),
     m_thresh(thresh),
     m_threshDistr(2),
-    m_yinBufferSize(frameSize/2),
-    m_fast(fast)
+    m_yinBufferSize(frameSize/2)
 {
     if (frameSize & (frameSize-1)) {
       //  throw "N must be a power of two";
@@ -46,9 +45,9 @@
 Yin::process(const double *in) const {
     
     double* yinBuffer = new double[m_yinBufferSize];
+
     // calculate aperiodicity function for all periods
-    if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
-    else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);    
+    YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);    
     YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
 
     int tau = 0;
@@ -58,7 +57,7 @@
     double aperiodicity;
     double f0;
     
-    if (tau!=0 && tau!=int(m_yinBufferSize)-1)
+    if (tau!=0)
     {
         interpolatedTau = YinUtil::parabolicInterpolation(yinBuffer, abs(tau), m_yinBufferSize);
         f0 = m_inputSampleRate * (1.0 / interpolatedTau);
@@ -83,21 +82,26 @@
 
 Yin::YinOutput
 Yin::processProbabilisticYin(const double *in) const {
-
+    
     double* yinBuffer = new double[m_yinBufferSize];
 
     // calculate aperiodicity function for all periods
-    if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
-    else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);    
-
+    YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);    
     YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
 
     vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
-        
-    // basic yin output
-    Yin::YinOutput yo(0,0,0);
-    for (int iBuf = 1; iBuf < int(m_yinBufferSize)-1; ++iBuf)
+    
+    // calculate overall "probability" from peak probability
+    double probSum = 0;
+    for (size_t iBin = 0; iBin < m_yinBufferSize; ++iBin)
     {
+        probSum += peakProbability[iBin];
+    }
+    double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
+    Yin::YinOutput yo(0,0,rms);
+    for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
+    {
+        yo.salience.push_back(peakProbability[iBuf]);
         if (peakProbability[iBuf] > 0)
         {
             double currentF0 = 
@@ -107,11 +111,6 @@
         }
     }
     
-    // add salience
-    for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf) {
-        yo.salience.push_back(peakProbability[iBuf]);
-    }
-
     // std::cerr << yo.freqProb.size() << std::endl;
     
     delete [] yinBuffer;
@@ -141,51 +140,9 @@
     return 0;
 }
 
-int
-Yin::setFast(bool fast)
-{
-    m_fast = fast;
-    return 0;
-}
-
 // int
 // Yin::setRemoveUnvoiced(bool parameter)
 // {
 //     m_removeUnvoiced = parameter;
 //     return 0;
 // }
-
-float
-Yin::constrainedMinPick(const double *in, const float minFreq, const int maxFreq) const {
-    
-    double* yinBuffer = new double[m_yinBufferSize];
-
-    // calculate aperiodicity function for all periods
-    YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);    
-    YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
-    
-    int minPeriod = m_inputSampleRate / maxFreq;
-    int maxPeriod = m_inputSampleRate / minFreq;
-    
-    if (minPeriod < 0 || maxPeriod > int(m_yinBufferSize) || minPeriod > maxPeriod) {
-        delete [] yinBuffer;
-        return 0.f;
-    }
-    
-    float bestVal = 1000;
-    int   bestTau = 0;
-    for (int tau = minPeriod; tau <= maxPeriod; ++tau)
-    {
-        if (yinBuffer[tau] < bestVal) 
-        {
-            bestVal = yinBuffer[tau];
-            bestTau = tau;
-        }
-    }
-    
-    float interpolatedTau =
-        YinUtil::parabolicInterpolation(yinBuffer, bestTau, m_yinBufferSize);
-    
-    delete [] yinBuffer;
-    return m_inputSampleRate * (1.0 / interpolatedTau);
-}
--- a/Yin.h	Mon Jan 26 17:32:02 2015 +0000
+++ b/Yin.h	Mon Mar 23 15:58:40 2015 +0000
@@ -31,7 +31,7 @@
 class Yin
 {
 public:
-    Yin(size_t frameSize, size_t inputSampleRate, double thresh = 0.2, bool fast = true);
+    Yin(size_t frameSize, size_t inputSampleRate, double thresh = 0.2);
     virtual ~Yin();
 
     struct YinOutput {
@@ -53,11 +53,9 @@
     int setThreshold(double parameter);
     int setThresholdDistr(float parameter);
     int setFrameSize(size_t frameSize);
-    int setFast(bool fast);
     // int setRemoveUnvoiced(bool frameSize);
     YinOutput process(const double *in) const;
     YinOutput processProbabilisticYin(const double *in) const;
-    float constrainedMinPick(const double *in, const float minFreq, const int maxFreq) const;
 
 private:
     mutable size_t m_frameSize;
@@ -65,7 +63,6 @@
     mutable double m_thresh;
     mutable size_t m_threshDistr;
     mutable size_t m_yinBufferSize;
-    mutable bool   m_fast;
     // mutable bool m_removeUnvoiced;
 };
 
--- a/YinVampFreqConstrained.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,269 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    pYIN - A fundamental frequency estimator for monophonic audio
-    Centre for Digital Music, Queen Mary, University of London.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "YinVampFreqConstrained.h"
-#include "MonoNote.h"
-
-#include "vamp-sdk/FFT.h"
-
-#include <vector>
-#include <algorithm>
-
-#include <cstdio>
-#include <cmath>
-#include <complex>
-
-using std::string;
-using std::vector;
-using Vamp::RealTime;
-
-
-YinVampFreqConstrained::YinVampFreqConstrained(float inputSampleRate) :
-    Plugin(inputSampleRate),
-    m_channels(0),
-    m_stepSize(256),
-    m_blockSize(2048),
-    m_fmin(40),
-    m_fmax(1000),
-    m_yin(2048, inputSampleRate, 0.0),
-    m_yinFmin(100.f),
-    m_yinFmax(400.f)
-{
-}
-
-YinVampFreqConstrained::~YinVampFreqConstrained()
-{
-}
-
-string
-YinVampFreqConstrained::getIdentifier() const
-{
-    return "yinfc";
-}
-
-string
-YinVampFreqConstrained::getName() const
-{
-    return "Frequency-constrained Yin";
-}
-
-string
-YinVampFreqConstrained::getDescription() const
-{
-    return "A vamp implementation of the Yin algorithm for monophonic frequency estimation with frequency constraints.";
-}
-
-string
-YinVampFreqConstrained::getMaker() const
-{
-    return "Matthias Mauch";
-}
-
-int
-YinVampFreqConstrained::getPluginVersion() const
-{
-    // Increment this each time you release a version that behaves
-    // differently from the previous one
-    return 1;
-}
-
-string
-YinVampFreqConstrained::getCopyright() const
-{
-    return "GPL";
-}
-
-YinVampFreqConstrained::InputDomain
-YinVampFreqConstrained::getInputDomain() const
-{
-    return TimeDomain;
-}
-
-size_t
-YinVampFreqConstrained::getPreferredBlockSize() const
-{
-    return 2048;
-}
-
-size_t 
-YinVampFreqConstrained::getPreferredStepSize() const
-{
-    return 256;
-}
-
-size_t
-YinVampFreqConstrained::getMinChannelCount() const
-{
-    return 1;
-}
-
-size_t
-YinVampFreqConstrained::getMaxChannelCount() const
-{
-    return 1;
-}
-
-YinVampFreqConstrained::ParameterList
-YinVampFreqConstrained::getParameterDescriptors() const
-{
-    ParameterList list;
-    
-    ParameterDescriptor d;
-
-    d.identifier = "minfreq";
-    d.name = "Minimum frequency";
-    d.description = "Minimum frequency used when searching for difference function minimum.";
-    d.unit = "Hz";
-    d.minValue = 40.f;
-    d.maxValue = 1000.0f;
-    d.defaultValue = 100.f;
-    d.isQuantized = false;
-    d.valueNames.clear();
-    list.push_back(d);
-    
-    d.identifier = "maxfreq";
-    d.name = "Maximum frequency";
-    d.description = "Maximum frequency used when searching for difference function minimum.";
-    d.unit = "Hz";
-    d.minValue = 40.f;
-    d.maxValue = 1000.0f;
-    d.defaultValue = 400.f;
-    d.isQuantized = false;
-    d.valueNames.clear();
-    list.push_back(d);
-    
-    return list;
-}
-
-float
-YinVampFreqConstrained::getParameter(string identifier) const
-{
-    if (identifier == "minfreq") {
-        return m_yinFmin;
-    }
-    if (identifier == "maxfreq") {
-        return m_yinFmax;
-    }
-    return 0.f;
-}
-
-void
-YinVampFreqConstrained::setParameter(string identifier, float value) 
-{
-    if (identifier == "minfreq")
-    {
-        m_yinFmin = value;
-    }
-    if (identifier == "maxfreq")
-    {
-        m_yinFmax = value;
-    }
-}
-
-YinVampFreqConstrained::ProgramList
-YinVampFreqConstrained::getPrograms() const
-{
-    ProgramList list;
-    return list;
-}
-
-string
-YinVampFreqConstrained::getCurrentProgram() const
-{
-    return ""; // no programs
-}
-
-void
-YinVampFreqConstrained::selectProgram(string name)
-{
-}
-
-YinVampFreqConstrained::OutputList
-YinVampFreqConstrained::getOutputDescriptors() const
-{
-    OutputList outputs;
-
-    OutputDescriptor d;
-    
-    int outputNumber = 0;
-
-    d.identifier = "f0";
-    d.name = "Estimated f0";
-    d.description = "Estimated fundamental frequency";
-    d.unit = "Hz";
-    d.hasFixedBinCount = true;
-    d.binCount = 1;
-    d.hasKnownExtents = true;
-    d.minValue = m_fmin;
-    d.maxValue = 500;
-    d.isQuantized = false;
-    d.sampleType = OutputDescriptor::FixedSampleRate;
-    d.sampleRate = (m_inputSampleRate / m_stepSize);
-    d.hasDuration = false;
-    outputs.push_back(d);
-
-    return outputs;
-}
-
-bool
-YinVampFreqConstrained::initialise(size_t channels, size_t stepSize, size_t blockSize)
-{
-    if (channels < getMinChannelCount() ||
-	channels > getMaxChannelCount()) return false;
-
-/*
-    std::cerr << "YinVampFreqConstrained::initialise: channels = " << channels
-          << ", stepSize = " << stepSize << ", blockSize = " << blockSize
-          << std::endl;
-*/
-    m_channels = channels;
-    m_stepSize = stepSize;
-    m_blockSize = blockSize;
-    
-    reset();
-
-    return true;
-}
-
-void
-YinVampFreqConstrained::reset()
-{    
-    m_yin.setFrameSize(m_blockSize);
-}
-
-YinVampFreqConstrained::FeatureSet
-YinVampFreqConstrained::process(const float *const *inputBuffers, RealTime timestamp)
-{
-    timestamp = timestamp + Vamp::RealTime::frame2RealTime(m_blockSize/2, lrintf(m_inputSampleRate));
-    FeatureSet fs;
-    
-    double *dInputBuffers = new double[m_blockSize];
-    for (size_t i = 0; i < m_blockSize; ++i) dInputBuffers[i] = inputBuffers[0][i];
-    
-    // std::cerr << "f0 in YinVampFreqConstrained: " << yo.f0 << std::endl;
-    Feature f;
-    f.hasTimestamp = true;
-    f.timestamp = timestamp;
-    f.values.push_back(m_yin.constrainedMinPick(dInputBuffers, m_yinFmin, m_yinFmax));
-    fs[0].push_back(f);
-    
-    delete [] dInputBuffers;
-    return fs;
-}
-
-YinVampFreqConstrained::FeatureSet
-YinVampFreqConstrained::getRemainingFeatures()
-{
-    FeatureSet fs;
-    return fs;
-}
--- a/YinVampFreqConstrained.h	Mon Jan 26 17:32:02 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    pYIN - A fundamental frequency estimator for monophonic audio
-    Centre for Digital Music, Queen Mary, University of London.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _YINVAMPFREQCONSTRAINED_H_
-#define _YINVAMPFREQCONSTRAINED_H_
-
-#include <vamp-sdk/Plugin.h>
-
-#include "Yin.h"
-
-class YinVampFreqConstrained : public Vamp::Plugin
-{
-public:
-    YinVampFreqConstrained(float inputSampleRate);
-    virtual ~YinVampFreqConstrained();
-
-    std::string getIdentifier() const;
-    std::string getName() const;
-    std::string getDescription() const;
-    std::string getMaker() const;
-    int getPluginVersion() const;
-    std::string getCopyright() const;
-
-    InputDomain getInputDomain() const;
-    size_t getPreferredBlockSize() const;
-    size_t getPreferredStepSize() const;
-    size_t getMinChannelCount() const;
-    size_t getMaxChannelCount() const;
-
-    ParameterList getParameterDescriptors() const;
-    float getParameter(std::string identifier) const;
-    void setParameter(std::string identifier, float value);
-
-    ProgramList getPrograms() const;
-    std::string getCurrentProgram() const;
-    void selectProgram(std::string name);
-
-    OutputList getOutputDescriptors() const;
-
-    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
-    void reset();
-
-    FeatureSet process(const float *const *inputBuffers,
-                       Vamp::RealTime timestamp);
-
-    FeatureSet getRemainingFeatures();
-
-protected:
-    size_t m_channels;
-    size_t m_stepSize;
-    size_t m_blockSize;
-    float m_fmin;
-    float m_fmax;
-    Yin m_yin;
-
-    float m_yinFmin;
-    float m_yinFmax;
-};
-
-#endif
Binary file evaluation/evalResults.mat has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/evaluation/notecsv2molina.awk	Mon Mar 23 15:58:40 2015 +0000
@@ -0,0 +1,1 @@
+BEGIN {FS=","}; {if ($2 > 0.09) {$2=$1+$2; $3 = 69+(log($3/440)/log(2)*12); print $1,$2, $3;}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/evaluation/notecsv2molina.sh	Mon Mar 23 15:58:40 2015 +0000
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+input_csv=$1
+
+if [ $# != 2 ]; then
+  minimum_duration=0
+else
+  minimum_duration=$2
+fi
+
+awk -v md="$minimum_duration" 'BEGIN {FS=","}; {if ($2 >= md) {$2=$1+$2; $3 = 69+(log($3/440)/log(2)*12); print $1,$2,$3;}}' < $input_csv
+
--- a/libmain.cpp	Mon Jan 26 17:32:02 2015 +0000
+++ b/libmain.cpp	Mon Mar 23 15:58:40 2015 +0000
@@ -17,12 +17,10 @@
 #include "PYinVamp.h"
 #include "YinVamp.h"
 #include "LocalCandidatePYIN.h"
-#include "YinVampFreqConstrained.h"
 
 static Vamp::PluginAdapter<PYinVamp> pyinvampPluginAdapter;
 static Vamp::PluginAdapter<YinVamp> yinvampPluginAdapter;
 static Vamp::PluginAdapter<LocalCandidatePYIN> localCandidatePYINPluginAdapter;
-static Vamp::PluginAdapter<YinVampFreqConstrained> yinVampFreqConstrainedPluginAdapter;
 
 const VampPluginDescriptor *
 vampGetPluginDescriptor(unsigned int version, unsigned int index)
@@ -33,7 +31,6 @@
     case  0: return pyinvampPluginAdapter.getDescriptor();
     case  1: return yinvampPluginAdapter.getDescriptor();
     case  2: return localCandidatePYINPluginAdapter.getDescriptor();
-    case  3: return yinVampFreqConstrainedPluginAdapter.getDescriptor();
     default: return 0;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/pitchgenerator.m	Mon Mar 23 15:58:40 2015 +0000
@@ -0,0 +1,17 @@
+f = 50:800;
+fs = 44100;
+t = (0:(2*fs))/fs;
+nFreq = length(f);
+
+for iFreq = 1:nFreq
+    f(iFreq)
+    x = zeros(size(t));
+    for iAdd = 1:100
+        x = x + cos(2*pi*f(iFreq)*t*iAdd)*0.6^(iAdd-1);
+        if f(iFreq)*iAdd > fs/2
+            break
+        end
+    end
+    x = x / max(abs(x));
+    wavwrite(x, fs, sprintf('/Users/matthiasm/data/pyin/simplewavs/%iHz.wav', f(iFreq)));
+end
\ No newline at end of file
--- a/pyin.n3	Mon Jan 26 17:32:02 2015 +0000
+++ b/pyin.n3	Mon Mar 23 15:58:40 2015 +0000
@@ -6,6 +6,7 @@
 @prefix dc:       <http://purl.org/dc/elements/1.1/> .
 @prefix af:       <http://purl.org/ontology/af/> .
 @prefix foaf:     <http://xmlns.com/foaf/0.1/> .
+@prefix doap: 	  <http://usefulinc.com/ns/doap#> .
 @prefix cc:       <http://web.resource.org/cc/> .
 @prefix :         <#> .
 
@@ -13,18 +14,26 @@
     foaf:maker          <http://www.vamp-plugins.org/doap.rdf#template-generator> ;
     foaf:primaryTopic   <http://vamp-plugins.org/rdf/plugins/pyin> .
 
-:pyin a  vamp:PluginLibrary ;
+:maker
+    foaf:name "Matthias Mauch" ;
+    foaf:logo <http://vamp-plugins.org/rdf/plugins/makers/qm.png> ;
+    foaf:page <http://c4dm.eecs.qmul.ac.uk/> .
+
+plugbase:library a  vamp:PluginLibrary ;
     vamp:identifier "pyin"  ; 
+    dc:title "pYIN" ;
+    dc:description "pYIN is a modification of the well-loved YIN algorithm for fundamental frequency (F0) estimation in monophonic audio." ;
     vamp:available_plugin plugbase:pyin ; 
     vamp:available_plugin plugbase:yin ; 
     foaf:page <http://code.soundsoftware.ac.uk/projects/pyin> ;
+    foaf:maker :maker ;
     .
 
 plugbase:pyin a   vamp:Plugin ;
     dc:title              "pYin" ;
     vamp:name             "pYin" ;
     dc:description        """Monophonic pitch and note tracking based on a probabilistic Yin extension.""" ;
-    foaf:maker            [ foaf:name "Matthias Mauch" ] ; # FIXME could give plugin author's URI here
+    foaf:maker            :maker ;
     dc:rights             """GPL""" ;
 #   cc:license            <Place plugin license URI here and uncomment> ; 
     vamp:identifier       "pyin" ;
@@ -150,7 +159,7 @@
     dc:title              "Yin" ;
     vamp:name             "Yin" ;
     dc:description        """A vamp implementation of the Yin algorithm for monophonic frequency estimation.""" ;
-    foaf:maker            [ foaf:name "Matthias Mauch" ] ; # FIXME could give plugin author's URI here
+    foaf:maker            :maker ;
     dc:rights             """GPL""" ;
 #   cc:license            <Place plugin license URI here and uncomment> ; 
     vamp:identifier       "yin" ;
Binary file testdata/DontTellMeExcerpt.wav has changed
Binary file testdata/bob_02.wav has changed
Binary file testdata/sine_a_440.ogg has changed