changeset 21:70dd2b4e776b interactive

in a hacky way, very basic constraining of frequencies for a certain time period seems to work now
author matthiasm
date Fri, 17 Jan 2014 12:09:28 +0000
parents 1625cc4f4221
children 12cab92b7c26
files Makefile.osx PYIN.cpp PYIN.h Yin.cpp Yin.h YinUtil.cpp YinUtil.h
diffstat 7 files changed, 163 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.osx	Fri Dec 06 16:19:26 2013 +0000
+++ b/Makefile.osx	Fri Jan 17 12:09:28 2014 +0000
@@ -1,4 +1,4 @@
-ARCHFLAGS := -arch x86_64 -arch i386 -mmacosx-version-min=10.7
+ARCHFLAGS := -arch x86_64 -mmacosx-version-min=10.7
 CFLAGS := $(ARCHFLAGS) -O3 -I../vamp-plugin-sdk -I/usr/local/boost -Wall -fPIC 
 CXXFLAGS := $(CFLAGS)
 
--- a/PYIN.cpp	Fri Dec 06 16:19:26 2013 +0000
+++ b/PYIN.cpp	Fri Jan 17 12:09:28 2014 +0000
@@ -45,8 +45,13 @@
     m_oNotes(0),
     m_threshDistr(2.0f),
     m_outputUnvoiced(0.0f),
+    m_minLocalFreq(0.f),
+    m_maxLocalFreq(5000.f),
+    m_leftBoundary(0.f),
+    m_rightBoundary(5000.f), // hack
     m_pitchProb(0),
-    m_timestamp(0)
+    m_timestamp(0),
+    m_currentProgram("")
 {
 }
 
@@ -162,6 +167,58 @@
     d.valueNames.push_back("Yes");
     d.valueNames.push_back("Yes, as negative frequencies");
     list.push_back(d);
+    
+    d.identifier = "minlocalfreq";
+    d.valueNames.clear();
+    d.name = "Minimum local frequency.";
+    d.description = "Minimum frequency in selection.";
+    d.unit = "";
+    d.minValue = 50.f;
+    d.maxValue = 5000.f;
+    d.defaultValue = 50.f;
+    d.isQuantized = false;
+    d.quantizeStep = 0;
+    d.valueNames.clear();
+    list.push_back(d);
+
+    d.identifier = "maxlocalfreq";
+    d.valueNames.clear();
+    d.name = "Maximum local frequency.";
+    d.description = "Maximum frequency in selection.";
+    d.unit = "";
+    d.minValue = 50.f;
+    d.maxValue = 5000.f;
+    d.defaultValue = 5000.f;
+    d.isQuantized = false;
+    d.quantizeStep = 0;
+    d.valueNames.clear();
+    list.push_back(d);
+
+    d.identifier = "leftboundary";
+    d.valueNames.clear();
+    d.name = "Left boundary.";
+    d.description = "Left boundary of time selection.";
+    d.unit = "";
+    d.minValue = 0.f;
+    d.maxValue = 1000.f;
+    d.defaultValue = 0.f;
+    d.isQuantized = false;
+    d.quantizeStep = 0;
+    d.valueNames.clear();
+    list.push_back(d);
+
+    d.identifier = "rightboundary";
+    d.valueNames.clear();
+    d.name = "Right boundary.";
+    d.description = "Right boundary of time selection.";
+    d.unit = "";
+    d.minValue = 0.f;
+    d.maxValue = 1000.f;
+    d.defaultValue = 0.f;
+    d.isQuantized = false;
+    d.quantizeStep = 0;
+    d.valueNames.clear();
+    list.push_back(d);
 
     return list;
 }
@@ -175,12 +232,25 @@
     if (identifier == "outputunvoiced") {
             return m_outputUnvoiced;
     }
