diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp index 9374bf49507..05143a483f6 100644 --- a/src/engine/controls/bpmcontrol.cpp +++ b/src/engine/controls/bpmcontrol.cpp @@ -539,7 +539,7 @@ bool BpmControl::getBeatContext(const mixxx::BeatsPointer& pBeats, double dPrevBeat; double dNextBeat; - if (!pBeats->findPrevNextBeats(dPosition, &dPrevBeat, &dNextBeat)) { + if (!pBeats->findPrevNextBeats(dPosition, &dPrevBeat, &dNextBeat, false)) { return false; } diff --git a/src/engine/controls/clockcontrol.cpp b/src/engine/controls/clockcontrol.cpp index ed1d27e7a28..a7dd22c0f74 100644 --- a/src/engine/controls/clockcontrol.cpp +++ b/src/engine/controls/clockcontrol.cpp @@ -69,8 +69,10 @@ void ClockControl::updateIndicators(const double dRate, (currentSample <= m_PrevBeatSamples)) { //qDebug() << "### findPrevNextBeats ### " << " currentSample: " << currentSample << " m_lastEvaluatedSample: " << m_lastEvaluatedSample << " m_PrevBeatSamples: " << m_PrevBeatSamples << " m_NextBeatSamples: " << m_NextBeatSamples; - pBeats->findPrevNextBeats( - currentSample, &m_PrevBeatSamples, &m_NextBeatSamples); + pBeats->findPrevNextBeats(currentSample, + &m_PrevBeatSamples, + &m_NextBeatSamples, + true); // Precise compare without tolerance needed m_blinkIntervalSamples = (m_NextBeatSamples - m_PrevBeatSamples) * kBlinkInterval; } diff --git a/src/engine/controls/loopingcontrol.cpp b/src/engine/controls/loopingcontrol.cpp index 44653ca86a2..37482602560 100644 --- a/src/engine/controls/loopingcontrol.cpp +++ b/src/engine/controls/loopingcontrol.cpp @@ -1194,7 +1194,7 @@ void LoopingControl::slotBeatLoop(double beats, bool keepStartPoint, bool enable // The closest beat might be ahead of play position and will cause a catching loop. double prevBeat; double nextBeat; - pBeats->findPrevNextBeats(currentSample, &prevBeat, &nextBeat); + pBeats->findPrevNextBeats(currentSample, &prevBeat, &nextBeat, false); if (m_pQuantizeEnabled->toBool() && prevBeat != -1) { double beatLength = nextBeat - prevBeat; diff --git a/src/engine/controls/quantizecontrol.cpp b/src/engine/controls/quantizecontrol.cpp index c059bca51c1..6edbe1d7724 100644 --- a/src/engine/controls/quantizecontrol.cpp +++ b/src/engine/controls/quantizecontrol.cpp @@ -80,7 +80,7 @@ void QuantizeControl::lookupBeatPositions(double dCurrentSample) { mixxx::BeatsPointer pBeats = m_pBeats; if (pBeats) { double prevBeat, nextBeat; - pBeats->findPrevNextBeats(dCurrentSample, &prevBeat, &nextBeat); + pBeats->findPrevNextBeats(dCurrentSample, &prevBeat, &nextBeat, false); m_pCOPrevBeat->set(prevBeat); m_pCONextBeat->set(nextBeat); } diff --git a/src/test/beatgridtest.cpp b/src/test/beatgridtest.cpp index 780aeb11b9c..96c908a9f6b 100644 --- a/src/test/beatgridtest.cpp +++ b/src/test/beatgridtest.cpp @@ -78,7 +78,7 @@ TEST(BeatGridTest, TestNthBeatWhenOnBeat) { // Also test prev/next beat calculation. double prevBeat, nextBeat; - pGrid->findPrevNextBeats(position, &prevBeat, &nextBeat); + pGrid->findPrevNextBeats(position, &prevBeat, &nextBeat, false); EXPECT_NEAR(position, prevBeat, kMaxBeatError); EXPECT_NEAR(position + beatLength, nextBeat, kMaxBeatError); @@ -115,7 +115,7 @@ TEST(BeatGridTest, TestNthBeatWhenOnBeat_BeforeEpsilon) { // Also test prev/next beat calculation. double prevBeat, nextBeat; - pGrid->findPrevNextBeats(position, &prevBeat, &nextBeat); + pGrid->findPrevNextBeats(position, &prevBeat, &nextBeat, false); EXPECT_NEAR(kClosestBeat, prevBeat, kMaxBeatError); EXPECT_NEAR(kClosestBeat + beatLength, nextBeat, kMaxBeatError); @@ -152,7 +152,7 @@ TEST(BeatGridTest, TestNthBeatWhenOnBeat_AfterEpsilon) { // Also test prev/next beat calculation. double prevBeat, nextBeat; - pGrid->findPrevNextBeats(position, &prevBeat, &nextBeat); + pGrid->findPrevNextBeats(position, &prevBeat, &nextBeat, false); EXPECT_NEAR(kClosestBeat, prevBeat, kMaxBeatError); EXPECT_NEAR(kClosestBeat + beatLength, nextBeat, kMaxBeatError); @@ -190,7 +190,7 @@ TEST(BeatGridTest, TestNthBeatWhenNotOnBeat) { // Also test prev/next beat calculation double foundPrevBeat, foundNextBeat; - pGrid->findPrevNextBeats(position, &foundPrevBeat, &foundNextBeat); + pGrid->findPrevNextBeats(position, &foundPrevBeat, &foundNextBeat, false); EXPECT_NEAR(previousBeat, foundPrevBeat, kMaxBeatError); EXPECT_NEAR(nextBeat, foundNextBeat, kMaxBeatError); } diff --git a/src/test/beatmaptest.cpp b/src/test/beatmaptest.cpp index 5cbafa71d35..cf3780e0e6f 100644 --- a/src/test/beatmaptest.cpp +++ b/src/test/beatmaptest.cpp @@ -100,11 +100,11 @@ TEST_F(BeatMapTest, TestNthBeat) { EXPECT_EQ(-1, pMap->findNthBeat(firstBeat, -2)); double prevBeat, nextBeat; - pMap->findPrevNextBeats(lastBeat, &prevBeat, &nextBeat); + pMap->findPrevNextBeats(lastBeat, &prevBeat, &nextBeat, false); EXPECT_EQ(lastBeat, prevBeat); EXPECT_EQ(-1, nextBeat); - pMap->findPrevNextBeats(firstBeat, &prevBeat, &nextBeat); + pMap->findPrevNextBeats(firstBeat, &prevBeat, &nextBeat, false); EXPECT_EQ(firstBeat, prevBeat); EXPECT_EQ(firstBeat + beatLengthSamples, nextBeat); } @@ -137,7 +137,7 @@ TEST_F(BeatMapTest, TestNthBeatWhenOnBeat) { // Also test prev/next beat calculation. double prevBeat, nextBeat; - pMap->findPrevNextBeats(position, &prevBeat, &nextBeat); + pMap->findPrevNextBeats(position, &prevBeat, &nextBeat, false); EXPECT_EQ(position, prevBeat); EXPECT_EQ(position + beatLengthSamples, nextBeat); @@ -175,7 +175,7 @@ TEST_F(BeatMapTest, TestNthBeatWhenOnBeat_BeforeEpsilon) { // Also test prev/next beat calculation double prevBeat, nextBeat; - pMap->findPrevNextBeats(position, &prevBeat, &nextBeat); + pMap->findPrevNextBeats(position, &prevBeat, &nextBeat, false); EXPECT_EQ(kClosestBeat, prevBeat); EXPECT_EQ(kClosestBeat + beatLengthSamples, nextBeat); @@ -216,7 +216,7 @@ TEST_F(BeatMapTest, TestNthBeatWhenOnBeat_AfterEpsilon) { // Also test prev/next beat calculation. double prevBeat, nextBeat; - pMap->findPrevNextBeats(position, &prevBeat, &nextBeat); + pMap->findPrevNextBeats(position, &prevBeat, &nextBeat, false); EXPECT_EQ(kClosestBeat, prevBeat); EXPECT_EQ(kClosestBeat + beatLengthSamples, nextBeat); @@ -256,7 +256,7 @@ TEST_F(BeatMapTest, TestNthBeatWhenNotOnBeat) { // Also test prev/next beat calculation double foundPrevBeat, foundNextBeat; - pMap->findPrevNextBeats(position, &foundPrevBeat, &foundNextBeat); + pMap->findPrevNextBeats(position, &foundPrevBeat, &foundNextBeat, false); EXPECT_EQ(previousBeat, foundPrevBeat); EXPECT_EQ(nextBeat, foundNextBeat); } diff --git a/src/track/beatgrid.cpp b/src/track/beatgrid.cpp index 36bfad9863d..2268d13000e 100644 --- a/src/track/beatgrid.cpp +++ b/src/track/beatgrid.cpp @@ -158,7 +158,7 @@ double BeatGrid::findClosestBeat(double dSamples) const { } double prevBeat; double nextBeat; - findPrevNextBeats(dSamples, &prevBeat, &nextBeat); + findPrevNextBeats(dSamples, &prevBeat, &nextBeat, false); if (prevBeat == -1) { // If both values are -1, we correctly return -1. return nextBeat; @@ -214,8 +214,10 @@ double BeatGrid::findNthBeat(double dSamples, int n) const { } bool BeatGrid::findPrevNextBeats(double dSamples, - double* dpPrevBeatSamples, - double* dpNextBeatSamples) const { + + double* dpPrevBeatSamples, + double* dpNextBeatSamples, + bool NoTolerance) const { double dFirstBeatSample; double dBeatLength; { @@ -232,11 +234,15 @@ bool BeatGrid::findPrevNextBeats(double dSamples, double beatFraction = (dSamples - dFirstBeatSample) / dBeatLength; double prevBeat = floor(beatFraction); double nextBeat = ceil(beatFraction); + double kEpsilon; - // If the position is within 1/1000,000,000th of the next or previous beat, treat it - // as if it is that beat. This value ensures safe float comparisation and that the - // accuracy is always better one sample. - const double kEpsilon = 1e-09; + if (NoTolerance) { + kEpsilon = 0.0f; + } else { + // If the position is within 1/100th of the next or previous beat, treat it + // as if it is that beat. + kEpsilon = .01; + } if (fabs(nextBeat - beatFraction) < kEpsilon) { beatFraction = nextBeat; @@ -252,7 +258,6 @@ bool BeatGrid::findPrevNextBeats(double dSamples, return true; } - std::unique_ptr BeatGrid::findBeats(double startSample, double stopSample) const { QMutexLocker locker(&m_mutex); if (!isValid() || startSample > stopSample) { diff --git a/src/track/beatgrid.h b/src/track/beatgrid.h index bd4747cc799..b1b0612b721 100644 --- a/src/track/beatgrid.h +++ b/src/track/beatgrid.h @@ -52,8 +52,10 @@ class BeatGrid final : public Beats { double findNextBeat(double dSamples) const override; double findPrevBeat(double dSamples) const override; bool findPrevNextBeats(double dSamples, - double* dpPrevBeatSamples, - double* dpNextBeatSamples) const override; + + double* dpPrevBeatSamples, + double* dpNextBeatSamples, + bool NoTolerance) const override; double findClosestBeat(double dSamples) const override; double findNthBeat(double dSamples, int n) const override; std::unique_ptr findBeats(double startSample, double stopSample) const override; diff --git a/src/track/beatmap.cpp b/src/track/beatmap.cpp index 9cb0e2b3fd6..cbc808f9126 100644 --- a/src/track/beatmap.cpp +++ b/src/track/beatmap.cpp @@ -188,7 +188,7 @@ double BeatMap::findClosestBeat(double dSamples) const { } double prevBeat; double nextBeat; - findPrevNextBeats(dSamples, &prevBeat, &nextBeat); + findPrevNextBeats(dSamples, &prevBeat, &nextBeat, false); if (prevBeat == -1) { // If both values are -1, we correctly return -1. return nextBeat; @@ -286,8 +286,9 @@ double BeatMap::findNthBeat(double dSamples, int n) const { } bool BeatMap::findPrevNextBeats(double dSamples, - double* dpPrevBeatSamples, - double* dpNextBeatSamples) const { + double* dpPrevBeatSamples, + double* dpNextBeatSamples, + bool NoTolerance) const { QMutexLocker locker(&m_mutex); if (!isValid()) { @@ -304,9 +305,15 @@ bool BeatMap::findPrevNextBeats(double dSamples, BeatList::const_iterator it = std::lower_bound(m_beats.constBegin(), m_beats.constEnd(), beat, BeatLessThan); - // If the position is within 1/10th of a second of the next or previous - // beat, pretend we are on that beat. - const double kFrameEpsilon = 0.1 * m_iSampleRate; + double kFrameEpsilon; + + if (NoTolerance) { + kFrameEpsilon = 0.0f; + } else { + // If the position is within 1/10th of a second of the next or previous + // beat, pretend we are on that beat. + kFrameEpsilon = 0.1 * m_iSampleRate; + } // Back-up by one. if (it != m_beats.begin()) { diff --git a/src/track/beatmap.h b/src/track/beatmap.h index d3f05c25911..cd231d74963 100644 --- a/src/track/beatmap.h +++ b/src/track/beatmap.h @@ -60,8 +60,9 @@ class BeatMap final : public Beats { double findNextBeat(double dSamples) const override; double findPrevBeat(double dSamples) const override; bool findPrevNextBeats(double dSamples, - double* dpPrevBeatSamples, - double* dpNextBeatSamples) const override; + double* dpPrevBeatSamples, + double* dpNextBeatSamples, + bool NoTolerance) const override; double findClosestBeat(double dSamples) const override; double findNthBeat(double dSamples, int n) const override; std::unique_ptr findBeats(double startSample, double stopSample) const override; diff --git a/src/track/beats.cpp b/src/track/beats.cpp index 58d90a96599..992c295d616 100644 --- a/src/track/beats.cpp +++ b/src/track/beats.cpp @@ -21,7 +21,7 @@ double Beats::findNBeatsFromSample(double fromSample, double beats) const { double prevBeat; double nextBeat; - if (!findPrevNextBeats(fromSample, &prevBeat, &nextBeat)) { + if (!findPrevNextBeats(fromSample, &prevBeat, &nextBeat, false)) { return fromSample; } double fromFractionBeats = (fromSample - prevBeat) / (nextBeat - prevBeat); diff --git a/src/track/beats.h b/src/track/beats.h index c3ae7e568e5..19814f58eeb 100644 --- a/src/track/beats.h +++ b/src/track/beats.h @@ -93,8 +93,9 @@ class Beats : public QObject { // even. Returns false if *at least one* sample is -1. (Can return false // with one beat successfully filled) virtual bool findPrevNextBeats(double dSamples, - double* dpPrevBeatSamples, - double* dpNextBeatSamples) const = 0; + double* dpPrevBeatSamples, + double* dpNextBeatSamples, + bool NoTolerance) const = 0; // Starting from sample dSamples, return the sample of the closest beat in // the track, or -1 if none exists. Non- -1 values are guaranteed to be