summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-04-09 12:04:00 +0200
committerJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-04-09 12:04:00 +0200
commit91cdfce6cc193ee20f704db4e83cb08e10e741b1 (patch)
treed426fe5ab333c036913aafb0296a330130d9b261
parent48927dbd9586f7923c987fe90f7f20e6b1887291 (diff)
parentd4108005a7c79abc40061682c1428a27d24fd34a (diff)
Merge branch '2.3' of github.com:mixxxdj/mixxx
-rw-r--r--CMakeLists.txt41
-rw-r--r--src/engine/controls/bpmcontrol.cpp59
-rw-r--r--src/engine/controls/bpmcontrol.h1
-rw-r--r--src/test/enginesynctest.cpp25
4 files changed, 74 insertions, 52 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 809dff8ad6..3a0502b5db 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,22 +1,4 @@
-cmake_minimum_required(VERSION 3.16.0)
-project(mixxx VERSION 2.3.0)
-set(CMAKE_PROJECT_HOMEPAGE_URL "https://www.mixxx.org")
-set(CMAKE_PROJECT_DESCRIPTION "Mixxx is Free DJ software that gives you everything you need to perform live mixes.")
-
-# Used for force control of color output
-set(BUILD_COLORS "auto" CACHE STRING "Try to use colors auto/always/no")
-# Option to disable symlinks
-set(USE_SYMLINKS ON CACHE BOOL "Use symlinks in build directory when possible")
-
-# Support new IN_LIST if() operator
-if(POLICY CMP0057)
- cmake_policy(SET CMP0057 NEW)
-endif()
-
-# Let AUTOMOC and AUTOUIC process GENERATED files
-if(POLICY CMP0071)
- cmake_policy(SET CMP0071 NEW)
-endif()
+cmake_minimum_required(VERSION 3.16)
# CMAKE_CXX_COMPILER_ID: Distinguish between "AppleClang" and "Clang"
if(POLICY CMP0025)
@@ -28,10 +10,31 @@ if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
+# Support new IN_LIST if() operator
+if(POLICY CMP0057)
+ cmake_policy(SET CMP0057 NEW)
+endif()
+
+# Enforce interprocedural optimization
if(POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
+# Let AUTOMOC and AUTOUIC process GENERATED files
+if(POLICY CMP0071)
+ cmake_policy(SET CMP0071 NEW)
+endif()
+
+project(mixxx VERSION 2.3.0)
+
+set(CMAKE_PROJECT_HOMEPAGE_URL "https://www.mixxx.org")
+set(CMAKE_PROJECT_DESCRIPTION "Mixxx is Free DJ software that gives you everything you need to perform live mixes.")
+
+# Used for force control of color output
+set(BUILD_COLORS "auto" CACHE STRING "Try to use colors auto/always/no")
+# Option to disable symlinks
+set(USE_SYMLINKS ON CACHE BOOL "Use symlinks in build directory when possible")
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
include(CMakeDependentOption)
include(CheckSymbolExists)
diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp
index f35990167b..5bc5ebefcd 100644
--- a/src/engine/controls/bpmcontrol.cpp
+++ b/src/engine/controls/bpmcontrol.cpp
@@ -39,6 +39,11 @@ constexpr int kBpmTapFilterLength = 5;
// the actual number of beats is this x2.
constexpr int kLocalBpmSpan = 4;
constexpr SINT kSamplesPerFrame = 2;
+
+// If we are 1 / 8.0 beat fraction near the previous beat we match that instead
+// of the next beat.
+constexpr double kPastBeatMatchThreshold = 1 / 8.0;
+
} // namespace
BpmControl::BpmControl(const QString& group,
@@ -46,8 +51,7 @@ BpmControl::BpmControl(const QString& group,
: EngineControl(group, pConfig),
m_tapFilter(this, kBpmTapFilterLength, kBpmTapMaxInterval),
m_dSyncInstantaneousBpm(0.0),
- m_dLastSyncAdjustment(1.0),
- m_dUserTweakingSync(false) {
+ m_dLastSyncAdjustment(1.0) {
m_dSyncTargetBeatDistance.setValue(0.0);
m_dUserOffset.setValue(0.0);
@@ -407,7 +411,6 @@ double BpmControl::calcSyncedRate(double userTweak) {
if (kLogger.traceEnabled()) {
kLogger.trace() << getGroup() << "BpmControl::calcSyncedRate, tweak " << userTweak;
}
- m_dUserTweakingSync = userTweak != 0.0;
double rate = 1.0;
// Don't know what to do if there's no bpm.
if (m_pLocalBpm->toBool()) {
@@ -444,7 +447,7 @@ double BpmControl::calcSyncedRate(double userTweak) {
}
// Now we have all we need to calculate the sync adjustment if any.
- double adjustment = calcSyncAdjustment(m_dUserTweakingSync);
+ double adjustment = calcSyncAdjustment(userTweak != 0.0);
return (rate + userTweak) * adjustment;
}
@@ -859,7 +862,20 @@ double BpmControl::getBeatMatchPosition(
return dThisPosition;
}
- double dOtherPosition = pOtherEngineBuffer->getExactPlayPos();
+ const double dOtherPosition = pOtherEngineBuffer->getExactPlayPos();
+ const double dThisSampleRate = m_pBeats->getSampleRate();
+ const double dThisRateRatio = m_pRateRatio->get();
+
+ // Seek our next beat to the other next beat near our beat.
+ // This is the only thing we can do if the track has different BPM,
+ // playing the next beat together.
+
+ // First calculate the position in the other track where this next beat will be.
+ const double thisSecs2ToNextBeat = (dThisNextBeat - dThisPosition) /
+ dThisSampleRate / dThisRateRatio;
+ const double dOtherPositionOfThisNextBeat =
+ thisSecs2ToNextBeat * otherBeats->getSampleRate() * pOtherEngineBuffer->getRateRatio() +
+ dOtherPosition;
double dOtherPrevBeat = -1;
double dOtherNextBeat = -1;
@@ -867,7 +883,7 @@ double BpmControl::getBeatMatchPosition(
double dOtherBeatFraction = -1;
if (!BpmControl::getBeatContext(
otherBeats,
- dOtherPosition,
+ dOtherPositionOfThisNextBeat,
&dOtherPrevBeat,
&dOtherNextBeat,
&dOtherBeatLength,
@@ -880,29 +896,24 @@ double BpmControl::getBeatMatchPosition(
return dThisPosition;
}
- double dThisSampleRate = m_pBeats->getSampleRate();
- double dThisRateRatio = m_pRateRatio->get();
-
- // Seek our next beat to the other next beat
- // This is the only thing we can do if the track has different BPM,
- // playing the next beat together.
- double thisDivSec = (dThisNextBeat - dThisPosition) /
- dThisSampleRate / dThisRateRatio;
-
- if (dOtherBeatFraction < 1.0 / 8) {
- // the user has probably pressed play too late, sync the previous beat
- dOtherBeatFraction += 1.0;
+ // We can either match the past beat with dOtherBeatFraction 1.0
+ // or the next beat with dOtherBeatFraction 0.0
+ // We prefer the next because this is what will be played,
+ // unless we are close to the previous.
+ // This happens if the user presses play too late.
+ if (dOtherBeatFraction > 1.0 - kPastBeatMatchThreshold) {
+ // match the past beat
+ dOtherBeatFraction -= 1.0;
}
- dOtherBeatFraction += m_dUserOffset.getValue();
- double otherDivSec = (1 - dOtherBeatFraction) *
+ double otherDivSec2 = dOtherBeatFraction *
dOtherBeatLength / otherBeats->getSampleRate() / pOtherEngineBuffer->getRateRatio();
-
- // This matches the next beat in of both tracks.
- double seekMatch = (thisDivSec - otherDivSec) *
- dThisSampleRate * dThisRateRatio;
+ // Transform for this track
+ double seekMatch = otherDivSec2 * dThisSampleRate * dThisRateRatio;
if (dThisBeatLength > 0) {
+ // restore phase adjustment
+ seekMatch += (dThisBeatLength * m_dUserOffset.getValue());
if (dThisBeatLength / 2 < seekMatch) {
// seek to previous beat, because of shorter distance
seekMatch -= dThisBeatLength;
diff --git a/src/engine/controls/bpmcontrol.h b/src/engine/controls/bpmcontrol.h
index 156fdca700..62b2fe8367 100644
--- a/src/engine/controls/bpmcontrol.h
+++ b/src/engine/controls/bpmcontrol.h
@@ -161,7 +161,6 @@ class BpmControl : public EngineControl {
// used in the engine thread only
double m_dSyncInstantaneousBpm;
double m_dLastSyncAdjustment;
- bool m_dUserTweakingSync;
// m_pBeats is written from an engine worker thread
mixxx::BeatsPointer m_pBeats;
diff --git a/src/test/enginesynctest.cpp b/src/test/enginesynctest.cpp
index ed923fbd32..ab6cccedf4 100644
--- a/src/test/enginesynctest.cpp
+++ b/src/test/enginesynctest.cpp
@@ -2250,9 +2250,10 @@ TEST_F(EngineSyncTest, QuantizeImpliesSyncPhase) {
EXPECT_DOUBLE_EQ(100, ControlObject::get(ConfigKey(m_sGroup2, "bpm")));
// we align here to the past beat, because beat_distance < 1.0/8
- EXPECT_DOUBLE_EQ(
+ EXPECT_NEAR(
ControlObject::get(ConfigKey(m_sGroup1, "beat_distance")) / 130 * 100,
- ControlObject::get(ConfigKey(m_sGroup2, "beat_distance")));
+ ControlObject::get(ConfigKey(m_sGroup2, "beat_distance")),
+ 1e-15);
}
TEST_F(EngineSyncTest, SeekStayInPhase) {
@@ -2271,7 +2272,8 @@ TEST_F(EngineSyncTest, SeekStayInPhase) {
ProcessBuffer();
// We expect to be two buffers ahead in a beat near 0.2
- EXPECT_DOUBLE_EQ(0.050309901738473183, ControlObject::get(ConfigKey(m_sGroup1, "beat_distance")));
+ EXPECT_DOUBLE_EQ(0.050309901738473162,
+ ControlObject::get(ConfigKey(m_sGroup1, "beat_distance")));
EXPECT_DOUBLE_EQ(0.18925937554508981, ControlObject::get(ConfigKey(m_sGroup1, "playposition")));
// The same again with a stopped track loaded in Channel 2
@@ -2294,7 +2296,7 @@ TEST_F(EngineSyncTest, SeekStayInPhase) {
ProcessBuffer();
// We expect to be two buffers ahead in a beat near 0.2
- EXPECT_DOUBLE_EQ(0.050309901738473183,
+ EXPECT_DOUBLE_EQ(0.050309901738473162,
ControlObject::get(ConfigKey(m_sGroup1, "beat_distance")));
EXPECT_DOUBLE_EQ(0.18925937554508981, ControlObject::get(ConfigKey(m_sGroup1, "playposition")));
}
@@ -2360,9 +2362,12 @@ TEST_F(EngineSyncTest, QuantizeHotCueActivate) {
pHotCue2Activate->set(1.0);
ProcessBuffer();
+ // Beat_distance is the distance to the previous beat wich has already passed.
+ // We compare here the distance to the next beat (1 - beat_distance) and
+ // scale it by the different tempos.
EXPECT_NEAR(
- ControlObject::get(ConfigKey(m_sGroup1, "beat_distance")) / 130 * 100,
- ControlObject::get(ConfigKey(m_sGroup2, "beat_distance")),
+ (1 - ControlObject::get(ConfigKey(m_sGroup1, "beat_distance"))) / 130 * 100,
+ (1 - ControlObject::get(ConfigKey(m_sGroup2, "beat_distance"))),
1e-15);
pHotCue2Activate->set(0.0);
@@ -2477,8 +2482,12 @@ TEST_F(EngineSyncTest, BeatMapQantizePlay) {
ProcessBuffer();
- EXPECT_DOUBLE_EQ(m_pChannel1->getEngineBuffer()->m_pSyncControl->getBeatDistance(),
- m_pChannel2->getEngineBuffer()->m_pSyncControl->getBeatDistance());
+ // Beat Distance shall be still 0, because we are before the first beat.
+ // This was fixed in https://bugs.launchpad.net/mixxx/+bug/1920084
+ EXPECT_DOUBLE_EQ(m_pChannel2->getEngineBuffer()->m_pSyncControl->getBeatDistance(), 0);
+ EXPECT_DOUBLE_EQ(
+ ControlObject::get(ConfigKey(m_sGroup1, "playposition")),
+ ControlObject::get(ConfigKey(m_sGroup2, "playposition")));
}
TEST_F(EngineSyncTest, BpmAdjustFactor) {