+    if (identifier == "minlocalfreq") {
+            return m_minLocalFreq;
+    }
+    if (identifier == "maxlocalfreq") {
+            return m_maxLocalFreq;
+    }
+    if (identifier == "leftboundary") {
+            return m_leftBoundary;
+    }
+    if (identifier == "rightboundary") {
+            return m_rightBoundary;
+    }
     return 0.f;
 }
 
 void
 PYIN::setParameter(string identifier, float value) 
 {
+    m_currentProgram = "custom";
     if (identifier == "threshdistr")
     {
         m_threshDistr = value;
@@ -189,25 +259,60 @@
     {
         m_outputUnvoiced = value;
     }
-    
+    if (identifier == "minlocalfreq")
+    {
+        m_minLocalFreq = value;
+    }
+    if (identifier == "maxlocalfreq")
+    {
+        m_maxLocalFreq = value;
+    }
+    if (identifier == "leftboundary")
+    {
+        m_leftBoundary = value;
+    }
+    if (identifier == "rightboundary")
+    {
+        m_rightBoundary = value;
+    }
 }
 
 PYIN::ProgramList
 PYIN::getPrograms() const
 {
     ProgramList list;
+    list.push_back("default");
+    list.push_back("custom");
+    list.push_back("donttellme");
     return list;
 }
 
 string
 PYIN::getCurrentProgram() const
 {
-    return ""; // no programs
+    return m_currentProgram;
 }
 
 void
 PYIN::selectProgram(string name)
 {
+    if (name == "default") {
+        m_minLocalFreq = 0;
+        m_maxLocalFreq = 10000;
+        m_leftBoundary = 0;
+        m_rightBoundary = 5000;
+    }
+    if (name == "custom") {
+        // do nothing
+    }
+    if (name == "donttellme")
+    {
+        m_currentProgram = "donttellme";
+        m_minLocalFreq = 0;
+        m_maxLocalFreq = 400;
+        m_leftBoundary = 1.9;
+        m_rightBoundary = 2.9;
+    }
 }
 
 PYIN::OutputList
@@ -360,7 +465,16 @@
     double *dInputBuffers = new double[m_blockSize];
     for (size_t i = 0; i < m_blockSize; ++i) dInputBuffers[i] = inputBuffers[0][i];
     
-    Yin::YinOutput yo = m_yin.processProbabilisticYin(dInputBuffers);
+    Yin::YinOutput yo;
+    float floatTime = timestamp.sec + timestamp.nsec * 1.0 / 1000000000;
+    std::cerr << timestamp << " " << floatTime << std::endl;
+    if (floatTime > m_leftBoundary && floatTime < m_rightBoundary) {
+        // constrained
+        yo = m_yin.processProbabilisticYin(dInputBuffers, m_minLocalFreq, m_maxLocalFreq);
+    } else {
+        yo = m_yin.processProbabilisticYin(dInputBuffers);
+    }
+    
     
     Feature f;
     f.hasTimestamp = true;
--- a/PYIN.h	Fri Dec 06 16:19:26 2013 +0000
+++ b/PYIN.h	Fri Jan 17 12:09:28 2014 +0000
@@ -72,8 +72,13 @@
 
     float m_threshDistr;
     float m_outputUnvoiced;
+    float m_minLocalFreq;
+    float m_maxLocalFreq;
+    float m_leftBoundary;
+    float m_rightBoundary;
     vector<vector<pair<double, double> > > m_pitchProb;
     vector<Vamp::RealTime> m_timestamp;
+    std::string m_currentProgram;
 };
 
 #endif
--- a/Yin.cpp	Fri Dec 06 16:19:26 2013 +0000
+++ b/Yin.cpp	Fri Jan 17 12:09:28 2014 +0000
@@ -81,7 +81,7 @@
 }
 
 Yin::YinOutput
-Yin::processProbabilisticYin(const double *in) const {
+Yin::processProbabilisticYin(const double *in, float minFreq, float maxFreq) const {
     
     double* yinBuffer = new double[m_yinBufferSize];
 
@@ -89,7 +89,18 @@
     YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);    
     YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
 
-    vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
+    vector<double> peakProbability;
+    if ((minFreq < 0 && maxFreq < 0) ||  maxFreq < minFreq)
+    {
+        peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
+    } else {
+        if (minFreq < 0) minFreq = 0;
+        if (maxFreq < 0) maxFreq = m_inputSampleRate / 2;
+        int minTau = m_inputSampleRate / maxFreq;
+        int maxTau = m_inputSampleRate / minFreq;
+        peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize, minTau, maxTau);
+    }
+    
     
     // calculate overall "probability" from peak probability
     double probSum = 0;
