Mercurial > hg > qm-vamp-plugins
diff plugins/BeatTrack.cpp @ 86:e377296d01b2
* First cut at including Matthew's newer beat tracker
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Tue, 20 Jan 2009 15:01:31 +0000 |
parents | 2631d0b3d7eb |
children | 790e051896a9 |
line wrap: on
line diff
--- a/plugins/BeatTrack.cpp Thu Dec 04 12:03:51 2008 +0000 +++ b/plugins/BeatTrack.cpp Tue Jan 20 15:01:31 2009 +0000 @@ -12,13 +12,17 @@ #include <dsp/onsets/DetectionFunction.h> #include <dsp/onsets/PeakPicking.h> #include <dsp/tempotracking/TempoTrack.h> +#include <dsp/tempotracking/TempoTrackV2.h> using std::string; using std::vector; using std::cerr; using std::endl; -float BeatTracker::m_stepSecs = 0.01161; +float BeatTracker::m_stepSecs = 0.01161; // 512 samples at 44100 + +#define METHOD_OLD 0 +#define METHOD_NEW 1 class BeatTrackerData { @@ -46,6 +50,7 @@ BeatTracker::BeatTracker(float inputSampleRate) : Vamp::Plugin(inputSampleRate), m_d(0), + m_method(METHOD_NEW), m_dfType(DF_COMPLEXSD), m_whiten(false) { @@ -98,14 +103,26 @@ ParameterList list; ParameterDescriptor desc; + + desc.identifier = "method"; + desc.name = "Beat Tracking Method"; + desc.description = ""; //!!! + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = METHOD_NEW; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("Old"); + desc.valueNames.push_back("New"); + list.push_back(desc); + desc.identifier = "dftype"; desc.name = "Onset Detection Function Type"; desc.description = "Method used to calculate the onset detection function"; desc.minValue = 0; desc.maxValue = 4; desc.defaultValue = 3; - desc.isQuantized = true; - desc.quantizeStep = 1; + desc.valueNames.clear(); desc.valueNames.push_back("High-Frequency Content"); desc.valueNames.push_back("Spectral Difference"); desc.valueNames.push_back("Phase Deviation"); @@ -139,6 +156,8 @@ default: case DF_COMPLEXSD: return 3; case DF_BROADBAND: return 4; } + } else if (name == "method") { + return m_method; } else if (name == "whiten") { return m_whiten ? 1.0 : 0.0; } @@ -156,6 +175,8 @@ default: case 3: m_dfType = DF_COMPLEXSD; break; case 4: m_dfType = DF_BROADBAND; break; } + } else if (name == "method") { + m_method = lrintf(value); } else if (name == "whiten") { m_whiten = (value > 0.5); } @@ -327,6 +348,13 @@ return FeatureSet(); } + if (m_method == METHOD_OLD) return beatTrackOld(); + else return beatTrackNew(); +} + +BeatTracker::FeatureSet +BeatTracker::beatTrackOld() +{ double aCoeffs[] = { 1.0000, -0.5949, 0.2348 }; double bCoeffs[] = { 0.1600, 0.3200, 0.1600 }; @@ -403,3 +431,64 @@ return returnFeatures; } +BeatTracker::FeatureSet +BeatTracker::beatTrackNew() +{ + vector<double> df; + vector<double> beatPeriod; + + for (size_t i = 2; i < m_d->dfOutput.size(); ++i) { // discard first two elts + df.push_back(m_d->dfOutput[i]); + beatPeriod.push_back(0.0); + } + if (df.empty()) return FeatureSet(); + + TempoTrackV2 tt; + + tt.calculateBeatPeriod(df, beatPeriod); + + vector<double> beats; + tt.calculateBeats(df, beatPeriod, beats); + + FeatureSet returnFeatures; + + char label[100]; + + for (size_t i = 0; i < beats.size(); ++i) { + + // beats are returned in reverse order? + + size_t index = beats.size() - i - 1; + + size_t frame = beats[index] * m_d->dfConfig.stepSize; + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + + float bpm = 0.0; + int frameIncrement = 0; + + if (index > 0) { + + frameIncrement = (beats[index - 1] - beats[index]) * m_d->dfConfig.stepSize; + + // one beat is frameIncrement frames, so there are + // samplerate/frameIncrement bps, so + // 60*samplerate/frameIncrement bpm + + if (frameIncrement > 0) { + bpm = (60.0 * m_inputSampleRate) / frameIncrement; + bpm = int(bpm * 100.0 + 0.5) / 100.0; + sprintf(label, "%.2f bpm", bpm); + feature.label = label; + } + } + + returnFeatures[0].push_back(feature); // beats are output 0 + } + + return returnFeatures; +} +