Mercurial > hg > pyin
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
--- /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" ;