--- a/Yin.h	Fri Dec 06 16:19:26 2013 +0000
+++ b/Yin.h	Fri Jan 17 12:09:28 2014 +0000
@@ -55,7 +55,8 @@
     int setFrameSize(size_t frameSize);
     // int setRemoveUnvoiced(bool frameSize);
     YinOutput process(const double *in) const;
-    YinOutput processProbabilisticYin(const double *in) const;
+    YinOutput processProbabilisticYin(const double *in,
+                                      float minFreq = -1, float maxFreq = -1) const;
 
 private:
     mutable size_t m_frameSize;
--- a/YinUtil.cpp	Fri Dec 06 16:19:26 2013 +0000
+++ b/YinUtil.cpp	Fri Jan 17 12:09:28 2014 +0000
@@ -166,10 +166,24 @@
 
 
 std::vector<double>
-YinUtil::yinProb(const double *yinBuffer, const size_t prior, const size_t yinBufferSize) 
+YinUtil::yinProb(const double *yinBuffer, const size_t prior, 
+                 const size_t yinBufferSize,
+                 size_t minTau, size_t maxTau) 
 {
     double minWeight = 0.01;
-    size_t tau;
+    
+    // sortint out min and max tau -- could be done more elegantly
+    size_t tau = 2;
+    if (minTau >= tau && minTau < yinBufferSize)
+    {
+        tau = minTau;
+    } else {
+        tau = 2;
+    }
+    if (maxTau < minTau) maxTau = yinBufferSize;
+    maxTau = std::min(maxTau, yinBufferSize);
+    std::cerr << maxTau << std::endl;
+
     std::vector<float> thresholds;
     std::vector<float> distribution;
     std::vector<double> peakProb = std::vector<double>(yinBufferSize);
@@ -229,11 +243,10 @@
     //     }
     // }
     // if (minYin < 0.01) std::cerr << "min Yin buffer element: " << minYin << std::endl;
-    
-    
+
+
     int currThreshInd = nThreshold-1;
-    tau = 2;
-    
+
     // double factor = 1.0 / (0.25 * (nThresholdInt+1) * (nThresholdInt + 1)); // factor to scale down triangular weight
     size_t minInd = 0;
     float minVal = 42.f;
@@ -241,7 +254,7 @@
     {
         if (yinBuffer[tau] < thresholds[currThreshInd])
         {
-            while (tau + 1 < yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau])
+            while (tau + 1 < maxTau && yinBuffer[tau+1] < yinBuffer[tau])
             {
                 tau++;
             }
@@ -258,7 +271,7 @@
         }
     }
     double nonPeakProb = 1;
-    for (size_t i = 0; i < yinBufferSize; ++i)
+    for (size_t i = minTau; i < maxTau; ++i)
     {
         nonPeakProb -= peakProb[i];
     }
--- a/YinUtil.h	Fri Dec 06 16:19:26 2013 +0000
+++ b/YinUtil.h	Fri Jan 17 12:09:28 2014 +0000
@@ -33,7 +33,9 @@
     static void fastDifference(const double *in, double *yinBuffer, const size_t yinBufferSize);
     static void cumulativeDifference(double *yinBuffer, const size_t yinBufferSize);
     static int absoluteThreshold(const double *yinBuffer, const size_t yinBufferSize, const double thresh);
-    static vector<double> yinProb(const double *yinBuffer, const size_t prior, const size_t yinBufferSize);
+    static vector<double> yinProb(const double *yinBuffer, const size_t prior, 
+                                  const size_t yinBufferSize, 
+                                  const size_t minTau = 2, const size_t maxTau = 0);
     static double parabolicInterpolation(const double *yinBuffer, const size_t tau,
                                          const size_t yinBufferSize);
 };