From 189956a516bbdff81bfad3bf2af991c5861a33c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Thu, 19 Jul 2018 14:55:49 +0200 Subject: Respect microphone mute control, used in Deere. --- src/engine/enginemaster.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/engine/enginemaster.cpp b/src/engine/enginemaster.cpp index 12a8e06ae3..acc718f82f 100644 --- a/src/engine/enginemaster.cpp +++ b/src/engine/enginemaster.cpp @@ -289,7 +289,8 @@ void EngineMaster::processChannels(int iBufferSize) { continue; } - if (pChannel->isTalkoverEnabled()) { + if (pChannel->isTalkoverEnabled() && + !pChannelInfo->m_pMuteControl->toBool()) { // talkover is an exclusive channel // once talkover is enabled it is not used in // xFader-Mix -- cgit v1.2.3 From 9e2dac6bf5bdf2795a47abbfe12d750089da6e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Thu, 19 Jul 2018 15:15:43 +0200 Subject: Respect volume control of the microphone channels --- src/engine/enginemaster.cpp | 8 ++++---- src/engine/enginemaster.h | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/engine/enginemaster.cpp b/src/engine/enginemaster.cpp index acc718f82f..ccdf192894 100644 --- a/src/engine/enginemaster.cpp +++ b/src/engine/enginemaster.cpp @@ -450,10 +450,10 @@ void EngineMaster::process(const int iBufferSize) { // Mix all the talkover enabled channels together. // Effects processing is done in place to avoid unnecessary buffer copying. ChannelMixer::applyEffectsInPlaceAndMixChannels( - m_talkoverGain, &m_activeTalkoverChannels, - &m_channelTalkoverGainCache, - m_pTalkover, m_masterHandle.handle(), - m_iBufferSize, m_iSampleRate, m_pEngineEffectsManager); + m_talkoverGain, &m_activeTalkoverChannels, + &m_channelTalkoverGainCache, + m_pTalkover, m_masterHandle.handle(), + m_iBufferSize, m_iSampleRate, m_pEngineEffectsManager); // Process effects on all microphones mixed together // We have no metadata for mixed effect buses, so use an empty GroupFeatureState. diff --git a/src/engine/enginemaster.h b/src/engine/enginemaster.h index 5a2fa72ed9..ea891b5f7f 100644 --- a/src/engine/enginemaster.h +++ b/src/engine/enginemaster.h @@ -164,8 +164,7 @@ class EngineMaster : public QObject, public AudioSource { class TalkoverGainCalculator : public GainCalculator { public: inline double getGain(ChannelInfo* pChannelInfo) const { - Q_UNUSED(pChannelInfo); - return 1.0; + return pChannelInfo->m_pVolumeControl->get(); } }; class OrientationVolumeGainCalculator : public GainCalculator { -- cgit v1.2.3 From 6976fae03ed9db2f0e3444e42cd20c9c729c59cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 23 Sep 2018 02:17:40 +0200 Subject: Sync to the loaded deck with the lowest index if no track is playing --- src/engine/sync/enginesync.cpp | 21 +++++++++++---------- src/test/enginesynctest.cpp | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/engine/sync/enginesync.cpp b/src/engine/sync/enginesync.cpp index 9b0436e95e..79b1c0b5c9 100644 --- a/src/engine/sync/enginesync.cpp +++ b/src/engine/sync/enginesync.cpp @@ -110,32 +110,33 @@ void EngineSync::requestEnableSync(Syncable* pSyncable, bool bEnabled) { double targetBeatDistance = 0.0; double targetBaseBpm = 0.0; - foreach (const Syncable* other_deck, m_syncables) { - if (other_deck == pSyncable) { + for (const auto& pOtherSyncable: m_syncables) { + if (pOtherSyncable == pSyncable) { // skip this deck continue; } - if (!other_deck->getChannel()->isMasterEnabled()) { + if (!pOtherSyncable->getChannel()->isMasterEnabled()) { // skip non-master decks, like preview decks. continue; } - double otherDeckBpm = other_deck->getBpm(); + double otherDeckBpm = pOtherSyncable->getBpm(); if (otherDeckBpm > 0.0) { - // If the requesting deck is playing, but the other deck - // is not, do not sync. - if (pSyncable->isPlaying() && !other_deck->isPlaying()) { + // If the requesting deck is playing, or we have already a + // non plaing deck found, only watch out for playing decks. + if ((foundTargetBpm || pSyncable->isPlaying()) + && !pOtherSyncable->isPlaying()) { continue; } foundTargetBpm = true; targetBpm = otherDeckBpm; - targetBaseBpm = other_deck->getBaseBpm(); - targetBeatDistance = other_deck->getBeatDistance(); + targetBaseBpm = pOtherSyncable->getBaseBpm(); + targetBeatDistance = pOtherSyncable->getBeatDistance(); // If the other deck is playing we stop looking // immediately. Otherwise continue looking for a playing // deck with bpm > 0.0. - if (other_deck->isPlaying()) { + if (pOtherSyncable->isPlaying()) { foundPlayingDeck = true; break; } diff --git a/src/test/enginesynctest.cpp b/src/test/enginesynctest.cpp index 99ef7cc609..744ce56cb0 100644 --- a/src/test/enginesynctest.cpp +++ b/src/test/enginesynctest.cpp @@ -1340,9 +1340,9 @@ TEST_F(EngineSyncTest, SyncPhaseToPlayingNonSyncDeck) { ControlObject::getControl(ConfigKey(m_sGroup1, "play"))->set(1.0); ProcessBuffer(); - EXPECT_FLOAT_EQ(140.0, + EXPECT_FLOAT_EQ(100.0, ControlObject::getControl(ConfigKey(m_sInternalClockGroup, "bpm"))->get()); - EXPECT_FLOAT_EQ(140.0, ControlObject::getControl(ConfigKey(m_sGroup1, "bpm"))->get()); + EXPECT_FLOAT_EQ(100.0, ControlObject::getControl(ConfigKey(m_sGroup1, "bpm"))->get()); // The exact beat distance will be one buffer past .6, but this is good // enough to confirm that it worked. EXPECT_GT(0.7, ControlObject::getControl(ConfigKey(m_sGroup1, "beat_distance"))->get()); -- cgit v1.2.3 From 8b51c4cdeed40e1c765c6c84e3414e9185e311af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 11 Nov 2018 23:22:31 +0100 Subject: Fix quantize seeks if one deck only is playing --- src/engine/bpmcontrol.cpp | 18 ++++++++++-------- src/test/enginesynctest.cpp | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/engine/bpmcontrol.cpp b/src/engine/bpmcontrol.cpp index 123ab756fd..8d42bd2177 100644 --- a/src/engine/bpmcontrol.cpp +++ b/src/engine/bpmcontrol.cpp @@ -614,18 +614,20 @@ double BpmControl::getNearestPositionInPhase(double dThisPosition, bool respectL } else { // If not, we have to figure it out EngineBuffer* pOtherEngineBuffer = pickSyncTarget(); - if (pOtherEngineBuffer == NULL) { - return dThisPosition; - } - if (playing) { - // "this" track is playing, or just starting - // only match phase if the sync target is playing as well - if (pOtherEngineBuffer->getSpeed() == 0.0) { - return dThisPosition; + if (!pOtherEngineBuffer || pOtherEngineBuffer->getSpeed() == 0.0) { + // "this" track is playing, or just starting + // only match phase if the sync target is playing as well + // else use the previouse phase of "this" track before the seek + pOtherEngineBuffer = getEngineBuffer(); } } + if (!pOtherEngineBuffer) { + // no suitable sync buffer found + return dThisPosition; + } + TrackPointer otherTrack = pOtherEngineBuffer->getLoadedTrack(); BeatsPointer otherBeats = otherTrack ? otherTrack->getBeats() : BeatsPointer(); diff --git a/src/test/enginesynctest.cpp b/src/test/enginesynctest.cpp index 9a2d892316..0256fed212 100644 --- a/src/test/enginesynctest.cpp +++ b/src/test/enginesynctest.cpp @@ -1499,6 +1499,23 @@ TEST_F(EngineSyncTest, QuantizeImpliesSyncPhase) { } +TEST_F(EngineSyncTest, SeekStayInPhase) { + ControlObject::set(ConfigKey(m_sGroup1, "quantize"), 1.0); + + auto pFileBpm1 = std::make_unique(m_sGroup1, "file_bpm"); + ControlObject::set(ConfigKey(m_sGroup1, "beat_distance"), 0.2); + pFileBpm1->set(130.0); + BeatsPointer pBeats1 = BeatFactory::makeBeatGrid(*m_pTrack1, 130, 0.0); + m_pTrack1->setBeats(pBeats1); + + ControlObject::set(ConfigKey(m_sGroup1, "play"), 1.0); + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "playposition"), 0.2); + ProcessBuffer(); + + ASSERT_DOUBLE_EQ(0.20464410501585786, ControlObject::get(ConfigKey(m_sGroup1, "playposition"))); +} TEST_F(EngineSyncTest, SyncWithoutBeatgrid) { // this tests bug lp1783020, notresetting rate when other deck has no beatgrid -- cgit v1.2.3 From 14b39b67dce9747ca7e064fbd5c7be001280ba84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sat, 17 Nov 2018 20:24:08 +0100 Subject: fix boolean interpretations of button COs. Fix coding style. --- src/engine/ratecontrol.cpp | 158 ++++++++++++++++++++++----------------------- src/engine/ratecontrol.h | 24 +++---- 2 files changed, 89 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index 644b5e385f..23fe029b32 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -82,52 +82,52 @@ RateControl::RateControl(QString group, m_pVCMode = ControlObject::getControl(ConfigKey(getGroup(), "vinylcontrol_mode")); // Permanent rate-change buttons - buttonRatePermDown = + m_pButtonRatePermDown = new ControlPushButton(ConfigKey(group,"rate_perm_down")); - connect(buttonRatePermDown, SIGNAL(valueChanged(double)), + connect(m_pButtonRatePermDown, SIGNAL(valueChanged(double)), this, SLOT(slotControlRatePermDown(double)), Qt::DirectConnection); - buttonRatePermDownSmall = + m_pButtonRatePermDownSmall = new ControlPushButton(ConfigKey(group,"rate_perm_down_small")); - connect(buttonRatePermDownSmall, SIGNAL(valueChanged(double)), + connect(m_pButtonRatePermDownSmall, SIGNAL(valueChanged(double)), this, SLOT(slotControlRatePermDownSmall(double)), Qt::DirectConnection); - buttonRatePermUp = + m_pButtonRatePermUp = new ControlPushButton(ConfigKey(group,"rate_perm_up")); - connect(buttonRatePermUp, SIGNAL(valueChanged(double)), + connect(m_pButtonRatePermUp, SIGNAL(valueChanged(double)), this, SLOT(slotControlRatePermUp(double)), Qt::DirectConnection); - buttonRatePermUpSmall = + m_pButtonRatePermUpSmall = new ControlPushButton(ConfigKey(group,"rate_perm_up_small")); - connect(buttonRatePermUpSmall, SIGNAL(valueChanged(double)), + connect(m_pButtonRatePermUpSmall, SIGNAL(valueChanged(double)), this, SLOT(slotControlRatePermUpSmall(double)), Qt::DirectConnection); // Temporary rate-change buttons - buttonRateTempDown = + m_pButtonRateTempDown = new ControlPushButton(ConfigKey(group,"rate_temp_down")); - connect(buttonRateTempDown, SIGNAL(valueChanged(double)), + connect(m_pButtonRateTempDown, SIGNAL(valueChanged(double)), this, SLOT(slotControlRateTempDown(double)), Qt::DirectConnection); - buttonRateTempDownSmall = + m_pButtonRateTempDownSmall = new ControlPushButton(ConfigKey(group,"rate_temp_down_small")); - connect(buttonRateTempDownSmall, SIGNAL(valueChanged(double)), + connect(m_pButtonRateTempDownSmall, SIGNAL(valueChanged(double)), this, SLOT(slotControlRateTempDownSmall(double)), Qt::DirectConnection); - buttonRateTempUp = + m_pButtonRateTempUp = new ControlPushButton(ConfigKey(group,"rate_temp_up")); - connect(buttonRateTempUp, SIGNAL(valueChanged(double)), + connect(m_pButtonRateTempUp, SIGNAL(valueChanged(double)), this, SLOT(slotControlRateTempUp(double)), Qt::DirectConnection); - buttonRateTempUpSmall = + m_pButtonRateTempUpSmall = new ControlPushButton(ConfigKey(group,"rate_temp_up_small")); - connect(buttonRateTempUpSmall, SIGNAL(valueChanged(double)), + connect(m_pButtonRateTempUpSmall, SIGNAL(valueChanged(double)), this, SLOT(slotControlRateTempUpSmall(double)), Qt::DirectConnection); @@ -185,14 +185,14 @@ RateControl::~RateControl() { delete m_pForwardButton; delete m_pBackButton; - delete buttonRateTempDown; - delete buttonRateTempDownSmall; - delete buttonRateTempUp; - delete buttonRateTempUpSmall; - delete buttonRatePermDown; - delete buttonRatePermDownSmall; - delete buttonRatePermUp; - delete buttonRatePermUpSmall; + delete m_pButtonRateTempDown; + delete m_pButtonRateTempDownSmall; + delete m_pButtonRateTempUp; + delete m_pButtonRateTempUpSmall; + delete m_pButtonRatePermDown; + delete m_pButtonRatePermDownSmall; + delete m_pButtonRatePermUp; + delete m_pButtonRatePermUpSmall; delete m_pWheel; delete m_pScratch2; @@ -281,112 +281,111 @@ void RateControl::slotReverseRollActivate(double v) { } } -void RateControl::slotControlFastForward(double v) -{ +void RateControl::slotControlFastForward(double v) { //qDebug() << "slotControlFastForward(" << v << ")"; - if (v==0.) - m_pRateSearch->set(0.); - else - m_pRateSearch->set(4.); + if (v > 0.0) { + m_pRateSearch->set(4.0); + } else { + m_pRateSearch->set(0.0); + } } -void RateControl::slotControlFastBack(double v) -{ +void RateControl::slotControlFastBack(double v) { //qDebug() << "slotControlFastBack(" << v << ")"; - if (v==0.) - m_pRateSearch->set(0.); - else - m_pRateSearch->set(-4.); + if (v > 0.0) { + m_pRateSearch->set(-4.0); + } else { + m_pRateSearch->set(0.0); + } } -void RateControl::slotControlRatePermDown(double) -{ +void RateControl::slotControlRatePermDown(double v) { // Adjusts temp rate down if button pressed - if (buttonRatePermDown->get()) { + if (v > 0.0) { m_pRateSlider->set(m_pRateSlider->get() - - m_pRateDir->get() * m_dPermanentRateChangeCoarse / (100 * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeCoarse / (100 * m_pRateRange->get())); } } -void RateControl::slotControlRatePermDownSmall(double) -{ +void RateControl::slotControlRatePermDownSmall(double v) { // Adjusts temp rate down if button pressed - if (buttonRatePermDownSmall->get()) + if (v > 0.0) { m_pRateSlider->set(m_pRateSlider->get() - - m_pRateDir->get() * m_dPermanentRateChangeFine / (100. * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeFine / (100. * m_pRateRange->get())); + } } -void RateControl::slotControlRatePermUp(double) -{ +void RateControl::slotControlRatePermUp(double v) { // Adjusts temp rate up if button pressed - if (buttonRatePermUp->get()) { + if (v > 0.0) { m_pRateSlider->set(m_pRateSlider->get() + - m_pRateDir->get() * m_dPermanentRateChangeCoarse / (100. * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeCoarse / (100. * m_pRateRange->get())); } } -void RateControl::slotControlRatePermUpSmall(double) -{ +void RateControl::slotControlRatePermUpSmall(double v) { // Adjusts temp rate up if button pressed - if (buttonRatePermUpSmall->get()) + if (v > 0.0) { m_pRateSlider->set(m_pRateSlider->get() + - m_pRateDir->get() * m_dPermanentRateChangeFine / (100. * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeFine / (100. * m_pRateRange->get())); + } } -void RateControl::slotControlRateTempDown(double) -{ +void RateControl::slotControlRateTempDown(double value) { // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempDown->get() && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) + bool pressed = value > 0; + if (pressed && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) { m_ePbPressed |= RateControl::RATERAMP_DOWN; m_ePbCurrent = RateControl::RATERAMP_DOWN; } - else if (!buttonRateTempDown->get()) + else if (!pressed) { m_ePbPressed &= ~RateControl::RATERAMP_DOWN; m_ePbCurrent = m_ePbPressed; } } -void RateControl::slotControlRateTempDownSmall(double) -{ +void RateControl::slotControlRateTempDownSmall(double value) { // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempDownSmall->get() && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) + bool pressed = value > 0; + if (pressed && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) { m_ePbPressed |= RateControl::RATERAMP_DOWN; m_ePbCurrent = RateControl::RATERAMP_DOWN; } - else if (!buttonRateTempDownSmall->get()) + else if (!pressed) { m_ePbPressed &= ~RateControl::RATERAMP_DOWN; m_ePbCurrent = m_ePbPressed; } } -void RateControl::slotControlRateTempUp(double) -{ +void RateControl::slotControlRateTempUp(double value) { // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempUp->get() && !(m_ePbPressed & RateControl::RATERAMP_UP)) + bool pressed = value > 0; + if (pressed && !(m_ePbPressed & RateControl::RATERAMP_UP)) { m_ePbPressed |= RateControl::RATERAMP_UP; m_ePbCurrent = RateControl::RATERAMP_UP; } - else if (!buttonRateTempUp->get()) + else if (!pressed) { m_ePbPressed &= ~RateControl::RATERAMP_UP; m_ePbCurrent = m_ePbPressed; } } -void RateControl::slotControlRateTempUpSmall(double) +void RateControl::slotControlRateTempUpSmall(double value) { // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempUpSmall->get() && !(m_ePbPressed & RateControl::RATERAMP_UP)) + bool pressed = value > 0; + if (pressed && !(m_ePbPressed & RateControl::RATERAMP_UP)) { m_ePbPressed |= RateControl::RATERAMP_UP; m_ePbCurrent = RateControl::RATERAMP_UP; } - else if (!buttonRateTempUpSmall->get()) + else if (!pressed) { m_ePbPressed &= ~RateControl::RATERAMP_UP; m_ePbCurrent = m_ePbPressed; @@ -533,11 +532,8 @@ double RateControl::calculateSpeed(double baserate, double speed, bool paused, return rate; } -void RateControl::process(const double rate, - const double currentSample, - const double totalSamples, - const int bufferSamples) -{ +void RateControl::process(const double rate, const double currentSample, + const double totalSamples, const int bufferSamples) { Q_UNUSED(rate); Q_UNUSED(currentSample); Q_UNUSED(totalSamples); @@ -555,9 +551,6 @@ void RateControl::process(const double rate, * one. */ - double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); - - if ((m_ePbPressed) && (!m_bTempStarted)) { m_bTempStarted = true; @@ -576,19 +569,22 @@ void RateControl::process(const double rate, double csmall = m_pRateDir->get() * m_dTemporaryRateChangeFine / (100. * range); - if (buttonRateTempUp->get()) + if (m_pButtonRateTempUp->toBool()) { addRateTemp(change); - else if (buttonRateTempDown->get()) + } else if (m_pButtonRateTempDown->toBool()) { subRateTemp(change); - else if (buttonRateTempUpSmall->get()) + } else if (m_pButtonRateTempUpSmall->toBool()) { addRateTemp(csmall); - else if (buttonRateTempDownSmall->get()) + } else if (m_pButtonRateTempDownSmall->toBool()) { subRateTemp(csmall); + } } else if (m_eRateRampMode == RampMode::Linear) { - m_dTemporaryRateChangeCoarse = ((double)latrate / ((double)m_iRateRampSensitivity / 100.)); + double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); + m_dTemporaryRateChangeCoarse = (latrate / ((double)m_iRateRampSensitivity / 100.)); - if (m_eRampBackMode == RATERAMP_RAMPBACK_PERIOD) + if (m_eRampBackMode == RATERAMP_RAMPBACK_PERIOD) { m_dRateTempRampbackChange = 0.0; + } } } diff --git a/src/engine/ratecontrol.h b/src/engine/ratecontrol.h index bd8b407fe5..265bd7665c 100644 --- a/src/engine/ratecontrol.h +++ b/src/engine/ratecontrol.h @@ -130,18 +130,18 @@ public: static double m_dPermanentRateChangeCoarse; static double m_dPermanentRateChangeFine; - ControlPushButton *buttonRateTempDown; - ControlPushButton *buttonRateTempDownSmall; - ControlPushButton *buttonRateTempUp; - ControlPushButton *buttonRateTempUpSmall; - - ControlPushButton *buttonRatePermDown; - ControlPushButton *buttonRatePermDownSmall; - ControlPushButton *buttonRatePermUp; - ControlPushButton *buttonRatePermUpSmall; - - ControlObject *m_pRateDir; - ControlObject *m_pRateRange; + ControlPushButton* m_pButtonRateTempDown; + ControlPushButton* m_pButtonRateTempDownSmall; + ControlPushButton* m_pButtonRateTempUp; + ControlPushButton* m_pButtonRateTempUpSmall; + + ControlPushButton* m_pButtonRatePermDown; + ControlPushButton* m_pButtonRatePermDownSmall; + ControlPushButton* m_pButtonRatePermUp; + ControlPushButton* m_pButtonRatePermUpSmall; + + ControlObject* m_pRateDir; + ControlObject* m_pRateRange; ControlPotmeter* m_pRateSlider; ControlPotmeter* m_pRateSearch; ControlPushButton* m_pReverseButton; -- cgit v1.2.3 From 93badfb196cbe822d3aab3a646b28ec0000a6ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sat, 17 Nov 2018 23:18:16 +0100 Subject: fix temp rate scaling, rename to m_tempRateRatio --- src/engine/ratecontrol.cpp | 65 +++++++++++++++++++--------------------------- src/engine/ratecontrol.h | 2 +- 2 files changed, 28 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index 23fe029b32..064d5790b7 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -36,7 +36,7 @@ RateControl::RateControl(QString group, m_ePbPressed(0), m_bTempStarted(false), m_dTempRateChange(0.0), - m_dRateTemp(0.0), + m_tempRateRatio(0.0), m_eRampBackMode(RATERAMP_RAMPBACK_NONE), m_dRateTempRampbackChange(0.0) { m_pScratchController = new PositionScratchController(group); @@ -556,27 +556,17 @@ void RateControl::process(const double rate, const double currentSample, if (m_eRateRampMode == RampMode::Stepping) { // old temporary pitch shift behavior - double range = m_pRateRange->get(); - - // Avoid Division by Zero - if (range == 0) { - qDebug() << "Avoiding a Division by Zero in RATERAMP_STEP code"; - return; - } - - double change = m_pRateDir->get() * m_dTemporaryRateChangeCoarse / - (100. * range); - double csmall = m_pRateDir->get() * m_dTemporaryRateChangeFine / - (100. * range); + double change = m_dTemporaryRateChangeCoarse / 100.0; + double csmall = m_dTemporaryRateChangeFine / 100.0; if (m_pButtonRateTempUp->toBool()) { - addRateTemp(change); + setRateTemp(change); } else if (m_pButtonRateTempDown->toBool()) { - subRateTemp(change); + setRateTemp(-change); } else if (m_pButtonRateTempUpSmall->toBool()) { - addRateTemp(csmall); + setRateTemp(csmall); } else if (m_pButtonRateTempDownSmall->toBool()) { - subRateTemp(csmall); + setRateTemp(-csmall); } } else if (m_eRateRampMode == RampMode::Linear) { double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); @@ -586,20 +576,19 @@ void RateControl::process(const double rate, const double currentSample, m_dRateTempRampbackChange = 0.0; } } - } if (m_eRateRampMode == RampMode::Linear) { if (m_ePbCurrent) { // apply ramped pitchbending if (m_ePbCurrent == RateControl::RATERAMP_UP) { - addRateTemp(m_dTemporaryRateChangeCoarse); + addRateTemp(m_dTemporaryRateChangeCoarse * m_pRateRange->get()); } else if (m_ePbCurrent == RateControl::RATERAMP_DOWN) { - subRateTemp(m_dTemporaryRateChangeCoarse); + subRateTemp(m_dTemporaryRateChangeCoarse * m_pRateRange->get()); } } else if ((m_bTempStarted) || ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) - && (m_dRateTemp != 0.0))) { + && (m_tempRateRatio != 0.0))) { // No buttons pressed, so time to deinitialize m_bTempStarted = false; @@ -607,15 +596,15 @@ void RateControl::process(const double rate, const double currentSample, && (m_dRateTempRampbackChange == 0.0)) { int period = 2; m_dRateTempRampbackChange = fabs( - m_dRateTemp / period); + m_tempRateRatio / period); } else if ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) && (m_dRateTempRampbackChange == 0.0)) { - if (fabs(m_dRateTemp) < m_dRateTempRampbackChange) { + if (fabs(m_tempRateRatio) < m_dRateTempRampbackChange) { resetRateTemp(); - } else if (m_dRateTemp > 0) { - subRateTemp(m_dRateTempRampbackChange); + } else if (m_tempRateRatio > 0) { + subRateTemp(m_dRateTempRampbackChange * m_pRateRange->get()); } else { - addRateTemp(m_dRateTempRampbackChange); + addRateTemp(m_dRateTempRampbackChange * m_pRateRange->get()); } } else { resetRateTemp(); @@ -630,34 +619,34 @@ void RateControl::process(const double rate, const double currentSample, } double RateControl::getTempRate() { - return (m_pRateDir->get() * (m_dRateTemp * m_pRateRange->get())); + qDebug() << m_tempRateRatio; + return m_tempRateRatio; } -void RateControl::setRateTemp(double v) -{ +void RateControl::setRateTemp(double v) { // Do not go backwards if ((calcRateRatio() + v) < 0) { return; } - m_dRateTemp = v; - if (m_dRateTemp < -1.0) { - m_dRateTemp = -1.0; - } else if (m_dRateTemp > 1.0) { - m_dRateTemp = 1.0; - } else if (isnan(m_dRateTemp)) { - m_dRateTemp = 0; + m_tempRateRatio = v; + if (m_tempRateRatio < -1.0) { + m_tempRateRatio = -1.0; + } else if (m_tempRateRatio > 1.0) { + m_tempRateRatio = 1.0; + } else if (isnan(m_tempRateRatio)) { + m_tempRateRatio = 0; } } void RateControl::addRateTemp(double v) { - setRateTemp(m_dRateTemp + v); + setRateTemp(m_tempRateRatio + v); } void RateControl::subRateTemp(double v) { - setRateTemp(m_dRateTemp - v); + setRateTemp(m_tempRateRatio - v); } void RateControl::resetRateTemp(void) diff --git a/src/engine/ratecontrol.h b/src/engine/ratecontrol.h index 265bd7665c..afc87baf4e 100644 --- a/src/engine/ratecontrol.h +++ b/src/engine/ratecontrol.h @@ -189,7 +189,7 @@ public: // Factor applied to jogwheels when the track is paused to speed up seeking. static const double kPausedJogMultiplier; // Temporary pitchrate, added to the permanent rate for calculateRate - double m_dRateTemp; + double m_tempRateRatio; enum RATERAMP_RAMPBACK_MODE m_eRampBackMode; // Return speed for temporary rate change double m_dRateTempRampbackChange; -- cgit v1.2.3 From aa2a8c2ec594a89a40b67d8f7db0a9dbc3b936f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sat, 17 Nov 2018 23:24:16 +0100 Subject: Fix going backwards, holding pitch bend buttons --- src/engine/ratecontrol.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index 064d5790b7..08b3396c70 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -486,7 +486,8 @@ double RateControl::calculateSpeed(double baserate, double speed, bool paused, if (useScratch2Value) { rate = scratchFactor; } else { - rate = speed + getTempRate(); + // add temp rate, but don't go backwards + rate = math_max(speed + getTempRate(), 0.0); rate += wheelFactor; } rate += jogFactor; @@ -619,16 +620,11 @@ void RateControl::process(const double rate, const double currentSample, } double RateControl::getTempRate() { - qDebug() << m_tempRateRatio; + // qDebug() << m_tempRateRatio; return m_tempRateRatio; } void RateControl::setRateTemp(double v) { - // Do not go backwards - if ((calcRateRatio() + v) < 0) { - return; - } - m_tempRateRatio = v; if (m_tempRateRatio < -1.0) { m_tempRateRatio = -1.0; -- cgit v1.2.3 From 10bbbceb819dee27aaa00245981b265a16d97c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sat, 17 Nov 2018 23:37:19 +0100 Subject: don't override user setting m_dTemporaryRateChangeCoarse in linear mode --- src/engine/ratecontrol.cpp | 7 ++++--- src/engine/ratecontrol.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index 08b3396c70..a4172bab7b 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -38,6 +38,7 @@ RateControl::RateControl(QString group, m_dTempRateChange(0.0), m_tempRateRatio(0.0), m_eRampBackMode(RATERAMP_RAMPBACK_NONE), + m_dRateTempRampChange(0.0), m_dRateTempRampbackChange(0.0) { m_pScratchController = new PositionScratchController(group); @@ -571,7 +572,7 @@ void RateControl::process(const double rate, const double currentSample, } } else if (m_eRateRampMode == RampMode::Linear) { double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); - m_dTemporaryRateChangeCoarse = (latrate / ((double)m_iRateRampSensitivity / 100.)); + m_dRateTempRampChange = (latrate / ((double)m_iRateRampSensitivity / 100.)); if (m_eRampBackMode == RATERAMP_RAMPBACK_PERIOD) { m_dRateTempRampbackChange = 0.0; @@ -583,9 +584,9 @@ void RateControl::process(const double rate, const double currentSample, if (m_ePbCurrent) { // apply ramped pitchbending if (m_ePbCurrent == RateControl::RATERAMP_UP) { - addRateTemp(m_dTemporaryRateChangeCoarse * m_pRateRange->get()); + addRateTemp(m_dRateTempRampChange * m_pRateRange->get()); } else if (m_ePbCurrent == RateControl::RATERAMP_DOWN) { - subRateTemp(m_dTemporaryRateChangeCoarse * m_pRateRange->get()); + subRateTemp(m_dRateTempRampChange * m_pRateRange->get()); } } else if ((m_bTempStarted) || ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) diff --git a/src/engine/ratecontrol.h b/src/engine/ratecontrol.h index afc87baf4e..2b959bf843 100644 --- a/src/engine/ratecontrol.h +++ b/src/engine/ratecontrol.h @@ -191,6 +191,8 @@ public: // Temporary pitchrate, added to the permanent rate for calculateRate double m_tempRateRatio; enum RATERAMP_RAMPBACK_MODE m_eRampBackMode; + // Speed for temporary rate change + double m_dRateTempRampChange; // Return speed for temporary rate change double m_dRateTempRampbackChange; }; -- cgit v1.2.3 From 19c44c6b78d4ae6e43e36bab81ecbde9f70a2597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 18 Nov 2018 01:21:31 +0100 Subject: Added test and fix to require two process calls to adopt pitch bend --- src/engine/enginebuffer.h | 1 + src/engine/ratecontrol.cpp | 9 +++--- src/engine/ratecontrol.h | 8 ++--- src/test/enginebuffertest.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/engine/enginebuffer.h b/src/engine/enginebuffer.h index 6adf9ab24d..1358e94a58 100644 --- a/src/engine/enginebuffer.h +++ b/src/engine/enginebuffer.h @@ -366,6 +366,7 @@ class EngineBuffer : public EngineObject { FRIEND_TEST(EngineBufferTest, ResetPitchAdjustUsesLinear); FRIEND_TEST(EngineBufferTest, VinylScalerRampZero); FRIEND_TEST(EngineBufferTest, ReadFadeOut); + FRIEND_TEST(EngineBufferTest, RateTempTest); EngineBufferScale* m_pScaleVinyl; // The keylock engine is configurable, so it could flip flop between // ScaleST and ScaleRB during a single callback. diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index a4172bab7b..c06564c1c1 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -437,6 +437,9 @@ double RateControl::calculateSpeed(double baserate, double speed, bool paused, bool* pReportReverse) { *pReportScratching = false; *pReportReverse = false; + + processTempRate(iSamplesPerBuffer); + double rate = (paused ? 0 : 1.0); double searching = m_pRateSearch->get(); if (searching) { @@ -534,11 +537,7 @@ double RateControl::calculateSpeed(double baserate, double speed, bool paused, return rate; } -void RateControl::process(const double rate, const double currentSample, - const double totalSamples, const int bufferSamples) { - Q_UNUSED(rate); - Q_UNUSED(currentSample); - Q_UNUSED(totalSamples); +void RateControl::processTempRate(const int bufferSamples) { /* * Code to handle temporary rate change buttons. * diff --git a/src/engine/ratecontrol.h b/src/engine/ratecontrol.h index 2b959bf843..28b9e67cdb 100644 --- a/src/engine/ratecontrol.h +++ b/src/engine/ratecontrol.h @@ -60,12 +60,7 @@ public: }; void setBpmControl(BpmControl* bpmcontrol); - // Must be called during each callback of the audio thread so that - // RateControl has a chance to update itself. - void process(const double dRate, - const double currentSample, - const double totalSamples, - const int bufferSamples) override; + // Returns the current engine rate. "reportScratching" is used to tell // the caller that the user is currently scratching, and this is used to // disable keylock. @@ -109,6 +104,7 @@ public: void trackLoaded(TrackPointer pNewTrack, TrackPointer pOldTrack) override; private: + void processTempRate(const int bufferSamples); double getJogFactor() const; double getWheelFactor() const; SyncMode getSyncMode() const; diff --git a/src/test/enginebuffertest.cpp b/src/test/enginebuffertest.cpp index a3c4cf017c..8d152ab295 100644 --- a/src/test/enginebuffertest.cpp +++ b/src/test/enginebuffertest.cpp @@ -11,6 +11,7 @@ #include "test/mockedenginebackendtest.h" #include "test/mixxxtest.h" #include "test/signalpathtest.h" +#include "engine/ratecontrol.h" // Incase any of the test in this file fail. You can use the audioplot.py tool // in the scripts folder to visually compare the results of the enginebuffer @@ -435,3 +436,71 @@ TEST_F(EngineBufferE2ETest, CueGotoAndPlayDenon) { ProcessBuffer(); EXPECT_EQ(cueBefore, ControlObject::get(ConfigKey(m_sGroup1, "cue_point"))); } + +TEST_F(EngineBufferTest, RateTempTest) { + RateControl::setTemporaryRateChangeCoarseAmount(4); + RateControl::setTemporaryRateChangeFineAmount(2); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_dir"), 1); + ControlObject::set(ConfigKey(m_sGroup1, "play"), 1.0); + ProcessBuffer(); + EXPECT_EQ(1.0, m_pChannel1->getEngineBuffer()->m_speed_old); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up"), 1); + ProcessBuffer(); + EXPECT_EQ(1.04, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up"), 0); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up_small"), 1); + ProcessBuffer(); + EXPECT_EQ(1.02, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up_small"), 0); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down"), 1); + ProcessBuffer(); + EXPECT_EQ(0.96, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down"), 0); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down_small"), 1); + ProcessBuffer(); + EXPECT_EQ(0.98, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down_small"), 0); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_dir"), -1); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up"), 1); + ProcessBuffer(); + EXPECT_EQ(1.04, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up"), 0); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up_small"), 1); + ProcessBuffer(); + EXPECT_EQ(1.02, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_up_small"), 0); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down"), 1); + ProcessBuffer(); + EXPECT_EQ(0.96, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down"), 0); + + ProcessBuffer(); + + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down_small"), 1); + ProcessBuffer(); + EXPECT_EQ(0.98, m_pChannel1->getEngineBuffer()->m_speed_old); + ControlObject::set(ConfigKey(m_sGroup1, "rate_temp_down_small"), 0); +} -- cgit v1.2.3 From aa12950573c21b703e0b366009057e0004c4c0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 18 Nov 2018 22:40:26 +0100 Subject: removed unused m_eRampBackMode --- src/engine/ratecontrol.cpp | 30 +++--------------------------- src/engine/ratecontrol.h | 14 -------------- 2 files changed, 3 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index c06564c1c1..3682cf9be6 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -37,9 +37,7 @@ RateControl::RateControl(QString group, m_bTempStarted(false), m_dTempRateChange(0.0), m_tempRateRatio(0.0), - m_eRampBackMode(RATERAMP_RAMPBACK_NONE), - m_dRateTempRampChange(0.0), - m_dRateTempRampbackChange(0.0) { + m_dRateTempRampChange(0.0) { m_pScratchController = new PositionScratchController(group); m_pRateDir = new ControlObject(ConfigKey(group, "rate_dir")); @@ -572,10 +570,6 @@ void RateControl::processTempRate(const int bufferSamples) { } else if (m_eRateRampMode == RampMode::Linear) { double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); m_dRateTempRampChange = (latrate / ((double)m_iRateRampSensitivity / 100.)); - - if (m_eRampBackMode == RATERAMP_RAMPBACK_PERIOD) { - m_dRateTempRampbackChange = 0.0; - } } } @@ -588,28 +582,10 @@ void RateControl::processTempRate(const int bufferSamples) { subRateTemp(m_dRateTempRampChange * m_pRateRange->get()); } } else if ((m_bTempStarted) - || ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) - && (m_tempRateRatio != 0.0))) { + || (m_tempRateRatio != 0.0)) { // No buttons pressed, so time to deinitialize m_bTempStarted = false; - - if ((m_eRampBackMode == RATERAMP_RAMPBACK_PERIOD) - && (m_dRateTempRampbackChange == 0.0)) { - int period = 2; - m_dRateTempRampbackChange = fabs( - m_tempRateRatio / period); - } else if ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) - && (m_dRateTempRampbackChange == 0.0)) { - if (fabs(m_tempRateRatio) < m_dRateTempRampbackChange) { - resetRateTemp(); - } else if (m_tempRateRatio > 0) { - subRateTemp(m_dRateTempRampbackChange * m_pRateRange->get()); - } else { - addRateTemp(m_dRateTempRampbackChange * m_pRateRange->get()); - } - } else { - resetRateTemp(); - } + resetRateTemp(); } } else if ((m_eRateRampMode == RampMode::Stepping) && (m_bTempStarted)) { if (!m_ePbCurrent) { diff --git a/src/engine/ratecontrol.h b/src/engine/ratecontrol.h index 28b9e67cdb..2956b0c182 100644 --- a/src/engine/ratecontrol.h +++ b/src/engine/ratecontrol.h @@ -48,17 +48,6 @@ public: Linear = 1 // pitch moves up/down in a progresively linear fashion }; - // This defines how the rate returns to normal. Currently unused. - // Rate ramp back mode: - // RATERAMP_RAMPBACK_NONE: returns back to normal all at once. - // RATERAMP_RAMPBACK_SPEED: moves back in a linearly progresive manner. - // RATERAMP_RAMPBACK_PERIOD: returns to normal within a period of time. - enum RATERAMP_RAMPBACK_MODE { - RATERAMP_RAMPBACK_NONE, - RATERAMP_RAMPBACK_SPEED, - RATERAMP_RAMPBACK_PERIOD - }; - void setBpmControl(BpmControl* bpmcontrol); // Returns the current engine rate. "reportScratching" is used to tell @@ -186,11 +175,8 @@ public: static const double kPausedJogMultiplier; // Temporary pitchrate, added to the permanent rate for calculateRate double m_tempRateRatio; - enum RATERAMP_RAMPBACK_MODE m_eRampBackMode; // Speed for temporary rate change double m_dRateTempRampChange; - // Return speed for temporary rate change - double m_dRateTempRampbackChange; }; #endif /* RATECONTROL_H */ -- cgit v1.2.3 From ff99c05aee63ec462d29945978f9be11d515f222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Tue, 20 Nov 2018 20:14:15 +0100 Subject: separate linear from stepping code. --- src/engine/ratecontrol.cpp | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index 3682cf9be6..7ca5f9f92d 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -536,24 +536,13 @@ double RateControl::calculateSpeed(double baserate, double speed, bool paused, } void RateControl::processTempRate(const int bufferSamples) { - /* - * Code to handle temporary rate change buttons. - * - * We support two behaviors, the standard ramped pitch bending - * and pitch shift stepping, which is the old behavior. - */ - - /* - * Initialize certain values necessary for pitchbending. Most of this - * code should be handled inside a slot, but we'd need to connect to - * the troublesome Latency ControlObject... Either the Master or Soundcard - * one. - */ - - if ((m_ePbPressed) && (!m_bTempStarted)) { - m_bTempStarted = true; - - if (m_eRateRampMode == RampMode::Stepping) { + // Code to handle temporary rate change buttons. + // We support two behaviors, the standard ramped pitch bending + // and pitch shift stepping, which is the old behavior. + + if (m_eRateRampMode == RampMode::Stepping) { + if (m_ePbPressed && !m_bTempStarted) { + m_bTempStarted = true; // old temporary pitch shift behavior double change = m_dTemporaryRateChangeCoarse / 100.0; double csmall = m_dTemporaryRateChangeFine / 100.0; @@ -567,13 +556,21 @@ void RateControl::processTempRate(const int bufferSamples) { } else if (m_pButtonRateTempDownSmall->toBool()) { setRateTemp(-csmall); } - } else if (m_eRateRampMode == RampMode::Linear) { + } + + if (m_bTempStarted) { + if (!m_ePbCurrent) { + m_bTempStarted = false; + resetRateTemp(); + } + } + } else if (m_eRateRampMode == RampMode::Linear) { + if (m_ePbPressed && !m_bTempStarted) { + m_bTempStarted = true; double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); m_dRateTempRampChange = (latrate / ((double)m_iRateRampSensitivity / 100.)); } - } - if (m_eRateRampMode == RampMode::Linear) { if (m_ePbCurrent) { // apply ramped pitchbending if (m_ePbCurrent == RateControl::RATERAMP_UP) { @@ -587,11 +584,6 @@ void RateControl::processTempRate(const int bufferSamples) { m_bTempStarted = false; resetRateTemp(); } - } else if ((m_eRateRampMode == RampMode::Stepping) && (m_bTempStarted)) { - if (!m_ePbCurrent) { - m_bTempStarted = false; - resetRateTemp(); - } } } -- cgit v1.2.3 From f23595e910102f7800b2aac29f7c9004a578c192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Tue, 20 Nov 2018 23:42:20 +0100 Subject: Fix race conditions with intermediate pitchbend variables --- src/engine/ratecontrol.cpp | 172 +++++++++++++++------------------------------ src/engine/ratecontrol.h | 20 ++---- 2 files changed, 64 insertions(+), 128 deletions(-) (limited to 'src') diff --git a/src/engine/ratecontrol.cpp b/src/engine/ratecontrol.cpp index fccde35a3b..2a7501b0ba 100644 --- a/src/engine/ratecontrol.cpp +++ b/src/engine/ratecontrol.cpp @@ -32,8 +32,6 @@ RateControl::RateControl(QString group, UserSettingsPointer pConfig) : EngineControl(group, pConfig), m_pBpmControl(NULL), - m_ePbCurrent(0), - m_ePbPressed(0), m_bTempStarted(false), m_tempRateRatio(0.0), m_dRateTempRampChange(0.0) { @@ -107,27 +105,12 @@ RateControl::RateControl(QString group, // Temporary rate-change buttons m_pButtonRateTempDown = new ControlPushButton(ConfigKey(group,"rate_temp_down")); - connect(m_pButtonRateTempDown, SIGNAL(valueChanged(double)), - this, SLOT(slotControlRateTempDown(double)), - Qt::DirectConnection); - m_pButtonRateTempDownSmall = new ControlPushButton(ConfigKey(group,"rate_temp_down_small")); - connect(m_pButtonRateTempDownSmall, SIGNAL(valueChanged(double)), - this, SLOT(slotControlRateTempDownSmall(double)), - Qt::DirectConnection); - m_pButtonRateTempUp = new ControlPushButton(ConfigKey(group,"rate_temp_up")); - connect(m_pButtonRateTempUp, SIGNAL(valueChanged(double)), - this, SLOT(slotControlRateTempUp(double)), - Qt::DirectConnection); - m_pButtonRateTempUpSmall = new ControlPushButton(ConfigKey(group,"rate_temp_up_small")); - connect(m_pButtonRateTempUpSmall, SIGNAL(valueChanged(double)), - this, SLOT(slotControlRateTempUpSmall(double)), - Qt::DirectConnection); // We need the sample rate so we can guesstimate something close // what latency is. @@ -329,64 +312,6 @@ void RateControl::slotControlRatePermUpSmall(double v) { } } -void RateControl::slotControlRateTempDown(double value) { - // Set the state of the Temporary button. Logic is handled in ::process() - bool pressed = value > 0; - if (pressed && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) - { - m_ePbPressed |= RateControl::RATERAMP_DOWN; - m_ePbCurrent = RateControl::RATERAMP_DOWN; - } - else if (!pressed) - { - m_ePbPressed &= ~RateControl::RATERAMP_DOWN; - m_ePbCurrent = m_ePbPressed; - } -} - -void RateControl::slotControlRateTempDownSmall(double value) { - // Set the state of the Temporary button. Logic is handled in ::process() - bool pressed = value > 0; - if (pressed && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) - { - m_ePbPressed |= RateControl::RATERAMP_DOWN; - m_ePbCurrent = RateControl::RATERAMP_DOWN; - } - else if (!pressed) - { - m_ePbPressed &= ~RateControl::RATERAMP_DOWN; - m_ePbCurrent = m_ePbPressed; - } -} - -void RateControl::slotControlRateTempUp(double value) { - // Set the state of the Temporary button. Logic is handled in ::process() - bool pressed = value > 0; - if (pressed && !(m_ePbPressed & RateControl::RATERAMP_UP)) - { - m_ePbPressed |= RateControl::RATERAMP_UP; - m_ePbCurrent = RateControl::RATERAMP_UP; - } - else if (!pressed) - { - m_ePbPressed &= ~RateControl::RATERAMP_UP; - m_ePbCurrent = m_ePbPressed; - } -} - -void RateControl::slotControlRateTempUpSmall(double value) -{ - // Set the state of the Temporary button. Logic is handled in ::process() - bool pressed = value > 0; - if (pressed && !(m_ePbPressed & RateControl::RATERAMP_UP)) { - m_ePbPressed |= RateControl::RATERAMP_UP; - m_ePbCurrent = RateControl::RATERAMP_UP; - } else if (!pressed) { - m_ePbPressed &= ~RateControl::RATERAMP_UP; - m_ePbCurrent = m_ePbPressed; - } -} - double RateControl::calcRateRatio() const { double rateRatio = 1.0 + m_pRateDir->get() * m_pRateRange->get() * m_pRateSlider->get(); @@ -531,50 +456,69 @@ void RateControl::processTempRate(const int bufferSamples) { // We support two behaviors, the standard ramped pitch bending // and pitch shift stepping, which is the old behavior. - if (m_eRateRampMode == RampMode::Stepping) { - if (m_ePbPressed && !m_bTempStarted) { - m_bTempStarted = true; - // old temporary pitch shift behavior - double change = m_dTemporaryRateChangeCoarse.getValue() / 100.0; - double csmall = m_dTemporaryRateChangeFine.getValue() / 100.0; - - if (m_pButtonRateTempUp->toBool()) { - setRateTemp(change); - } else if (m_pButtonRateTempDown->toBool()) { - setRateTemp(-change); - } else if (m_pButtonRateTempUpSmall->toBool()) { - setRateTemp(csmall); - } else if (m_pButtonRateTempDownSmall->toBool()) { - setRateTemp(-csmall); - } - } + RampDirection rampDirection = RampDirection::None; + if (m_pButtonRateTempUp->toBool()) { + rampDirection = RampDirection::Up; + } else if (m_pButtonRateTempDown->toBool()) { + rampDirection = RampDirection::Down; + } else if (m_pButtonRateTempUpSmall->toBool()) { + rampDirection = RampDirection::UpSmall; + } else if (m_pButtonRateTempDownSmall->toBool()) { + rampDirection = RampDirection::DownSmall; + } - if (m_bTempStarted) { - if (!m_ePbCurrent) { - m_bTempStarted = false; - resetRateTemp(); + if (rampDirection != RampDirection::None) { + if (m_eRateRampMode == RampMode::Stepping) { + if (!m_bTempStarted) { + m_bTempStarted = true; + // old temporary pitch shift behavior + double change = m_dTemporaryRateChangeCoarse.getValue() / 100.0; + double csmall = m_dTemporaryRateChangeFine.getValue() / 100.0; + + switch (rampDirection) { + case RampDirection::Up: + setRateTemp(change); + break; + case RampDirection::Down: + setRateTemp(-change); + break; + case RampDirection::UpSmall: + setRateTemp(csmall); + break; + case RampDirection::DownSmall: + setRateTemp(-csmall); + break; + case RampDirection::None: + default: + DEBUG_ASSERT(false); + } } - } - } else if (m_eRateRampMode == RampMode::Linear) { - if (m_ePbPressed && !m_bTempStarted) { - m_bTempStarted = true; - double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); - m_dRateTempRampChange = (latrate / ((double)m_iRateRampSensitivity / 100.)); - } + } else if (m_eRateRampMode == RampMode::Linear) { + if (rampDirection != RampDirection::None) { + if (!m_bTempStarted) { + m_bTempStarted = true; + double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); + m_dRateTempRampChange = (latrate / ((double)m_iRateRampSensitivity / 100.)); + } - if (m_ePbCurrent) { - // apply ramped pitchbending - if (m_ePbCurrent == RateControl::RATERAMP_UP) { - addRateTemp(m_dRateTempRampChange * m_pRateRange->get()); - } else if (m_ePbCurrent == RateControl::RATERAMP_DOWN) { - subRateTemp(m_dRateTempRampChange * m_pRateRange->get()); + switch (rampDirection) { + case RampDirection::Up: + case RampDirection::UpSmall: + addRateTemp(m_dRateTempRampChange * m_pRateRange->get()); + break; + case RampDirection::Down: + case RampDirection::DownSmall: + subRateTemp(m_dRateTempRampChange * m_pRateRange->get()); + break; + case RampDirection::None: + default: + DEBUG_ASSERT(false); + } } - } else if ((m_bTempStarted) - || (m_tempRateRatio != 0.0)) { - // No buttons pressed, so time to deinitialize - m_bTempStarted = false; - resetRateTemp(); } + } else if (m_bTempStarted) { + m_bTempStarted = false; + resetRateTemp(); } } diff --git a/src/engine/ratecontrol.h b/src/engine/ratecontrol.h index f394209e4d..c42c6923ea 100644 --- a/src/engine/ratecontrol.h +++ b/src/engine/ratecontrol.h @@ -36,11 +36,12 @@ public: // Enumerations which hold the state of the pitchbend buttons. // These enumerations can be used like a bitmask. - enum RATERAMP_DIRECTION { - RATERAMP_NONE = 0, // No buttons are held down - RATERAMP_DOWN = 1, // Down button is being held - RATERAMP_UP = 2, // Up button is being held - RATERAMP_BOTH = 3 // Both buttons are being held down + enum class RampDirection { + None, // No buttons are held down + Down, // Down button is being held + Up, // Up button is being held + DownSmall, // DownSmall button is being held + UpSmall, // UpSmall button is being held }; enum class RampMode { @@ -84,10 +85,6 @@ public: void slotControlRatePermDownSmall(double); void slotControlRatePermUp(double); void slotControlRatePermUpSmall(double); - void slotControlRateTempDown(double); - void slotControlRateTempDownSmall(double); - void slotControlRateTempUp(double); - void slotControlRateTempUpSmall(double); void slotControlFastForward(double); void slotControlFastBack(double); @@ -153,11 +150,6 @@ public: ControlProxy* m_pSyncMode; ControlProxy* m_pSlipEnabled; - // The current rate ramping direction. Only holds the last button pressed. - int m_ePbCurrent; - // The rate ramping buttons which are currently being pressed. - int m_ePbPressed; - // This is true if we've already started to ramp the rate bool m_bTempStarted; // Set the Temporary Rate Change Mode -- cgit v1.2.3 From 345905f6da1bea0f804bf2b9ce68cbe5fc8d0025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 19 Dec 2018 22:01:41 +0100 Subject: Fix typo --- src/engine/sync/enginesync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/engine/sync/enginesync.cpp b/src/engine/sync/enginesync.cpp index 79b1c0b5c9..db3c80a6cb 100644 --- a/src/engine/sync/enginesync.cpp +++ b/src/engine/sync/enginesync.cpp @@ -123,7 +123,7 @@ void EngineSync::requestEnableSync(Syncable* pSyncable, bool bEnabled) { double otherDeckBpm = pOtherSyncable->getBpm(); if (otherDeckBpm > 0.0) { // If the requesting deck is playing, or we have already a - // non plaing deck found, only watch out for playing decks. + // non playing deck found, only watch out for playing decks. if ((foundTargetBpm || pSyncable->isPlaying()) && !pOtherSyncable->isPlaying()) { continue; -- cgit v1.2.3 From 2ba470b308e77081ad44301a893ddbf8a7ebbc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 19 Dec 2018 23:08:18 +0100 Subject: Fix the test for matching the orignal intention, and added an itermediates step to explicite test for lp1784185 --- src/test/enginesynctest.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/test/enginesynctest.cpp b/src/test/enginesynctest.cpp index 744ce56cb0..10a08eded7 100644 --- a/src/test/enginesynctest.cpp +++ b/src/test/enginesynctest.cpp @@ -1320,29 +1320,43 @@ TEST_F(EngineSyncTest, SyncPhaseToPlayingNonSyncDeck) { EXPECT_LT(0.8, ControlObject::getControl(ConfigKey(m_sInternalClockGroup, "beat_distance"))->get()); - // But if there is a third deck that is sync-enabled, we match that. ControlObject::getControl(ConfigKey(m_sGroup1, "play"))->set(0.0); + pButtonSyncEnabled1->set(0.0); + ControlObject::getControl(ConfigKey(m_sGroup1, "rate"))->set(getRateSliderValue(1.0)); + ControlObject::getControl(ConfigKey(m_sGroup2, "play"))->set(0.0); + pButtonSyncEnabled2->set(0.0); + ControlObject::getControl(ConfigKey(m_sGroup2, "rate"))->set(getRateSliderValue(1.0)); + + // But if there is a third deck that is sync-enabled, we match that. auto pButtonSyncEnabled3 = std::make_unique(m_sGroup3, "sync_enabled"); auto pFileBpm3 = std::make_unique(m_sGroup3, "file_bpm"); ControlObject::getControl(ConfigKey(m_sGroup3, "beat_distance"))->set(0.6); - ControlObject::getControl(ConfigKey(m_sGroup3, "rate"))->set(getRateSliderValue(1.0)); BeatsPointer pBeats3 = BeatFactory::makeBeatGrid(*m_pTrack3, 140, 0.0); m_pTrack3->setBeats(pBeats3); pFileBpm3->set(140.0); - pButtonSyncEnabled1->set(0.0); + // This will sync to the first deck here and not the second (lp1784185) + pButtonSyncEnabled3->set(1.0); + ProcessBuffer(); + EXPECT_FLOAT_EQ(130.0, ControlObject::getControl(ConfigKey(m_sGroup3, "bpm"))->get()); + // revert that + ControlObject::getControl(ConfigKey(m_sGroup3, "rate"))->set(getRateSliderValue(1.0)); ProcessBuffer(); + EXPECT_FLOAT_EQ(140.0, ControlObject::getControl(ConfigKey(m_sGroup3, "bpm"))->get()); + // now we have Deck 3 with 140 bpm and sync enabled + pButtonSyncEnabled1->set(1.0); - pButtonSyncEnabled3->set(1.0); + ProcessBuffer(); ControlObject::getControl(ConfigKey(m_sGroup3, "play"))->set(1.0); ControlObject::getControl(ConfigKey(m_sGroup2, "play"))->set(1.0); ControlObject::getControl(ConfigKey(m_sGroup1, "play"))->set(1.0); ProcessBuffer(); - EXPECT_FLOAT_EQ(100.0, + // We expect Deck 1 is Deck 3 bpm + EXPECT_FLOAT_EQ(140.0, ControlObject::getControl(ConfigKey(m_sInternalClockGroup, "bpm"))->get()); - EXPECT_FLOAT_EQ(100.0, ControlObject::getControl(ConfigKey(m_sGroup1, "bpm"))->get()); + EXPECT_FLOAT_EQ(140.0, ControlObject::getControl(ConfigKey(m_sGroup1, "bpm"))->get()); // The exact beat distance will be one buffer past .6, but this is good // enough to confirm that it worked. EXPECT_GT(0.7, ControlObject::getControl(ConfigKey(m_sGroup1, "beat_distance"))->get()); -- cgit v1.2.3 From d6434642463837ca8bf97d3d27249f8ee4bed0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Thu, 20 Dec 2018 07:23:12 +0100 Subject: cache playing state --- src/engine/sync/enginesync.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/engine/sync/enginesync.cpp b/src/engine/sync/enginesync.cpp index db3c80a6cb..fd8e689de9 100644 --- a/src/engine/sync/enginesync.cpp +++ b/src/engine/sync/enginesync.cpp @@ -120,23 +120,24 @@ void EngineSync::requestEnableSync(Syncable* pSyncable, bool bEnabled) { continue; } - double otherDeckBpm = pOtherSyncable->getBpm(); - if (otherDeckBpm > 0.0) { + double otherBpm = pOtherSyncable->getBpm(); + bool otherIsPlaying = pOtherSyncable->isPlaying(); + if (otherBpm > 0.0) { // If the requesting deck is playing, or we have already a // non playing deck found, only watch out for playing decks. if ((foundTargetBpm || pSyncable->isPlaying()) - && !pOtherSyncable->isPlaying()) { + && !otherIsPlaying) { continue; } foundTargetBpm = true; - targetBpm = otherDeckBpm; + targetBpm = otherBpm; targetBaseBpm = pOtherSyncable->getBaseBpm(); targetBeatDistance = pOtherSyncable->getBeatDistance(); // If the other deck is playing we stop looking // immediately. Otherwise continue looking for a playing // deck with bpm > 0.0. - if (pOtherSyncable->isPlaying()) { + if (otherIsPlaying) { foundPlayingDeck = true; break; } -- cgit v1.2.3 From a9b7c701951a0b6e19b029ae39fab8407cd215f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Thu, 20 Dec 2018 23:04:09 +0100 Subject: Fix inheritance --- src/engine/sync/basesyncablelistener.h | 20 +------------------- src/engine/sync/enginesync.h | 18 +++++++++--------- src/engine/sync/internalclock.cpp | 2 +- src/engine/sync/syncable.h | 16 ++++++++++++++-- 4 files changed, 25 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/engine/