Mercurial > hg > cepstral-pitchtracker
changeset 35:2f5b169e4a3b
Integrate NoteHypothesis class, build fixes
author | Chris Cannam |
---|---|
date | Thu, 19 Jul 2012 13:46:45 +0100 |
parents | 3fb9c657d86b |
children | 2a2480689cbf |
files | CepstralPitchTracker.cpp CepstralPitchTracker.h Makefile.inc NoteHypothesis.cpp NoteHypothesis.h |
diffstat | 5 files changed, 36 insertions(+), 245 deletions(-) [+] |
line wrap: on
line diff
--- a/CepstralPitchTracker.cpp Fri Jul 13 22:48:02 2012 +0100 +++ b/CepstralPitchTracker.cpp Thu Jul 19 13:46:45 2012 +0100 @@ -37,161 +37,6 @@ using std::vector; using Vamp::RealTime; -CepstralPitchTracker::Hypothesis::Hypothesis() -{ - m_state = New; -} - -CepstralPitchTracker::Hypothesis::~Hypothesis() -{ -} - -bool -CepstralPitchTracker::Hypothesis::isWithinTolerance(Estimate s) const -{ - if (m_pending.empty()) { - return true; - } - - // check we are within a relatively close tolerance of the last - // candidate - Estimate last = m_pending[m_pending.size()-1]; - double r = s.freq / last.freq; - int cents = lrint(1200.0 * (log(r) / log(2.0))); - if (cents < -60 || cents > 60) return false; - - // and within a slightly bigger tolerance of the current mean - double meanFreq = getMeanFrequency(); - r = s.freq / meanFreq; - cents = lrint(1200.0 * (log(r) / log(2.0))); - if (cents < -80 || cents > 80) return false; - - return true; -} - -bool -CepstralPitchTracker::Hypothesis::isOutOfDateFor(Estimate s) const -{ - if (m_pending.empty()) return false; - - return ((s.time - m_pending[m_pending.size()-1].time) > - RealTime::fromMilliseconds(40)); -} - -bool -CepstralPitchTracker::Hypothesis::isSatisfied() const -{ - if (m_pending.empty()) return false; - - double meanConfidence = 0.0; - for (int i = 0; i < m_pending.size(); ++i) { - meanConfidence += m_pending[i].confidence; - } - meanConfidence /= m_pending.size(); - - int lengthRequired = 10000; - if (meanConfidence > 0.0) { - lengthRequired = int(2.0 / meanConfidence + 0.5); - } - - return (m_pending.size() > lengthRequired); -} - -bool -CepstralPitchTracker::Hypothesis::accept(Estimate s) -{ - bool accept = false; - - switch (m_state) { - - case New: - m_state = Provisional; - accept = true; - break; - - case Provisional: - if (isOutOfDateFor(s)) { - m_state = Rejected; - } else if (isWithinTolerance(s)) { - accept = true; - } - break; - - case Satisfied: - if (isOutOfDateFor(s)) { - m_state = Expired; - } else if (isWithinTolerance(s)) { - accept = true; - } - break; - - case Rejected: - break; - - case Expired: - break; - } - - if (accept) { - m_pending.push_back(s); - if (m_state == Provisional && isSatisfied()) { - m_state = Satisfied; - } - } - - return accept; -} - -CepstralPitchTracker::Hypothesis::State -CepstralPitchTracker::Hypothesis::getState() const -{ - return m_state; -} - -CepstralPitchTracker::Hypothesis::Estimates -CepstralPitchTracker::Hypothesis::getAcceptedEstimates() const -{ - if (m_state == Satisfied || m_state == Expired) { - return m_pending; - } else { - return Estimates(); - } -} - -double -CepstralPitchTracker::Hypothesis::getMeanFrequency() const -{ - double acc = 0.0; - for (int i = 0; i < m_pending.size(); ++i) { - acc += m_pending[i].freq; - } - acc /= m_pending.size(); - return acc; -} - -CepstralPitchTracker::Hypothesis::Note -CepstralPitchTracker::Hypothesis::getAveragedNote() const -{ - Note n; - - if (!(m_state == Satisfied || m_state == Expired)) { - n.freq = 0.0; - n.time = RealTime::zeroTime; - n.duration = RealTime::zeroTime; - return n; - } - - n.time = m_pending.begin()->time; - - Estimates::const_iterator i = m_pending.end(); - --i; - n.duration = i->time - n.time; - - // just mean frequency for now, but this isn't at all right perceptually - n.freq = getMeanFrequency(); - - return n; -} CepstralPitchTracker::CepstralPitchTracker(float inputSampleRate) : Plugin(inputSampleRate), @@ -320,8 +165,6 @@ { OutputList outputs; - int n = 0; - OutputDescriptor d; d.identifier = "f0"; @@ -391,11 +234,11 @@ } void -CepstralPitchTracker::addFeaturesFrom(Hypothesis h, FeatureSet &fs) +CepstralPitchTracker::addFeaturesFrom(NoteHypothesis h, FeatureSet &fs) { - Hypothesis::Estimates es = h.getAcceptedEstimates(); + NoteHypothesis::Estimates es = h.getAcceptedEstimates(); - for (int i = 0; i < es.size(); ++i) { + for (int i = 0; i < (int)es.size(); ++i) { Feature f; f.hasTimestamp = true; f.timestamp = es[i].time; @@ -406,7 +249,7 @@ Feature nf; nf.hasTimestamp = true; nf.hasDuration = true; - Hypothesis::Note n = h.getAveragedNote(); + NoteHypothesis::Note n = h.getAveragedNote(); nf.timestamp = n.time; nf.duration = n.duration; nf.values.push_back(n.freq); @@ -422,7 +265,7 @@ // average according to the vertical filter length for (int j = -m_vflen/2; j <= m_vflen/2; ++j) { int ix = i + m_binFrom + j; - if (ix >= 0 && ix < m_blockSize) { + if (ix >= 0 && ix < (int)m_blockSize) { v += cep[ix]; ++n; } @@ -575,24 +418,19 @@ std::cerr << "magmean = " << magmean << ", confidence = " << confidence << std::endl; } - Hypothesis::Estimate e; + NoteHypothesis::Estimate e; e.freq = peakfreq; e.time = timestamp; e.confidence = confidence; -// m_good.advanceTime(); - for (int i = 0; i < m_possible.size(); ++i) { -// m_possible[i].advanceTime(); - } - if (!m_good.accept(e)) { int candidate = -1; bool accepted = false; - for (int i = 0; i < m_possible.size(); ++i) { + for (int i = 0; i < (int)m_possible.size(); ++i) { if (m_possible[i].accept(e)) { - if (m_possible[i].getState() == Hypothesis::Satisfied) { + if (m_possible[i].getState() == NoteHypothesis::Satisfied) { accepted = true; candidate = i; } @@ -601,31 +439,31 @@ } if (!accepted) { - Hypothesis h; + NoteHypothesis h; h.accept(e); //!!! must succeed as h is new, so perhaps there should be a ctor for this m_possible.push_back(h); } - if (m_good.getState() == Hypothesis::Expired) { + if (m_good.getState() == NoteHypothesis::Expired) { addFeaturesFrom(m_good, fs); } - if (m_good.getState() == Hypothesis::Expired || - m_good.getState() == Hypothesis::Rejected) { + if (m_good.getState() == NoteHypothesis::Expired || + m_good.getState() == NoteHypothesis::Rejected) { if (candidate >= 0) { m_good = m_possible[candidate]; } else { - m_good = Hypothesis(); + m_good = NoteHypothesis(); } } // reap rejected/expired hypotheses from possible list Hypotheses toReap = m_possible; m_possible.clear(); - for (int i = 0; i < toReap.size(); ++i) { - Hypothesis h = toReap[i]; - if (h.getState() != Hypothesis::Rejected && - h.getState() != Hypothesis::Expired) { + for (int i = 0; i < (int)toReap.size(); ++i) { + NoteHypothesis h = toReap[i]; + if (h.getState() != NoteHypothesis::Rejected && + h.getState() != NoteHypothesis::Expired) { m_possible.push_back(h); } } @@ -639,7 +477,7 @@ CepstralPitchTracker::getRemainingFeatures() { FeatureSet fs; - if (m_good.getState() == Hypothesis::Satisfied) { + if (m_good.getState() == NoteHypothesis::Satisfied) { addFeaturesFrom(m_good, fs); } return fs;
--- a/CepstralPitchTracker.h Fri Jul 13 22:48:02 2012 +0100 +++ b/CepstralPitchTracker.h Thu Jul 19 13:46:45 2012 +0100 @@ -22,11 +22,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _CEPSTRUM_PITCH_H_ -#define _CEPSTRUM_PITCH_H_ +#ifndef _CEPSTRAL_PITCH_H_ +#define _CEPSTRAL_PITCH_H_ #include <vamp-sdk/Plugin.h> +#include "NoteHypothesis.h" + class CepstralPitchTracker : public Vamp::Plugin { public: @@ -76,54 +78,11 @@ int m_binTo; int m_bins; // count of "interesting" bins, those returned in m_cepOutput - class Hypothesis { + typedef std::vector<NoteHypothesis> Hypotheses; + Hypotheses m_possible; + NoteHypothesis m_good; - public: - struct Estimate { - double freq; - Vamp::RealTime time; - double confidence; - }; - typedef std::vector<Estimate> Estimates; - - struct Note { - double freq; - Vamp::RealTime time; - Vamp::RealTime duration; - }; - - Hypothesis(); - ~Hypothesis(); - - enum State { - New, - Provisional, - Satisfied, - Rejected, - Expired - }; - - bool accept(Estimate); - - State getState() const; - Estimates getAcceptedEstimates() const; - Note getAveragedNote() const; - - private: - bool isWithinTolerance(Estimate) const; - bool isOutOfDateFor(Estimate) const; - bool isSatisfied() const; - double getMeanFrequency() const; - - State m_state; - Estimates m_pending; - }; - - typedef std::vector<Hypothesis> Hypotheses; - Hypotheses m_possible; - Hypothesis m_good; - - void addFeaturesFrom(Hypothesis h, FeatureSet &fs); + void addFeaturesFrom(NoteHypothesis h, FeatureSet &fs); void filter(const double *in, double *out); double cubicInterpolate(const double[4], double);
--- a/Makefile.inc Fri Jul 13 22:48:02 2012 +0100 +++ b/Makefile.inc Thu Jul 19 13:46:45 2012 +0100 @@ -8,9 +8,11 @@ CXXFLAGS := $(CXXFLAGS) LDFLAGS := $(LDFLAGS) -HEADERS := CepstralPitchTracker.h +HEADERS := CepstralPitchTracker.h \ + NoteHypothesis.h SOURCES := CepstralPitchTracker.cpp \ + NoteHypothesis.cpp \ libmain.cpp OBJECTS := $(SOURCES:.cpp=.o)
--- a/NoteHypothesis.cpp Fri Jul 13 22:48:02 2012 +0100 +++ b/NoteHypothesis.cpp Thu Jul 19 13:46:45 2012 +0100 @@ -5,9 +5,7 @@ #include <cmath> -#include "system/sysutils.h" - -namespace Turbot { +using Vamp::RealTime; NoteHypothesis::NoteHypothesis() { @@ -166,5 +164,3 @@ return n; } -} -
--- a/NoteHypothesis.h Fri Jul 13 22:48:02 2012 +0100 +++ b/NoteHypothesis.h Thu Jul 19 13:46:45 2012 +0100 @@ -4,11 +4,9 @@ #ifndef _NOTE_HYPOTHESIS_H_ #define _NOTE_HYPOTHESIS_H_ -#include "base/RealTime.h" +#include "vamp-sdk/RealTime.h" #include <vector> -namespace Turbot { - /** * An agent used to test an incoming series of instantaneous pitch * estimates to see whether they fit a consistent single-note @@ -50,13 +48,13 @@ struct Estimate { Estimate() : freq(0), time(), confidence(0) { } - Estimate(double _f, RealTime _t, double _c) : + Estimate(double _f, Vamp::RealTime _t, double _c) : freq(_f), time(_t), confidence(_c) { } bool operator==(const Estimate &e) const { return e.freq == freq && e.time == time && e.confidence == confidence; } double freq; - RealTime time; + Vamp::RealTime time; double confidence; }; typedef std::vector<Estimate> Estimates; @@ -83,14 +81,14 @@ struct Note { Note() : freq(0), time(), duration() { } - Note(double _f, RealTime _t, RealTime _d) : + Note(double _f, Vamp::RealTime _t, Vamp::RealTime _d) : freq(_f), time(_t), duration(_d) { } bool operator==(const Note &e) const { return e.freq == freq && e.time == time && e.duration == duration; } double freq; - RealTime time; - RealTime duration; + Vamp::RealTime time; + Vamp::RealTime duration; }; /** @@ -112,6 +110,4 @@ Estimates m_pending; }; -} - #endif