# HG changeset patch # User Chris Cannam # Date 1378110574 -3600 # Node ID c4837ed2eeb156e8941347a1d7d70b9638cba799 # Parent 592ac92002a8b66ed8a420441b93cf948d41bec6# Parent edad8a88a0749d79a8fdd44bf906455dd5b9dd1b Merge mepd_new_params branch diff -r 592ac92002a8 -r c4837ed2eeb1 plugins/BarBeatTrack.cpp --- a/plugins/BarBeatTrack.cpp Wed Dec 12 15:28:33 2012 +0000 +++ b/plugins/BarBeatTrack.cpp Mon Sep 02 09:29:34 2013 +0100 @@ -35,20 +35,20 @@ { public: BarBeatTrackerData(float rate, const DFConfig &config) : dfConfig(config) { - df = new DetectionFunction(config); + df = new DetectionFunction(config); // decimation factor aims at resampling to c. 3KHz; must be power of 2 int factor = MathUtilities::nextPowerOfTwo(rate / 3000); // std::cerr << "BarBeatTrackerData: factor = " << factor << std::endl; downBeat = new DownBeat(rate, factor, config.stepSize); } ~BarBeatTrackerData() { - delete df; + delete df; delete downBeat; } void reset() { - delete df; - df = new DetectionFunction(dfConfig); - dfOutput.clear(); + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); downBeat->resetAudioBuffer(); origin = Vamp::RealTime::zeroTime; } @@ -59,12 +59,16 @@ vector dfOutput; Vamp::RealTime origin; }; - + BarBeatTracker::BarBeatTracker(float inputSampleRate) : Vamp::Plugin(inputSampleRate), m_d(0), - m_bpb(4) + m_bpb(4), + m_alpha(0.9), // changes are as per the BeatTrack.cpp + m_tightness(4.), // changes are as per the BeatTrack.cpp + m_inputtempo(120.), // changes are as per the BeatTrack.cpp + m_constraintempo(false) // changes are as per the BeatTrack.cpp { } @@ -100,7 +104,7 @@ int BarBeatTracker::getPluginVersion() const { - return 2; + return 3; } string @@ -126,32 +130,103 @@ desc.quantizeStep = 1; list.push_back(desc); + // changes are as per the BeatTrack.cpp + //Alpha Parameter of Beat Tracker + desc.identifier = "alpha"; + desc.name = "Alpha"; + desc.description = "Inertia - Flexibility Trade Off"; + desc.minValue = 0.1; + desc.maxValue = 0.99; + desc.defaultValue = 0.90; + desc.unit = ""; + desc.isQuantized = false; + list.push_back(desc); + + + // changes are as per the BeatTrack.cpp + //Tightness Parameter of Beat Tracker + desc.identifier = "tightness"; + desc.name = "Tightness"; + desc.description = "Inertia - Flexibility Trade Off 2"; + desc.minValue = 3; + desc.maxValue = 7; + desc.defaultValue = 4; + desc.unit = ""; + desc.isQuantized = true; + list.push_back(desc); + + // changes are as per the BeatTrack.cpp + //User input tempo + desc.identifier = "inputtempo"; + desc.name = "InputTempo"; + desc.description = "User defined Tempo"; + desc.minValue = 50; + desc.maxValue = 250; + desc.defaultValue = 120; + desc.unit = "BPM"; + desc.isQuantized = true; + list.push_back(desc); + + // changes are as per the BeatTrack.cpp + desc.identifier = "constraintempo"; + desc.name = "Constrain Tempo"; + desc.description = "Constrain tempo to use Gaussian weighting"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = ""; + desc.valueNames.clear(); + list.push_back(desc); + + return list; } float BarBeatTracker::getParameter(std::string name) const { - if (name == "bpb") return m_bpb; + if (name == "bpb") { + return m_bpb; + } else if (name == "alpha") { + return m_alpha; + } else if (name == "tightness") { + return m_tightness; + } else if (name == "inputtempo") { + return m_inputtempo; + } else if (name == "constraintempo") { + return m_constraintempo ? 1.0 : 0.0; + } return 0.0; } void BarBeatTracker::setParameter(std::string name, float value) { - if (name == "bpb") m_bpb = lrintf(value); + if (name == "bpb") { + m_bpb = lrintf(value); + } else if (name == "alpha") { + m_alpha = value; + } else if (name == "tightness") { + m_tightness = value; + } else if (name == "inputtempo") { + m_inputtempo = value; + } else if (name == "constraintempo") { + m_constraintempo = (value > 0.5); + } } bool BarBeatTracker::initialise(size_t channels, size_t stepSize, size_t blockSize) { if (m_d) { - delete m_d; - m_d = 0; + delete m_d; + m_d = 0; } if (channels < getMinChannelCount() || - channels > getMaxChannelCount()) { + channels > getMaxChannelCount()) { std::cerr << "BarBeatTracker::initialise: Unsupported channel count: " << channels << std::endl; return false; @@ -177,7 +252,7 @@ dfConfig.adaptiveWhitening = false; dfConfig.whiteningRelaxCoeff = -1; dfConfig.whiteningFloor = -1; - + m_d = new BarBeatTrackerData(m_inputSampleRate, dfConfig); m_d->downBeat->setBeatsPerBar(m_bpb); return true; @@ -267,10 +342,10 @@ Vamp::RealTime timestamp) { if (!m_d) { - cerr << "ERROR: BarBeatTracker::process: " - << "BarBeatTracker has not been initialised" - << endl; - return FeatureSet(); + cerr << "ERROR: BarBeatTracker::process: " + << "BarBeatTracker has not been initialised" + << endl; + return FeatureSet(); } // We use time domain input, because DownBeat requires it -- so we @@ -311,10 +386,10 @@ BarBeatTracker::getRemainingFeatures() { if (!m_d) { - cerr << "ERROR: BarBeatTracker::getRemainingFeatures: " - << "BarBeatTracker has not been initialised" - << endl; - return FeatureSet(); + cerr << "ERROR: BarBeatTracker::getRemainingFeatures: " + << "BarBeatTracker has not been initialised" + << endl; + return FeatureSet(); } return barBeatTrack(); @@ -334,10 +409,18 @@ if (df.empty()) return FeatureSet(); TempoTrackV2 tt(m_inputSampleRate, m_d->dfConfig.stepSize); - tt.calculateBeatPeriod(df, beatPeriod, tempi); + + // changes are as per the BeatTrack.cpp - allow m_inputtempo and m_constraintempo to be set be the user + tt.calculateBeatPeriod(df, beatPeriod, tempi, m_inputtempo, m_constraintempo); vector beats; - tt.calculateBeats(df, beatPeriod, beats); + // changes are as per the BeatTrack.cpp - allow m_alpha and m_tightness to be set be the user + tt.calculateBeats(df, beatPeriod, beats, m_alpha, m_tightness); + + // tt.calculateBeatPeriod(df, beatPeriod, tempi, 0., 0); // use default parameters + + // vector beats; + // tt.calculateBeats(df, beatPeriod, beats, 0.9, 4.); // use default parameters until i fix this plugin too vector downbeats; size_t downLength = 0; @@ -349,7 +432,7 @@ // std::cerr << "BarBeatTracker: found downbeats at: "; // for (int i = 0; i < downbeats.size(); ++i) std::cerr << downbeats[i] << " " << std::endl; - + FeatureSet returnFeatures; char label[20]; @@ -368,7 +451,7 @@ for (size_t i = 0; i < beats.size(); ++i) { - size_t frame = beats[i] * m_d->dfConfig.stepSize; + size_t frame = beats[i] * m_d->dfConfig.stepSize; if (dbi < downbeats.size() && i == downbeats[dbi]) { beat = 0; @@ -383,15 +466,15 @@ // 0 -> beats // 1 -> bars // 2 -> beat counter function - - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime - (frame, lrintf(m_inputSampleRate)); + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); sprintf(label, "%d", beat + 1); feature.label = label; - returnFeatures[0].push_back(feature); // labelled beats + returnFeatures[0].push_back(feature); // labelled beats feature.values.push_back(beat + 1); returnFeatures[2].push_back(feature); // beat function diff -r 592ac92002a8 -r c4837ed2eeb1 plugins/BarBeatTrack.h --- a/plugins/BarBeatTrack.h Wed Dec 12 15:28:33 2012 +0000 +++ b/plugins/BarBeatTrack.h Mon Sep 02 09:29:34 2013 +0100 @@ -56,6 +56,13 @@ static float m_stepSecs; int m_bpb; FeatureSet barBeatTrack(); + + // MEPD new protected parameters to allow the user to control these advanced parameters of the beat tracker + // changes are as per the BeatTrack.h + double m_alpha; + double m_tightness; + double m_inputtempo; + bool m_constraintempo; }; diff -r 592ac92002a8 -r c4837ed2eeb1 plugins/BeatTrack.cpp --- a/plugins/BeatTrack.cpp Wed Dec 12 15:28:33 2012 +0000 +++ b/plugins/BeatTrack.cpp Mon Sep 02 09:29:34 2013 +0100 @@ -33,15 +33,15 @@ { public: BeatTrackerData(const DFConfig &config) : dfConfig(config) { - df = new DetectionFunction(config); + df = new DetectionFunction(config); } ~BeatTrackerData() { - delete df; + delete df; } void reset() { - delete df; - df = new DetectionFunction(dfConfig); - dfOutput.clear(); + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); origin = Vamp::RealTime::zeroTime; } @@ -50,14 +50,20 @@ vector dfOutput; Vamp::RealTime origin; }; - + BeatTracker::BeatTracker(float inputSampleRate) : Vamp::Plugin(inputSampleRate), m_d(0), m_method(METHOD_NEW), m_dfType(DF_COMPLEXSD), - m_whiten(false) + m_whiten(false), + m_alpha(0.9), // MEPD new exposed parameter for beat tracker, default value = 0.9 (as old version) + m_tightness(4.), // MEPD new exposed parameter for beat tracker, default value = 4. (as old version) + m_inputtempo(120.), // MEPD new exposed parameter for beat tracker, default value = 120. (as old version) + m_constraintempo(false) // MEPD new exposed parameter for beat tracker, default value = false (as old version) + // calling the beat tracker with these default parameters will give the same output as the previous existing version + { } @@ -93,13 +99,13 @@ int BeatTracker::getPluginVersion() const { - return 5; + return 6; } string BeatTracker::getCopyright() const { - return "Plugin by Christian Landone and Matthew Davies. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; + return "Plugin by Christian Landone and Matthew Davies. Copyright (c) 2006-2012 QMUL - All Rights Reserved"; } BeatTracker::ParameterList @@ -147,6 +153,58 @@ desc.valueNames.clear(); list.push_back(desc); + // MEPD new exposed parameter - used in the dynamic programming part of the beat tracker + //Alpha Parameter of Beat Tracker + desc.identifier = "alpha"; + desc.name = "Alpha"; + desc.description = "Inertia - Flexibility Trade Off"; + desc.minValue = 0.1; + desc.maxValue = 0.99; + desc.defaultValue = 0.90; + desc.unit = ""; + desc.isQuantized = false; + list.push_back(desc); + + + // MEPD new exposed parameter - used in the dynamic programming part of the beat tracker + //Tightness Parameter of Beat Tracker + desc.identifier = "tightness"; + desc.name = "Tightness"; + desc.description = "Inertia - Flexibility Trade Off 2"; + desc.minValue = 3; + desc.maxValue = 7; + desc.defaultValue = 4; + desc.unit = ""; + desc.isQuantized = true; + list.push_back(desc); + + // MEPD new exposed parameter - used in the periodicity estimation + //User input tempo + desc.identifier = "inputtempo"; + desc.name = "InputTempo"; + desc.description = "User defined Tempo"; + desc.minValue = 50; + desc.maxValue = 250; + desc.defaultValue = 120; + desc.unit = "BPM"; + desc.isQuantized = true; + list.push_back(desc); + + // MEPD new exposed parameter - used in periodicity estimation + desc.identifier = "constraintempo"; + desc.name = "Constrain Tempo"; + desc.description = "Constrain tempo to use Gaussian weighting"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = ""; + desc.valueNames.clear(); + list.push_back(desc); + + + return list; } @@ -164,7 +222,15 @@ } else if (name == "method") { return m_method; } else if (name == "whiten") { - return m_whiten ? 1.0 : 0.0; + return m_whiten ? 1.0 : 0.0; + } else if (name == "alpha") { + return m_alpha; + } else if (name == "tightness") { + return m_tightness; + } else if (name == "inputtempo") { + return m_inputtempo; + } else if (name == "constraintempo") { + return m_constraintempo ? 1.0 : 0.0; } return 0.0; } @@ -184,6 +250,14 @@ m_method = lrintf(value); } else if (name == "whiten") { m_whiten = (value > 0.5); + } else if (name == "alpha") { + m_alpha = value; + } else if (name == "tightness") { + m_tightness = value; + } else if (name == "inputtempo") { + m_inputtempo = value; + } else if (name == "constraintempo") { + m_constraintempo = (value > 0.5); } } @@ -191,12 +265,12 @@ BeatTracker::initialise(size_t channels, size_t stepSize, size_t blockSize) { if (m_d) { - delete m_d; - m_d = 0; + delete m_d; + m_d = 0; } if (channels < getMinChannelCount() || - channels > getMaxChannelCount()) { + channels > getMaxChannelCount()) { std::cerr << "BeatTracker::initialise: Unsupported channel count: " << channels << std::endl; return false; @@ -222,7 +296,7 @@ dfConfig.adaptiveWhitening = m_whiten; dfConfig.whiteningRelaxCoeff = -1; dfConfig.whiteningFloor = -1; - + m_d = new BeatTrackerData(dfConfig); return true; } @@ -302,10 +376,10 @@ Vamp::RealTime timestamp) { if (!m_d) { - cerr << "ERROR: BeatTracker::process: " - << "BeatTracker has not been initialised" - << endl; - return FeatureSet(); + cerr << "ERROR: BeatTracker::process: " + << "BeatTracker has not been initialised" + << endl; + return FeatureSet(); } size_t len = m_d->dfConfig.frameLength / 2; @@ -320,7 +394,7 @@ magnitudes[i] = sqrt(inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] + inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]); - phases[i] = atan2(-inputBuffers[0][i*2+1], inputBuffers[0][i*2]); + phases[i] = atan2(-inputBuffers[0][i*2+1], inputBuffers[0][i*2]); } double output = m_d->df->process(magnitudes, phases); @@ -346,10 +420,10 @@ BeatTracker::getRemainingFeatures() { if (!m_d) { - cerr << "ERROR: BeatTracker::getRemainingFeatures: " - << "BeatTracker has not been initialised" - << endl; - return FeatureSet(); + cerr << "ERROR: BeatTracker::getRemainingFeatures: " + << "BeatTracker has not been initialised" + << endl; + return FeatureSet(); } if (m_method == METHOD_OLD) return beatTrackOld(); @@ -383,33 +457,33 @@ for (size_t i = 0; i < beats.size(); ++i) { - size_t frame = beats[i] * m_d->dfConfig.stepSize; + size_t frame = beats[i] * m_d->dfConfig.stepSize; - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime - (frame, lrintf(m_inputSampleRate)); + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); - float bpm = 0.0; - int frameIncrement = 0; + float bpm = 0.0; + int frameIncrement = 0; - if (i < beats.size() - 1) { + if (i < beats.size() - 1) { - frameIncrement = (beats[i+1] - beats[i]) * m_d->dfConfig.stepSize; + frameIncrement = (beats[i+1] - beats[i]) * m_d->dfConfig.stepSize; - // one beat is frameIncrement frames, so there are - // samplerate/frameIncrement bps, so - // 60*samplerate/frameIncrement bpm + // 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; + 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 + returnFeatures[0].push_back(feature); // beats are output 0 } double prevTempo = 0.0; @@ -419,7 +493,7 @@ size_t frame = i * m_d->dfConfig.stepSize * ttParams.lagLength; // std::cerr << "unit " << i << ", step size " << m_d->dfConfig.stepSize << ", hop " << ttParams.lagLength << ", frame = " << frame << std::endl; - + if (tempi[i] > 1 && int(tempi[i] * 100) != int(prevTempo * 100)) { Feature feature; feature.hasTimestamp = true; @@ -461,52 +535,56 @@ TempoTrackV2 tt(m_inputSampleRate, m_d->dfConfig.stepSize); - tt.calculateBeatPeriod(df, beatPeriod, tempi); + + // MEPD - note this function is now passed 2 new parameters, m_inputtempo and m_constraintempo + tt.calculateBeatPeriod(df, beatPeriod, tempi, m_inputtempo, m_constraintempo); vector beats; - tt.calculateBeats(df, beatPeriod, beats); - + + // MEPD - note this function is now passed 2 new parameters, m_alpha and m_tightness + tt.calculateBeats(df, beatPeriod, beats, m_alpha, m_tightness); + FeatureSet returnFeatures; char label[100]; for (size_t i = 0; i < beats.size(); ++i) { - size_t frame = beats[i] * m_d->dfConfig.stepSize; - - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime - (frame, lrintf(m_inputSampleRate)); + size_t frame = beats[i] * m_d->dfConfig.stepSize; - float bpm = 0.0; - int frameIncrement = 0; + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); - if (i+1 < beats.size()) { + float bpm = 0.0; + int frameIncrement = 0; - frameIncrement = (beats[i+1] - beats[i]) * m_d->dfConfig.stepSize; + if (i+1 < beats.size()) { - // one beat is frameIncrement frames, so there are - // samplerate/frameIncrement bps, so - // 60*samplerate/frameIncrement bpm + frameIncrement = (beats[i+1] - beats[i]) * m_d->dfConfig.stepSize; - if (frameIncrement > 0) { - bpm = (60.0 * m_inputSampleRate) / frameIncrement; - bpm = int(bpm * 100.0 + 0.5) / 100.0; + // 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 + returnFeatures[0].push_back(feature); // beats are output 0 } double prevTempo = 0.0; for (size_t i = 0; i < tempi.size(); ++i) { - size_t frame = i * m_d->dfConfig.stepSize; - + size_t frame = i * m_d->dfConfig.stepSize; + if (tempi[i] > 1 && int(tempi[i] * 100) != int(prevTempo * 100)) { Feature feature; feature.hasTimestamp = true; @@ -522,4 +600,3 @@ return returnFeatures; } - diff -r 592ac92002a8 -r c4837ed2eeb1 plugins/BeatTrack.h --- a/plugins/BeatTrack.h Wed Dec 12 15:28:33 2012 +0000 +++ b/plugins/BeatTrack.h Mon Sep 02 09:29:34 2013 +0100 @@ -55,6 +55,13 @@ BeatTrackerData *m_d; int m_method; int m_dfType; + + // MEPD new protected parameters to allow the user to control these advanced parameters of the beat tracker + double m_alpha; + double m_tightness; + double m_inputtempo; + bool m_constraintempo; + bool m_whiten; static float m_stepSecs; FeatureSet beatTrackOld();