changeset 49:4db418fafb6d tony

added new plugin for yin constrained frequency estimation
author matthiasm
date Fri, 28 Feb 2014 17:51:29 +0000
parents b8cdbefd2c58
children 85eb802a8091
files Makefile.inc Yin.cpp Yin.h YinVamp.cpp YinVampFreqConstrained.cpp YinVampFreqConstrained.h libmain.cpp
diffstat 7 files changed, 380 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.inc	Mon Feb 24 17:39:45 2014 +0000
+++ b/Makefile.inc	Fri Feb 28 17:51:29 2014 +0000
@@ -12,6 +12,7 @@
 SOURCES := PYinVamp.cpp \
            YinVamp.cpp \
            LocalCandidatePYIN.cpp \
+           YinVampFreqConstrained.cpp \
            Yin.cpp \
            YinUtil.cpp \
            MonoNote.cpp \
@@ -66,6 +67,7 @@
 
 PYinVamp.o: PYinVamp.h
 YinVamp.o: YinVamp.h
+YinVampFreqConstrained.o: YinVampFreqConstrained.h
 LocalCandidatePYIN.o: LocalCandidatePYIN.h
 Yin.o: Yin.h
 MonoNoteParameters.o: MonoNoteParameters.h
--- a/Yin.cpp	Mon Feb 24 17:39:45 2014 +0000
+++ b/Yin.cpp	Fri Feb 28 17:51:29 2014 +0000
@@ -144,3 +144,38 @@
 //     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::fastDifference(in, yinBuffer, m_yinBufferSize);    
+    YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
+    
+    int minPeriod = m_inputSampleRate / maxFreq;
+    int maxPeriod = m_inputSampleRate / minFreq;
+    
+    if (minPeriod < 0 || maxPeriod > 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);
+}
\ No newline at end of file
--- a/Yin.h	Mon Feb 24 17:39:45 2014 +0000
+++ b/Yin.h	Fri Feb 28 17:51:29 2014 +0000
@@ -56,6 +56,7 @@
     // 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;
--- a/YinVamp.cpp	Mon Feb 24 17:39:45 2014 +0000
+++ b/YinVamp.cpp	Fri Feb 28 17:51:29 2014 +0000
@@ -135,18 +135,6 @@
         
     list.push_back(d);
 
-    // d.identifier = "removeunvoiced";
-    // d.name = "Remove pitches classified as unvoiced.";
-    // d.description = "If ticked, then the pitch estimator will return the most likely pitch, even if it 'thinks' there isn't any.";
-    // d.unit = "";
-    // d.minValue = 0.0f;
-    // d.maxValue = 1.0f;
-    // d.defaultValue = 0.0f;
-    // d.isQuantized = true;
-    // d.quantizeStep = 1.0f;
-    // d.valueNames.clear();
-    // list.push_back(d);
-
     d.identifier = "outputunvoiced";
     d.valueNames.clear();
     d.name = "Output estimates classified as unvoiced?";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/YinVampFreqConstrained.cpp	Fri Feb 28 17:51:29 2014 +0000
@@ -0,0 +1,269 @@
+/* -*- 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/4, 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/YinVampFreqConstrained.h	Fri Feb 28 17:51:29 2014 +0000
@@ -0,0 +1,70 @@
+/* -*- 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
--- a/libmain.cpp	Mon Feb 24 17:39:45 2014 +0000
+++ b/libmain.cpp	Fri Feb 28 17:51:29 2014 +0000
@@ -17,10 +17,12 @@
 #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)
@@ -31,6 +33,7 @@
     case  0: return pyinvampPluginAdapter.getDescriptor();
     case  1: return yinvampPluginAdapter.getDescriptor();
     case  2: return localCandidatePYINPluginAdapter.getDescriptor();
+    case  3: return yinVampFreqConstrainedPluginAdapter.getDescriptor();
     default: return 0;
     }
 }