# HG changeset patch # User matthiasm # Date 1393609889 0 # Node ID 4db418fafb6dcd077ce54a99f4909e3ab798c8cf # Parent b8cdbefd2c588027767b9985651a582f7c8172bd added new plugin for yin constrained frequency estimation diff -r b8cdbefd2c58 -r 4db418fafb6d Makefile.inc --- 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 diff -r b8cdbefd2c58 -r 4db418fafb6d Yin.cpp --- 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 diff -r b8cdbefd2c58 -r 4db418fafb6d Yin.h --- 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; diff -r b8cdbefd2c58 -r 4db418fafb6d YinVamp.cpp --- 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?"; diff -r b8cdbefd2c58 -r 4db418fafb6d YinVampFreqConstrained.cpp --- /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 +#include + +#include +#include +#include + +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; +} diff -r b8cdbefd2c58 -r 4db418fafb6d YinVampFreqConstrained.h --- /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 + +#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 diff -r b8cdbefd2c58 -r 4db418fafb6d libmain.cpp --- 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 pyinvampPluginAdapter; static Vamp::PluginAdapter yinvampPluginAdapter; static Vamp::PluginAdapter localCandidatePYINPluginAdapter; +static Vamp::PluginAdapter 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; } }