From 42984dd070ac81dbcb6e7cd9f132c5eb9f581a65 Mon Sep 17 00:00:00 2001 From: Owen Williams Date: Mon, 15 Mar 2021 15:51:51 -0400 Subject: [PATCH 1/2] Sync Lock: rename functions to make them clearer --- src/engine/controls/bpmcontrol.cpp | 2 +- src/engine/controls/bpmcontrol.h | 2 +- src/engine/sync/clock.h | 4 +- src/engine/sync/enginesync.cpp | 62 +++++++++++++++++------------- src/engine/sync/enginesync.h | 11 ++++-- src/engine/sync/internalclock.cpp | 18 ++++----- src/engine/sync/internalclock.h | 8 ++-- src/engine/sync/syncable.h | 16 ++++---- src/engine/sync/synccontrol.cpp | 24 ++++++------ src/engine/sync/synccontrol.h | 11 +++--- 10 files changed, 87 insertions(+), 71 deletions(-) diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp index fac2e68e87d..d72f6ff7921 100644 --- a/src/engine/controls/bpmcontrol.cpp +++ b/src/engine/controls/bpmcontrol.cpp @@ -1104,7 +1104,7 @@ void BpmControl::setTargetBeatDistance(double beatDistance) { m_dSyncTargetBeatDistance.setValue(beatDistance); } -void BpmControl::setInstantaneousBpm(double instantaneousBpm) { +void BpmControl::updateInstantaneousBpm(double instantaneousBpm) { m_dSyncInstantaneousBpm = instantaneousBpm; } diff --git a/src/engine/controls/bpmcontrol.h b/src/engine/controls/bpmcontrol.h index f5cca122262..7e5e3446b26 100644 --- a/src/engine/controls/bpmcontrol.h +++ b/src/engine/controls/bpmcontrol.h @@ -47,7 +47,7 @@ class BpmControl : public EngineControl { } void setTargetBeatDistance(double beatDistance); - void setInstantaneousBpm(double instantaneousBpm); + void updateInstantaneousBpm(double instantaneousBpm); void resetSyncAdjustment(); double updateLocalBpm(); /// updateBeatDistance is adjusted to include the user offset so diff --git a/src/engine/sync/clock.h b/src/engine/sync/clock.h index 75d987fc2ae..9814bf1d441 100644 --- a/src/engine/sync/clock.h +++ b/src/engine/sync/clock.h @@ -5,8 +5,8 @@ class Clock { virtual ~Clock() = default; virtual double getBeatDistance() const = 0; - virtual void setMasterBeatDistance(double beatDistance) = 0; + virtual void updateMasterBeatDistance(double beatDistance) = 0; virtual double getBpm() const = 0; - virtual void setMasterBpm(double bpm) = 0; + virtual void updateMasterBpm(double bpm) = 0; }; diff --git a/src/engine/sync/enginesync.cpp b/src/engine/sync/enginesync.cpp index 474ff418e99..595be45439c 100644 --- a/src/engine/sync/enginesync.cpp +++ b/src/engine/sync/enginesync.cpp @@ -19,7 +19,7 @@ EngineSync::EngineSync(UserSettingsPointer pConfig) m_pInternalClock(new InternalClock(kInternalClockGroup, this)), m_pMasterSyncable(nullptr) { qRegisterMetaType("SyncMode"); - m_pInternalClock->setMasterBpm(124.0); + m_pInternalClock->updateMasterBpm(124.0); } EngineSync::~EngineSync() { @@ -90,14 +90,19 @@ void EngineSync::requestSyncMode(Syncable* pSyncable, SyncMode mode) { pParamsSyncable = findBpmMatchTarget(pSyncable); if (!pParamsSyncable) { // We weren't able to find anything to match to, so set ourselves as the - // target. That way we'll use our own params when we setMasterParams below. + // target. That way we'll use our own params when we updateMasterBpm below. pParamsSyncable = pSyncable; } } // Now that all of the decks have their assignments, reinit master params if needed. if (pParamsSyncable) { - setMasterParams(pParamsSyncable); - pSyncable->setInstantaneousBpm(pParamsSyncable->getBpm()); + if (kLogger.traceEnabled()) { + kLogger.trace() + << "EngineSync::requestSyncMode setting master params from " + << pParamsSyncable->getGroup(); + } + reinitMasterParams(pParamsSyncable); + pSyncable->updateInstantaneousBpm(pParamsSyncable->getBpm()); if (pParamsSyncable != pSyncable) { pSyncable->requestSync(); } @@ -194,6 +199,9 @@ void EngineSync::deactivateSync(Syncable* pSyncable) { } Syncable* EngineSync::pickMaster(Syncable* enabling_syncable) { + if (kLogger.traceEnabled()) { + kLogger.trace() << "EngineSync::pickMaster"; + } if (m_pMasterSyncable && m_pMasterSyncable->getSyncMode() == SYNC_MASTER_EXPLICIT && m_pMasterSyncable->getBaseBpm() != 0.0) { @@ -354,14 +362,14 @@ void EngineSync::notifyPlayingAudible(Syncable* pSyncable, bool playingAudible) if (newMaster != nullptr && newMaster != m_pMasterSyncable) { activateMaster(newMaster, SYNC_MASTER_SOFT); - setMasterParams(newMaster); + reinitMasterParams(newMaster); } else { Syncable* pOnlyPlayer = getUniquePlayingSyncedDeck(); if (pOnlyPlayer) { // Even if we didn't change master, if there is only one player (us), then we should - // reinit the beat distance. + // update the beat distance. pOnlyPlayer->notifyUniquePlaying(); - setMasterBeatDistance(pOnlyPlayer, pOnlyPlayer->getBeatDistance()); + updateMasterBeatDistance(pOnlyPlayer, pOnlyPlayer->getBeatDistance()); } } @@ -380,7 +388,7 @@ void EngineSync::notifyBaseBpmChanged(Syncable* pSyncable, double bpm) { } if (isSyncMaster(pSyncable)) { - setMasterBpm(pSyncable, bpm); + updateMasterBpm(pSyncable, bpm); } } @@ -389,7 +397,7 @@ void EngineSync::notifyRateChanged(Syncable* pSyncable, double bpm) { kLogger.trace() << "EngineSync::notifyRateChanged" << pSyncable->getGroup() << bpm; } - setMasterBpm(pSyncable, bpm); + updateMasterBpm(pSyncable, bpm); } void EngineSync::requestBpmUpdate(Syncable* pSyncable, double bpm) { @@ -408,10 +416,10 @@ void EngineSync::requestBpmUpdate(Syncable* pSyncable, double bpm) { if (mbaseBpm != 0.0) { // resync to current master - pSyncable->setMasterParams(beatDistance, mbaseBpm, mbpm); + pSyncable->reinitMasterParams(beatDistance, mbaseBpm, mbpm); } else { // There is no other master, adopt this bpm as master - pSyncable->setMasterParams(0.0, 0.0, bpm); + pSyncable->reinitMasterParams(0.0, 0.0, bpm); } } @@ -425,7 +433,7 @@ void EngineSync::notifyInstantaneousBpmChanged(Syncable* pSyncable, double bpm) // Do not update the master rate slider because instantaneous changes are // not user visible. - setMasterInstantaneousBpm(pSyncable, bpm); + updateMasterInstantaneousBpm(pSyncable, bpm); } void EngineSync::notifyBeatDistanceChanged(Syncable* pSyncable, double beatDistance) { @@ -437,7 +445,7 @@ void EngineSync::notifyBeatDistanceChanged(Syncable* pSyncable, double beatDista return; } - setMasterBeatDistance(pSyncable, beatDistance); + updateMasterBeatDistance(pSyncable, beatDistance); } Syncable* EngineSync::pickNonSyncSyncTarget(EngineChannel* pDontPick) const { @@ -564,52 +572,52 @@ double EngineSync::masterBaseBpm() const { return m_pInternalClock->getBaseBpm(); } -void EngineSync::setMasterBpm(Syncable* pSource, double bpm) { - //qDebug() << "EngineSync::setMasterBpm" << pSource << bpm; +void EngineSync::updateMasterBpm(Syncable* pSource, double bpm) { + //qDebug() << "EngineSync::updateMasterBpm" << pSource << bpm; if (pSource != m_pInternalClock) { - m_pInternalClock->setMasterBpm(bpm); + m_pInternalClock->updateMasterBpm(bpm); } foreach (Syncable* pSyncable, m_syncables) { if (pSyncable == pSource || !pSyncable->isSynchronized()) { continue; } - pSyncable->setMasterBpm(bpm); + pSyncable->updateMasterBpm(bpm); } } -void EngineSync::setMasterInstantaneousBpm(Syncable* pSource, double bpm) { +void EngineSync::updateMasterInstantaneousBpm(Syncable* pSource, double bpm) { if (pSource != m_pInternalClock) { - m_pInternalClock->setInstantaneousBpm(bpm); + m_pInternalClock->updateInstantaneousBpm(bpm); } foreach (Syncable* pSyncable, m_syncables) { if (pSyncable == pSource || !pSyncable->isSynchronized()) { continue; } - pSyncable->setInstantaneousBpm(bpm); + pSyncable->updateInstantaneousBpm(bpm); } } -void EngineSync::setMasterBeatDistance(Syncable* pSource, double beatDistance) { +void EngineSync::updateMasterBeatDistance(Syncable* pSource, double beatDistance) { if (kLogger.traceEnabled()) { kLogger.trace() << "EngineSync::setMasterBeatDistance" << (pSource ? pSource->getGroup() : "null") << beatDistance; } if (pSource != m_pInternalClock) { - m_pInternalClock->setMasterBeatDistance(beatDistance); + m_pInternalClock->updateMasterBeatDistance(beatDistance); } foreach (Syncable* pSyncable, m_syncables) { if (pSyncable == pSource || !pSyncable->isSynchronized()) { continue; } - pSyncable->setMasterBeatDistance(beatDistance); + pSyncable->updateMasterBeatDistance(beatDistance); } } -void EngineSync::setMasterParams(Syncable* pSource) { +void EngineSync::reinitMasterParams(Syncable* pSource) { // Important note! Because of the way sync works, the new master is usually not the same // as the Syncable setting the master parameters (here, pSource). Notify the proper Syncable // so it can prepare itself. (This is a hack to undo half/double math so that we initialize @@ -644,17 +652,17 @@ void EngineSync::setMasterParams(Syncable* pSource) { bpm = baseBpm; } if (kLogger.traceEnabled()) { - kLogger.trace() << "BaseSyncableListener::setMasterParams, source is" + kLogger.trace() << "BaseSyncableListener::reinitMasterParams, source is" << pSource->getGroup() << beatDistance << baseBpm << bpm; } if (pSource != m_pInternalClock) { - m_pInternalClock->setMasterParams(beatDistance, baseBpm, bpm); + m_pInternalClock->reinitMasterParams(beatDistance, baseBpm, bpm); } foreach (Syncable* pSyncable, m_syncables) { if (!pSyncable->isSynchronized()) { continue; } - pSyncable->setMasterParams(beatDistance, baseBpm, bpm); + pSyncable->reinitMasterParams(beatDistance, baseBpm, bpm); } } diff --git a/src/engine/sync/enginesync.h b/src/engine/sync/enginesync.h index 5ce7574b520..0e3118010b2 100644 --- a/src/engine/sync/enginesync.h +++ b/src/engine/sync/enginesync.h @@ -103,17 +103,20 @@ class EngineSync : public SyncableListener { double masterBaseBpm() const; /// Set the BPM on every sync-enabled Syncable except pSource. - void setMasterBpm(Syncable* pSource, double bpm); + void updateMasterBpm(Syncable* pSource, double bpm); /// Set the master instantaneous BPM on every sync-enabled Syncable except /// pSource. - void setMasterInstantaneousBpm(Syncable* pSource, double bpm); + void updateMasterInstantaneousBpm(Syncable* pSource, double bpm); /// Set the master beat distance on every sync-enabled Syncable except /// pSource. - void setMasterBeatDistance(Syncable* pSource, double beatDistance); + void updateMasterBeatDistance(Syncable* pSource, double beatDistance); - void setMasterParams(Syncable* pSource); + /// Initialize the master parameters using the provided syncable as the source. + /// This should only be called for "major" updates, like a new track or change in + /// master. Should not be called on every buffer callback. + void reinitMasterParams(Syncable* pSource); /// Iff there is a single playing syncable in sync mode, return it. /// This is used to initialize master params. diff --git a/src/engine/sync/internalclock.cpp b/src/engine/sync/internalclock.cpp index 734523d7e83..4beec9733fb 100644 --- a/src/engine/sync/internalclock.cpp +++ b/src/engine/sync/internalclock.cpp @@ -103,7 +103,7 @@ double InternalClock::getBeatDistance() const { return m_dClockPosition / m_dBeatLength; } -void InternalClock::setMasterBeatDistance(double beatDistance) { +void InternalClock::updateMasterBeatDistance(double beatDistance) { if (kLogger.traceEnabled()) { kLogger.trace() << "InternalClock::setMasterBeatDistance" << beatDistance; } @@ -121,7 +121,7 @@ double InternalClock::getBpm() const { return m_pClockBpm->get(); } -void InternalClock::setMasterBpm(double bpm) { +void InternalClock::updateMasterBpm(double bpm) { if (kLogger.traceEnabled()) { kLogger.trace() << "InternalClock::setBpm" << bpm; } @@ -132,7 +132,7 @@ void InternalClock::setMasterBpm(double bpm) { updateBeatLength(m_iOldSampleRate, bpm); } -void InternalClock::setInstantaneousBpm(double bpm) { +void InternalClock::updateInstantaneousBpm(double bpm) { if (kLogger.traceEnabled()) { kLogger.trace() << "InternalClock::setInstantaneousBpm" << bpm; } @@ -143,16 +143,16 @@ void InternalClock::setInstantaneousBpm(double bpm) { void InternalClock::notifyMasterParamSource() { } -void InternalClock::setMasterParams(double beatDistance, double baseBpm, double bpm) { +void InternalClock::reinitMasterParams(double beatDistance, double baseBpm, double bpm) { if (kLogger.traceEnabled()) { - kLogger.trace() << "InternalClock::setMasterParams" << beatDistance << baseBpm << bpm; + kLogger.trace() << "InternalClock::reinitMasterParams" << beatDistance << baseBpm << bpm; } if (bpm <= 0.0 || baseBpm <= 0.0) { return; } m_dBaseBpm = baseBpm; - setMasterBpm(bpm); - setMasterBeatDistance(beatDistance); + updateMasterBpm(bpm); + updateMasterBeatDistance(beatDistance); } void InternalClock::slotBaseBpmChanged(double baseBpm) { @@ -168,7 +168,7 @@ void InternalClock::slotBeatDistanceChanged(double beatDistance) { if (beatDistance < 0.0 || beatDistance > 1.0) { return; } - setMasterBeatDistance(beatDistance); + updateMasterBeatDistance(beatDistance); } void InternalClock::updateBeatLength(int sampleRate, double bpm) { @@ -204,7 +204,7 @@ void InternalClock::updateBeatLength(int sampleRate, double bpm) { m_iOldSampleRate = sampleRate; // Restore the old beat distance. - setMasterBeatDistance(oldBeatDistance); + updateMasterBeatDistance(oldBeatDistance); } void InternalClock::onCallbackStart(int sampleRate, int bufferSize) { diff --git a/src/engine/sync/internalclock.h b/src/engine/sync/internalclock.h index da0ddde7509..d27e3939fd0 100644 --- a/src/engine/sync/internalclock.h +++ b/src/engine/sync/internalclock.h @@ -48,14 +48,14 @@ class InternalClock : public QObject, public Clock, public Syncable { } double getBeatDistance() const override; - void setMasterBeatDistance(double beatDistance) override; + void updateMasterBeatDistance(double beatDistance) override; double getBaseBpm() const override; - void setMasterBpm(double bpm) override; + void updateMasterBpm(double bpm) override; void notifyMasterParamSource() override; double getBpm() const override; - void setInstantaneousBpm(double bpm) override; - void setMasterParams(double beatDistance, double baseBpm, double bpm) override; + void updateInstantaneousBpm(double bpm) override; + void reinitMasterParams(double beatDistance, double baseBpm, double bpm) override; void onCallbackStart(int sampleRate, int bufferSize); void onCallbackEnd(int sampleRate, int bufferSize); diff --git a/src/engine/sync/syncable.h b/src/engine/sync/syncable.h index 1596b378cbb..f96b0153690 100644 --- a/src/engine/sync/syncable.h +++ b/src/engine/sync/syncable.h @@ -106,26 +106,28 @@ class Syncable { // current Sync Master. // Must never result in a call to // SyncableListener::notifyBeatDistanceChanged or signal loops could occur. - virtual void setMasterBeatDistance(double beatDistance) = 0; + virtual void updateMasterBeatDistance(double beatDistance) = 0; + // Update the current playback speed (not including scratch values) + // of the current master. // Must never result in a call to SyncableListener::notifyBpmChanged or // signal loops could occur. - virtual void setMasterBpm(double bpm) = 0; + virtual void updateMasterBpm(double bpm) = 0; // Tells a Syncable that it's going to be used as a source for master // params. This is a gross hack so that the SyncControl can undo its // half/double adjustment so bpms are initialized correctly. virtual void notifyMasterParamSource() = 0; - // Combines the above three calls into one, since they are often set - // simultaneously. Avoids redundant recalculation that would occur by - // using the three calls separately. - virtual void setMasterParams(double beatDistance, double baseBpm, double bpm) = 0; + // Perform a reset of Master parameters. This function also triggers recalculation + // of half-double multiplier. + virtual void reinitMasterParams(double beatDistance, double baseBpm, double bpm) = 0; + // Update the playback speed of the master, including scratch values. // Must never result in a call to // SyncableListener::notifyInstantaneousBpmChanged or signal loops could // occur. - virtual void setInstantaneousBpm(double bpm) = 0; + virtual void updateInstantaneousBpm(double bpm) = 0; }; /// SyncableListener is an interface class used by EngineSync to receive diff --git a/src/engine/sync/synccontrol.cpp b/src/engine/sync/synccontrol.cpp index 728a51d9b39..604a55db176 100644 --- a/src/engine/sync/synccontrol.cpp +++ b/src/engine/sync/synccontrol.cpp @@ -22,8 +22,10 @@ namespace { const mixxx::Logger kLogger("SyncControl"); } // namespace -SyncControl::SyncControl(const QString& group, UserSettingsPointer pConfig, - EngineChannel* pChannel, SyncableListener* pEngineSync) +SyncControl::SyncControl(const QString& group, + UserSettingsPointer pConfig, + EngineChannel* pChannel, + SyncableListener* pEngineSync) : EngineControl(group, pConfig), m_sGroup(group), m_pChannel(pChannel), @@ -159,7 +161,7 @@ void SyncControl::requestSync() { if (isPlaying() && m_pQuantize->toBool()) { // only sync phase if the deck is playing and if quantize is enabled. // this way the it is up to the user to decide if a seek is desired or not. - // This is helpful if the beatgrid of the track doe not fit at the current + // This is helpful if the beatgrid of the track does not fit at the current // playposition m_pChannel->getEngineBuffer()->requestSyncPhase(); } @@ -177,7 +179,7 @@ double SyncControl::adjustSyncBeatDistance(double beatDistance) const { // Similar to adjusting the target beat distance, when we report our beat // distance we need to adjust it by the master bpm adjustment factor. If // we've been doubling the master bpm, we need to divide it in half. If - // we'be been halving the master bpm, we need to double it. Both operations + // we've been halving the master bpm, we need to double it. Both operations // also need to account for if the longer beat is past its halfway point. // // This is the inverse of the updateTargetBeatDistance function below. @@ -204,7 +206,7 @@ double SyncControl::getBaseBpm() const { return m_pLocalBpm->get() / m_masterBpmAdjustFactor; } -void SyncControl::setMasterBeatDistance(double beatDistance) { +void SyncControl::updateMasterBeatDistance(double beatDistance) { if (kLogger.traceEnabled()) { kLogger.trace() << getGroup() << "SyncControl::setMasterBeatDistance" << beatDistance; @@ -217,7 +219,7 @@ void SyncControl::setMasterBeatDistance(double beatDistance) { updateTargetBeatDistance(); } -void SyncControl::setMasterBpm(double bpm) { +void SyncControl::updateMasterBpm(double bpm) { if (kLogger.traceEnabled()) { kLogger.trace() << getGroup() << "SyncControl::setMasterBpm" << bpm; } @@ -242,15 +244,15 @@ void SyncControl::notifyMasterParamSource() { m_masterBpmAdjustFactor = kBpmUnity; } -void SyncControl::setMasterParams( +void SyncControl::reinitMasterParams( double beatDistance, double baseBpm, double bpm) { if (kLogger.traceEnabled()) { kLogger.trace() << "SyncControl::setMasterParams" << getGroup() << beatDistance << baseBpm << bpm; } m_masterBpmAdjustFactor = determineBpmMultiplier(fileBpm(), baseBpm); - setMasterBpm(bpm); - setMasterBeatDistance(beatDistance); + updateMasterBpm(bpm); + updateMasterBeatDistance(beatDistance); } double SyncControl::determineBpmMultiplier(double myBpm, double targetBpm) const { @@ -309,9 +311,9 @@ double SyncControl::getBpm() const { return m_pBpm->get() / m_masterBpmAdjustFactor; } -void SyncControl::setInstantaneousBpm(double bpm) { +void SyncControl::updateInstantaneousBpm(double bpm) { // Adjust the incoming bpm by the multiplier. - m_pBpmControl->setInstantaneousBpm(bpm * m_masterBpmAdjustFactor); + m_pBpmControl->updateInstantaneousBpm(bpm * m_masterBpmAdjustFactor); } void SyncControl::reportTrackPosition(double fractionalPlaypos) { diff --git a/src/engine/sync/synccontrol.h b/src/engine/sync/synccontrol.h index 69af12e6c65..1654a0208b1 100644 --- a/src/engine/sync/synccontrol.h +++ b/src/engine/sync/synccontrol.h @@ -47,17 +47,17 @@ class SyncControl : public EngineControl, public Syncable { // Must never result in a call to // SyncableListener::notifyBeatDistanceChanged or signal loops could occur. - void setMasterBeatDistance(double beatDistance) override; + void updateMasterBeatDistance(double beatDistance) override; // Must never result in a call to // SyncableListener::notifyBpmChanged or signal loops could occur. - void setMasterBpm(double bpm) override; + void updateMasterBpm(double bpm) override; void notifyMasterParamSource() override; - void setMasterParams(double beatDistance, double baseBpm, double bpm) override; + void reinitMasterParams(double beatDistance, double baseBpm, double bpm) override; // Must never result in a call to // SyncableListener::notifyInstantaneousBpmChanged or signal loops could // occur. - void setInstantaneousBpm(double bpm) override; + void updateInstantaneousBpm(double bpm) override; void setEngineControls(RateControl* pRateControl, BpmControl* pBpmControl); @@ -107,7 +107,8 @@ class SyncControl : public EngineControl, public Syncable { // When syncing, sometimes it's better to match half or double the // master bpm. FRIEND_TEST(EngineSyncTest, HalfDoubleBpmTest); - // The amount we should multiply the master BPM to find a good sync match. + FRIEND_TEST(EngineSyncTest, HalfDoubleThenPlay); + // The amount we should multiply the master BPM by to find a good sync match. // Sometimes this is 2 or 0.5. double m_masterBpmAdjustFactor; // It is handy to store the raw reported target beat distance in case the From 47cd79e4294d196a1a1c607eb27e87b841f230cb Mon Sep 17 00:00:00 2001 From: Owen Williams Date: Tue, 15 Jun 2021 22:21:04 -0400 Subject: [PATCH 2/2] Sync Lock: Don't recalc half/double multiplier on every callback --- src/engine/sync/enginesync.cpp | 10 ++++++---- src/test/enginesynctest.cpp | 35 +++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/engine/sync/enginesync.cpp b/src/engine/sync/enginesync.cpp index 595be45439c..7be0f0fe283 100644 --- a/src/engine/sync/enginesync.cpp +++ b/src/engine/sync/enginesync.cpp @@ -415,11 +415,13 @@ void EngineSync::requestBpmUpdate(Syncable* pSyncable, double bpm) { } if (mbaseBpm != 0.0) { - // resync to current master - pSyncable->reinitMasterParams(beatDistance, mbaseBpm, mbpm); + // update from current master + pSyncable->updateMasterBeatDistance(beatDistance); + pSyncable->updateMasterBpm(mbpm); } else { - // There is no other master, adopt this bpm as master - pSyncable->reinitMasterParams(0.0, 0.0, bpm); + // There is no master, adopt this bpm as master value + pSyncable->updateMasterBeatDistance(0.0); + pSyncable->updateMasterBpm(bpm); } } diff --git a/src/test/enginesynctest.cpp b/src/test/enginesynctest.cpp index 953c9405e62..cfe50230b1e 100644 --- a/src/test/enginesynctest.cpp +++ b/src/test/enginesynctest.cpp @@ -1670,18 +1670,22 @@ TEST_F(EngineSyncTest, HalfDoubleBpmTest) { mixxx::BeatsPointer pBeats2 = BeatFactory::makeBeatGrid(m_pTrack2->getSampleRate(), 140, 0.0); m_pTrack2->trySetBeats(pBeats2); + // Mixxx will choose the first playing deck to be master. Let's start deck 2 first. + ControlObject::getControl(ConfigKey(m_sGroup1, "volume"))->set(1.0); + ControlObject::getControl(ConfigKey(m_sGroup2, "volume"))->set(1.0); + ProcessBuffer(); ControlObject::getControl(ConfigKey(m_sGroup1, "quantize"))->set(1.0); ControlObject::getControl(ConfigKey(m_sGroup2, "quantize"))->set(1.0); - ControlObject::getControl(ConfigKey(m_sGroup2, "sync_mode")) - ->set(SYNC_FOLLOWER); - ControlObject::getControl(ConfigKey(m_sGroup1, "sync_mode")) - ->set(SYNC_FOLLOWER); - - // Mixxx will choose the first playing deck to be master. Let's start deck 2 first. + ControlObject::getControl(ConfigKey(m_sGroup2, "sync_enabled"))->set(1); + ControlObject::getControl(ConfigKey(m_sGroup1, "sync_enabled"))->set(1); + ProcessBuffer(); ControlObject::getControl(ConfigKey(m_sGroup2, "play"))->set(1.0); ControlObject::getControl(ConfigKey(m_sGroup1, "play"))->set(1.0); ProcessBuffer(); + ASSERT_TRUE(isSoftMaster(m_sGroup2)); + ASSERT_TRUE(isFollower(m_sGroup1)); + EXPECT_EQ(0.5, m_pChannel1->getEngineBuffer() ->m_pSyncControl->m_masterBpmAdjustFactor); @@ -1777,9 +1781,15 @@ TEST_F(EngineSyncTest, HalfDoubleThenPlay) { ControlObject::getControl(ConfigKey(m_sGroup2, "quantize"))->set(1.0); // We expect that m_sGroup1 has adjusted its own bpm to the second deck and becomes a single master. - // When the second deck is synced the master bpm is adopted by the internal clock + // The internal clock is initialized right away. EXPECT_TRUE(isSoftMaster(m_sGroup1)); EXPECT_TRUE(isFollower(m_sGroup2)); + EXPECT_DOUBLE_EQ(1.0, + m_pChannel1->getEngineBuffer() + ->m_pSyncControl->m_masterBpmAdjustFactor); + EXPECT_DOUBLE_EQ(2.0, + m_pChannel2->getEngineBuffer() + ->m_pSyncControl->m_masterBpmAdjustFactor); EXPECT_DOUBLE_EQ(87.5, ControlObject::getControl(ConfigKey(m_sInternalClockGroup, "bpm")) ->get()); @@ -1790,9 +1800,10 @@ TEST_F(EngineSyncTest, HalfDoubleThenPlay) { EXPECT_DOUBLE_EQ(87.5 / 80, ControlObject::getControl(ConfigKey(m_sGroup1, "rate_ratio")) ->get()); - EXPECT_DOUBLE_EQ(1, + EXPECT_DOUBLE_EQ(1.0, ControlObject::getControl(ConfigKey(m_sGroup2, "rate_ratio")) ->get()); + // Local bpms are not adjusted by the multiplier EXPECT_DOUBLE_EQ(80, ControlObject::getControl(ConfigKey(m_sGroup1, "local_bpm")) ->get()); @@ -1828,13 +1839,19 @@ TEST_F(EngineSyncTest, HalfDoubleThenPlay) { ProcessBuffer(); pButtonSyncEnabled2->slotSet(1.0); pButtonSyncEnabled1->slotSet(1.0); + EXPECT_DOUBLE_EQ(0.5, + m_pChannel1->getEngineBuffer() + ->m_pSyncControl->m_masterBpmAdjustFactor); + EXPECT_DOUBLE_EQ(1.0, + m_pChannel2->getEngineBuffer() + ->m_pSyncControl->m_masterBpmAdjustFactor); ControlObject::getControl(ConfigKey(m_sGroup1, "play"))->set(1.0); ControlObject::getControl(ConfigKey(m_sGroup2, "play"))->set(1.0); EXPECT_DOUBLE_EQ(87.5 / 80, ControlObject::getControl(ConfigKey(m_sGroup1, "rate_ratio")) ->get()); - EXPECT_DOUBLE_EQ(1, + EXPECT_DOUBLE_EQ(1.0, ControlObject::getControl(ConfigKey(m_sGroup2, "rate_ratio")) ->get());