# HG changeset patch # User Chris Cannam # Date 1746520988 -3600 # Tue May 06 09:43:08 2025 +0100 # Node ID 23f7f647f2c6c385536c08559ad4cd48d49f5997 # Parent aa008596444d783bb3ffc22f161fa289ea53c730 # Parent 1bd6f905377d993a40f4a084659c5232fce46324 Merge from branch higher-precision diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -3,4 +3,6 @@ re:^doc/html/ re:^doc/latex/ *.so +*.o +*.a re:^tests/test-minibpm$ diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Written by Chris Cannam, chris.cannam@breakfastquay.com. Published by Particular Programs Ltd t/a Breakfast Quay. -Copyright 2007-2021 Particular Programs Ltd. +Copyright 2007-2025 Particular Programs Ltd. * About MiniBPM: https://breakfastquay.com/minibpm/ * Code repository: https://hg.sr.ht/~breakfastquay/minibpm diff --git a/com/breakfastquay/minibpm/MiniBpm.java b/com/breakfastquay/minibpm/MiniBpm.java --- a/com/breakfastquay/minibpm/MiniBpm.java +++ b/com/breakfastquay/minibpm/MiniBpm.java @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/src/MiniBpm.cpp b/src/MiniBpm.cpp --- a/src/MiniBpm.cpp +++ b/src/MiniBpm.cpp @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -63,6 +63,7 @@ #include #include +#include #include #include #include @@ -225,6 +226,7 @@ // 0 1 2 4 4 4 8 8 8 8 8 8 16 16 16 16 16 16 16 ... base = (lag * multiple) - (multiple / 4); count = (multiple / 4) + (multiple / 2); + if (base < 0) base = 0; } } @@ -269,40 +271,48 @@ int multiple = 1; double interpolated = lag; + double overallPeak = 0.0; - double total = 0.0; - int n = 0; + while (multiple <= 16) { - while (1) { - int base, count; getContributingRange(lag, multiple, base, count); - if (base + count > acfLength) break; double peak = 0.0; - int peakidx = 0; - for (int j = base; j < base + count; ++j) { + int pix = 0; + for (int j = base; j < acfLength; ++j) { if (acf[j] > peak) { peak = acf[j]; - peakidx = j; + pix = j; + } else if (j >= base + count) { + break; } } - if (peak > 0.0) { - double scaled = double(peakidx) / multiple; - total += scaled; - ++n; + if (peak > overallPeak * 0.9) { + double loc = pix; + if (pix > 0 && pix + 1 < acfLength) { + double a = acf[pix-1]; + double b = acf[pix]; + double c = acf[pix+1]; + if (b > a && b > c) { + double d = a - 2*b + c; + if (d != 0.0) { + loc += ((a - c) / d) / 2.0; + } + } + } + interpolated = loc / multiple; + if (peak > overallPeak) { + overallPeak = peak; + } } if (multiple == 1) multiple = m_beatsPerBar; else multiple = multiple * 2; } - if (n > 0) { - interpolated = total / n; - } - double bpm = Autocorrelation::lagToBpm(interpolated, m_hopsPerSec); return bpm; } @@ -381,7 +391,7 @@ m_input = new double[m_blockSize]; m_partial = new double[m_stepSize]; - int frameSize = std::max(lfsize, hfsize); + int frameSize = std::max(lfsize, hfsize); m_frame = new double[frameSize]; zero(m_input, m_blockSize); @@ -563,12 +573,18 @@ return 0.0; } + std::set grossCandidatesSeen; + std::multimap::const_iterator ci(candidateMap.end()); while (ci != candidateMap.begin()) { --ci; int lag = ci->second + minlag; double bpm = filter.refine(lag, acf, acfLength); - m_candidates.push_back(bpm); + int gross = int(round(bpm * 2.0)); // treat within 0.5 as duplicate + if (grossCandidatesSeen.find(gross) == grossCandidatesSeen.end()) { + m_candidates.push_back(bpm); + grossCandidatesSeen.insert(gross); + } } delete[] cf; diff --git a/src/MiniBpm.h b/src/MiniBpm.h --- a/src/MiniBpm.h +++ b/src/MiniBpm.h @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/src/jni/MiniBpmJNI.cpp b/src/jni/MiniBpmJNI.cpp --- a/src/jni/MiniBpmJNI.cpp +++ b/src/jni/MiniBpmJNI.cpp @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/tests/TestMiniBpm.cpp b/tests/TestMiniBpm.cpp --- a/tests/TestMiniBpm.cpp +++ b/tests/TestMiniBpm.cpp @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -304,8 +304,7 @@ { double acf[] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; double bpm = REFINER(1).refine(1, acf, 8); - BOOST_CHECK_LT(bpm, 60); - BOOST_CHECK_GT(bpm, 50); + BOOST_CHECK_EQUAL(bpm, 48); } BOOST_AUTO_TEST_SUITE_END() diff --git a/vamp/Makefile b/vamp/Makefile --- a/vamp/Makefile +++ b/vamp/Makefile @@ -7,7 +7,7 @@ MINIBPM_SOURCES := ../src/MiniBpm.cpp MINIBPM_HEADERS := ../src/MiniBpm.h -CXXFLAGS := -I../src -fPIC +CXXFLAGS := -std=c++98 -I../src -fPIC VAMP_LDFLAGS := $(LDFLAGS) $(PLUGIN_LDFLAGS) -lvamp-sdk diff --git a/vamp/MiniBpmVamp.cpp b/vamp/MiniBpmVamp.cpp --- a/vamp/MiniBpmVamp.cpp +++ b/vamp/MiniBpmVamp.cpp @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -71,7 +71,7 @@ { // Increment this each time you release a version that behaves // differently from the previous one - return 1; + return 2; } string @@ -189,6 +189,18 @@ d.hasDuration = true; outputs.push_back(d); + d = OutputDescriptor(); + d.identifier = "candidates"; + d.name = "Tempo Candidates"; + d.description = "A multi-valued feature containing all tempo candidates starting with the most likely"; + d.hasFixedBinCount = false; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = m_inputSampleRate; + d.hasDuration = true; + outputs.push_back(d); + return outputs; } @@ -210,12 +222,14 @@ { m_mbpm->reset(); m_mbpm->setBeatsPerBar(m_beatsPerBar); + m_lastTimestamp = Vamp::RealTime::zeroTime; } MiniBpmVamp::FeatureSet MiniBpmVamp::process(const float *const *inputBuffers, Vamp::RealTime timestamp) { m_mbpm->process(inputBuffers[0], m_blockSize); + m_lastTimestamp = timestamp; return FeatureSet(); } @@ -230,10 +244,24 @@ f.hasTimestamp = true; f.timestamp = Vamp::RealTime::zeroTime; f.hasDuration = true; - f.duration = Vamp::RealTime::fromSeconds(1.0); + f.duration = m_lastTimestamp + + Vamp::RealTime::frame2RealTime(m_blockSize, m_inputSampleRate); f.values.push_back(bpm); fs[0].push_back(f); + std::vector candidates = m_mbpm->getTempoCandidates(); + + f = Feature(); + f.hasTimestamp = true; + f.timestamp = Vamp::RealTime::zeroTime; + f.hasDuration = true; + f.duration = m_lastTimestamp + + Vamp::RealTime::frame2RealTime(m_blockSize, m_inputSampleRate); + for (size_t i = 0; i < candidates.size(); ++i) { + f.values.push_back(candidates[i]); + } + fs[1].push_back(f); + return fs; } diff --git a/vamp/MiniBpmVamp.h b/vamp/MiniBpmVamp.h --- a/vamp/MiniBpmVamp.h +++ b/vamp/MiniBpmVamp.h @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -72,6 +72,7 @@ protected: breakfastquay::MiniBPM *m_mbpm; + Vamp::RealTime m_lastTimestamp; size_t m_blockSize; int m_beatsPerBar; }; diff --git a/vamp/libmain.cpp b/vamp/libmain.cpp --- a/vamp/libmain.cpp +++ b/vamp/libmain.cpp @@ -3,7 +3,7 @@ /* MiniBPM A fixed-tempo BPM estimator for music audio - Copyright 2012-2021 Particular Programs Ltd. + Copyright 2012-2025 Particular Programs Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as