Mercurial > hg > vamp-simple-cepstrum
diff CepstrumPitchTracker.cpp @ 21:df41333abbc9 track
A first crack at turning frequencies into notes
author | Chris Cannam |
---|---|
date | Tue, 03 Jul 2012 21:10:56 +0100 |
parents | 7786d595d2f2 |
children | a949c0278d7d |
line wrap: on
line diff
--- a/CepstrumPitchTracker.cpp Mon Jul 02 21:37:02 2012 +0100 +++ b/CepstrumPitchTracker.cpp Tue Jul 03 21:10:56 2012 +0100 @@ -31,6 +31,7 @@ using std::string; using std::vector; +using Vamp::RealTime; CepstrumPitchTracker::Hypothesis::Hypothesis() { @@ -48,10 +49,22 @@ if (m_pending.empty()) { return true; } + + Estimate first = m_pending[0]; Estimate last = m_pending[m_pending.size()-1]; + + // check we are within a relatively close tolerance of the last + // candidate double r = s.freq / last.freq; int cents = lrint(1200.0 * (log(r) / log(2.0))); - return (cents > -100 && cents < 100); + if (cents < -40 || cents > 40) return false; + + // and within a wider tolerance of our starting candidate + r = s.freq / first.freq; + cents = lrint(1200.0 * (log(r) / log(2.0))); + if (cents < -80 || cents > 80) return false; + + return true; } bool @@ -145,16 +158,54 @@ } } +CepstrumPitchTracker::Hypothesis::Note +CepstrumPitchTracker::Hypothesis::getAveragedNote() +{ + 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::iterator i = m_pending.end(); + --i; + n.duration = i->time - n.time; + + // just mean frequency for now, but this isn't at all right + double acc = 0.0; + for (int i = 0; i < m_pending.size(); ++i) { + acc += m_pending[i].freq; + } + acc /= m_pending.size(); + n.freq = acc; + + return n; +} + void -CepstrumPitchTracker::Hypothesis::addFeatures(FeatureList &fl) +CepstrumPitchTracker::Hypothesis::addFeatures(FeatureSet &fs) { for (int i = 0; i < m_pending.size(); ++i) { Feature f; f.hasTimestamp = true; f.timestamp = m_pending[i].time; f.values.push_back(m_pending[i].freq); - fl.push_back(f); + fs[0].push_back(f); } + + Feature nf; + nf.hasTimestamp = true; + nf.hasDuration = true; + Note n = getAveragedNote(); + nf.timestamp = n.time; + nf.duration = n.duration; + nf.values.push_back(n.freq); + fs[1].push_back(nf); } CepstrumPitchTracker::CepstrumPitchTracker(float inputSampleRate) : @@ -303,6 +354,21 @@ d.hasDuration = false; outputs.push_back(d); + d.identifier = "notes"; + d.name = "Notes"; + d.description = "Derived fixed-pitch note frequencies"; + d.unit = "Hz"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = true; + d.minValue = m_fmin; + d.maxValue = m_fmax; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = (m_inputSampleRate / m_stepSize); + d.hasDuration = true; + outputs.push_back(d); + return outputs; } @@ -358,7 +424,7 @@ } CepstrumPitchTracker::FeatureSet -CepstrumPitchTracker::process(const float *const *inputBuffers, Vamp::RealTime timestamp) +CepstrumPitchTracker::process(const float *const *inputBuffers, RealTime timestamp) { FeatureSet fs; @@ -466,7 +532,7 @@ } if (m_accepted.getState() == Hypothesis::Expired) { - m_accepted.addFeatures(fs[0]); + m_accepted.addFeatures(fs); } if (m_accepted.getState() == Hypothesis::Expired || @@ -503,7 +569,7 @@ { FeatureSet fs; if (m_accepted.getState() == Hypothesis::Satisfied) { - m_accepted.addFeatures(fs[0]); + m_accepted.addFeatures(fs); } return fs; }