diff options
-rw-r--r-- | .gitattributes | 26 | ||||
-rw-r--r-- | build/debian/changelog | 6 | ||||
-rw-r--r-- | src/controllers/controlpickermenu.cpp | 6 | ||||
-rw-r--r-- | src/engine/controls/bpmcontrol.cpp | 42 | ||||
-rw-r--r-- | src/engine/controls/bpmcontrol.h | 3 | ||||
-rw-r--r-- | src/engine/controls/ratecontrol.cpp | 357 | ||||
-rw-r--r-- | src/engine/controls/ratecontrol.h | 65 | ||||
-rw-r--r-- | src/engine/enginebuffer.h | 1 | ||||
-rw-r--r-- | src/engine/enginemaster.cpp | 11 | ||||
-rw-r--r-- | src/engine/enginemaster.h | 3 | ||||
-rw-r--r-- | src/engine/sync/basesyncablelistener.cpp | 23 | ||||
-rw-r--r-- | src/engine/sync/basesyncablelistener.h | 20 | ||||
-rw-r--r-- | src/engine/sync/enginesync.cpp | 83 | ||||
-rw-r--r-- | src/engine/sync/enginesync.h | 19 | ||||
-rw-r--r-- | src/engine/sync/internalclock.cpp | 3 | ||||
-rw-r--r-- | src/engine/sync/syncable.h | 26 | ||||
-rw-r--r-- | src/engine/sync/synccontrol.cpp | 54 | ||||
-rw-r--r-- | src/engine/sync/synccontrol.h | 2 | ||||
-rw-r--r-- | src/mixer/basetrackplayer.cpp | 12 | ||||
-rw-r--r-- | src/mixer/basetrackplayer.h | 2 | ||||
-rw-r--r-- | src/test/enginebuffertest.cpp | 69 | ||||
-rw-r--r-- | src/test/enginesynctest.cpp | 104 |
22 files changed, 515 insertions, 422 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..0076522bf9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,26 @@ +# Execute the following command in your local project +# directory to exclude localization files from merges +# across branches: +# +# $ git config --global merge.ours.driver true +# +# This command sets a shell script that is used for all +# merge=ours files. In this case the script "true" does +# not touch anything, just returns successful. +# +# Background: Localization files from external sources like +# Transifex must not be merged between release branches and +# should be ignore while merging! Instead those files are +# updated by re-importing them manually from the external +# source. This workflow is supported by configuring the merge +# strategy for the local Git repository appropriately, i.e. +# by excluding those files from merging and always keeping the +# files from the current/target branch (= "ours"). + +# Exclude Transifex files from merging +/res/translations/*.ts merge=ours +/res/translations/*.qm merge=ours + +# Exclude WiX translations from merging +/build/wix/Localization/po/*.po merge=ours +/build/wix/Localization/po/*.wxl merge=ours diff --git a/build/debian/changelog b/build/debian/changelog index 7be287a008..435098f0d8 100644 --- a/build/debian/changelog +++ b/build/debian/changelog @@ -1,3 +1,9 @@ +mixxx (2.1.6-0ubuntu1) bionic; urgency=medium + + * New upstream release + + -- Daniel <daniel@daniel-530U3C-530U4C-532U3C> Sun, 23 Dec 2018 11:01:23 +0100 + mixxx (2.1.4-0ubuntu1) bionic; urgency=medium * New upstream release. diff --git a/src/controllers/controlpickermenu.cpp b/src/controllers/controlpickermenu.cpp index a989d3af43..16e41e8952 100644 --- a/src/controllers/controlpickermenu.cpp +++ b/src/controllers/controlpickermenu.cpp @@ -457,6 +457,12 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent) tr("Quick Effect Super Knob (control linked effect parameters)"), tr("Quick Effect"), quickEffectMenu); + addPrefixedControl(QString("[QuickEffectRack1_[Channel%1]_Effect1]").arg(i), + "enabled", + tr("Deck %1 Quick Effect Enable Button").arg(i), + tr("Quick Effect Enable Button"), + tr("Quick Effect"), + quickEffectMenu); } const int kNumEffectRacks = 1; diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp index 0ff25ec230..328ca718b6 100644 --- a/src/engine/controls/bpmcontrol.cpp +++ b/src/engine/controls/bpmcontrol.cpp @@ -148,11 +148,11 @@ double BpmControl::getBpm() const { return m_pEngineBpm->get(); } -void BpmControl::slotFileBpmChanged(double bpm) { - Q_UNUSED(bpm); +void BpmControl::slotFileBpmChanged(double file_bpm) { // Adjust the file-bpm with the current setting of the rate to get the // engine BPM. We only do this for SYNC_NONE decks because EngineSync will // set our BPM if the file BPM changes. See SyncControl::fileBpmChanged(). + //qDebug() << "BpmControl::slotFileBpmChanged" << file_bpm; BeatsPointer pBeats = m_pBeats; if (pBeats) { const double beats_bpm = @@ -161,13 +161,10 @@ void BpmControl::slotFileBpmChanged(double bpm) { if (beats_bpm != -1) { m_pLocalBpm->set(beats_bpm); } else { - m_pLocalBpm->set(bpm); + m_pLocalBpm->set(file_bpm); } } else { - m_pLocalBpm->set(bpm); - } - if (getSyncMode() == SYNC_NONE) { - slotUpdateEngineBpm(); + m_pLocalBpm->set(file_bpm); } resetSyncAdjustment(); } @@ -271,8 +268,8 @@ bool BpmControl::syncTempo() { double fOtherBpm = pOtherEngineBuffer->getBpm(); double fOtherLocalBpm = pOtherEngineBuffer->getLocalBpm(); - //qDebug() << "this" << "bpm" << fThisBpm << "filebpm" << fThisFileBpm; - //qDebug() << "other" << "bpm" << fOtherBpm << "filebpm" << fOtherFileBpm; + //qDebug() << "this" << "bpm" << fThisBpm << "filebpm" << fThisLocalBpm; + //qDebug() << "other" << "bpm" << fOtherBpm << "filebpm" << fOtherLocalBpm; //////////////////////////////////////////////////////////////////////////// // Rough proof of how syncing works -- rryan 3/2011 @@ -587,8 +584,11 @@ double BpmControl::getNearestPositionInPhase( if (!pBeats) { return dThisPosition; } + + SyncMode syncMode = getSyncMode(); + // Master buffer is always in sync! - if (getSyncMode() == SYNC_MASTER) { + if (syncMode == SYNC_MASTER) { return dThisPosition; } @@ -614,24 +614,26 @@ double BpmControl::getNearestPositionInPhase( } double dOtherBeatFraction; - if (getSyncMode() == SYNC_FOLLOWER) { + if (syncMode == SYNC_FOLLOWER) { // If we're a follower, it's easy to get the other beat fraction dOtherBeatFraction = m_dSyncTargetBeatDistance.getValue(); } 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(); @@ -830,7 +832,7 @@ double BpmControl::updateLocalBpm() { double BpmControl::updateBeatDistance() { double beat_distance = getBeatDistance(getSampleOfTrack().current); m_pThisBeatDistance->set(beat_distance); - if (getSyncMode() == SYNC_NONE) { + if (!isSynchronized()) { m_dUserOffset.setValue(0.0); } return beat_distance; diff --git a/src/engine/controls/bpmcontrol.h b/src/engine/controls/bpmcontrol.h index b802e8f353..15291134b1 100644 --- a/src/engine/controls/bpmcontrol.h +++ b/src/engine/controls/bpmcontrol.h @@ -93,6 +93,9 @@ class BpmControl : public EngineControl { SyncMode getSyncMode() const { return syncModeFromDouble(m_pSyncMode->get()); } + inline bool isSynchronized() const { + return toSynchronized(getSyncMode()); + } bool syncTempo(); double calcSyncAdjustment(double my_percentage, bool userTweakingSync); double calcRateRatio() const; diff --git a/src/engine/controls/ratecontrol.cpp b/src/engine/controls/ratecontrol.cpp index e51ec0a69d..9faa6422a5 100644 --- a/src/engine/controls/ratecontrol.cpp +++ b/src/engine/controls/ratecontrol.cpp @@ -32,12 +32,9 @@ RateControl::RateControl(QString group, UserSettingsPointer pConfig) : EngineControl(group, pConfig), m_pBpmControl(NULL), - m_ePbCurrent(0), - m_ePbPressed(0), m_bTempStarted(false), - m_dRateTemp(0.0), - m_eRampBackMode(RATERAMP_RAMPBACK_NONE), - m_dRateTempRampbackChange(0.0) { + m_tempRateRatio(0.0), + m_dRateTempRampChange(0.0) { m_pScratchController = new PositionScratchController(group); m_pRateDir = new ControlObject(ConfigKey(group, "rate_dir")); @@ -81,54 +78,39 @@ 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, &ControlObject::valueChanged, + connect(m_pButtonRatePermDown, &ControlObject::valueChanged, this, &RateControl::slotControlRatePermDown, Qt::DirectConnection); - buttonRatePermDownSmall = + m_pButtonRatePermDownSmall = new ControlPushButton(ConfigKey(group,"rate_perm_down_small")); - connect(buttonRatePermDownSmall, &ControlObject::valueChanged, + connect(m_pButtonRatePermDownSmall, &ControlObject::valueChanged, this, &RateControl::slotControlRatePermDownSmall, Qt::DirectConnection); - buttonRatePermUp = + m_pButtonRatePermUp = new ControlPushButton(ConfigKey(group,"rate_perm_up")); - connect(buttonRatePermUp, &ControlObject::valueChanged, + connect(m_pButtonRatePermUp, &ControlObject::valueChanged, this, &RateControl::slotControlRatePermUp, Qt::DirectConnection); - buttonRatePermUpSmall = + m_pButtonRatePermUpSmall = new ControlPushButton(ConfigKey(group,"rate_perm_up_small")); - connect(buttonRatePermUpSmall, &ControlObject::valueChanged, + connect(m_pButtonRatePermUpSmall, &ControlObject::valueChanged, this, &RateControl::slotControlRatePermUpSmall, Qt::DirectConnection); // Temporary rate-change buttons - buttonRateTempDown = + m_pButtonRateTempDown = new ControlPushButton(ConfigKey(group,"rate_temp_down")); - connect(buttonRateTempDown, &ControlObject::valueChanged, - this, &RateControl::slotControlRateTempDown, - Qt::DirectConnection); - - buttonRateTempDownSmall = + m_pButtonRateTempDownSmall = new ControlPushButton(ConfigKey(group,"rate_temp_down_small")); - connect(buttonRateTempDownSmall, &ControlObject::valueChanged, - this, &RateControl::slotControlRateTempDownSmall, - Qt::DirectConnection); - - buttonRateTempUp = + m_pButtonRateTempUp = new ControlPushButton(ConfigKey(group,"rate_temp_up")); - connect(buttonRateTempUp, &ControlObject::valueChanged, - this, &RateControl::slotControlRateTempUp, - Qt::DirectConnection); - - buttonRateTempUpSmall = + m_pButtonRateTempUpSmall = new ControlPushButton(ConfigKey(group,"rate_temp_up_small")); - connect(buttonRateTempUpSmall, &ControlObject::valueChanged, - this, &RateControl::slotControlRateTempUpSmall, - Qt::DirectConnection); // We need the sample rate so we can guesstimate something close // what latency is. @@ -184,14 +166,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; @@ -280,111 +262,53 @@ 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.getValue() / (100 * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeCoarse.getValue() / (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.getValue() / (100. * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeFine.getValue() / (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.getValue() / (100. * m_pRateRange->get())); + m_pRateDir->get() * m_dPermanentRateChangeCoarse.getValue() / (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.getValue() / (100. * m_pRateRange->get())); -} - -void RateControl::slotControlRateTempDown(double) -{ - // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempDown->get() && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) - { - m_ePbPressed |= RateControl::RATERAMP_DOWN; - m_ePbCurrent = RateControl::RATERAMP_DOWN; - } - else if (!buttonRateTempDown->get()) - { - m_ePbPressed &= ~RateControl::RATERAMP_DOWN; - m_ePbCurrent = m_ePbPressed; - } -} - -void RateControl::slotControlRateTempDownSmall(double) -{ - // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempDownSmall->get() && !(m_ePbPressed & RateControl::RATERAMP_DOWN)) - { - m_ePbPressed |= RateControl::RATERAMP_DOWN; - m_ePbCurrent = RateControl::RATERAMP_DOWN; - } - else if (!buttonRateTempDownSmall->get()) - { - m_ePbPressed &= ~RateControl::RATERAMP_DOWN; - m_ePbCurrent = m_ePbPressed; - } -} - -void RateControl::slotControlRateTempUp(double) -{ - // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempUp->get() && !(m_ePbPressed & RateControl::RATERAMP_UP)) - { - m_ePbPressed |= RateControl::RATERAMP_UP; - m_ePbCurrent = RateControl::RATERAMP_UP; - } - else if (!buttonRateTempUp->get()) - { - m_ePbPressed &= ~RateControl::RATERAMP_UP; - m_ePbCurrent = m_ePbPressed; - } -} - -void RateControl::slotControlRateTempUpSmall(double) { - // Set the state of the Temporary button. Logic is handled in ::process() - if (buttonRateTempUpSmall->get() && !(m_ePbPressed & RateControl::RATERAMP_UP)){ - m_ePbPressed |= RateControl::RATERAMP_UP; - m_ePbCurrent = RateControl::RATERAMP_UP; - } else if (!buttonRateTempUpSmall->get()) { - m_ePbPressed &= ~RateControl::RATERAMP_UP; - m_ePbCurrent = m_ePbPressed; + m_pRateDir->get() * m_dPermanentRateChangeFine.getValue() / (100. * m_pRateRange->get())); } } @@ -427,6 +351,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) { @@ -477,7 +404,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; @@ -523,134 +451,101 @@ double RateControl::calculateSpeed(double baserate, double speed, bool paused, return rate; } -void RateControl::process(const double rate, - const double currentSample, - const int bufferSamples) -{ - Q_UNUSED(rate); - Q_UNUSED(currentSample); - /* - * 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. - */ - - double latrate = ((double)bufferSamples / (double)m_pSampleRate->get()); - - - if ((m_ePbPressed) && (!m_bTempStarted)) { - m_bTempStarted = true; +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. + + 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 (rampDirection != RampDirection::None) { 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; + 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); + } } - - double change = m_pRateDir->get() * m_dTemporaryRateChangeCoarse.getValue() / - (100. * range); - double csmall = m_pRateDir->get() * m_dTemporaryRateChangeFine.getValue() / - (100. * range); - - if (buttonRateTempUp->get()) - addRateTemp(change); - else if (buttonRateTempDown->get()) - subRateTemp(change); - else if (buttonRateTempUpSmall->get()) - addRateTemp(csmall); - else if (buttonRateTempDownSmall->get()) - subRateTemp(csmall); } else if (m_eRateRampMode == RampMode::Linear) { - m_dTemporaryRateChangeCoarse.setValue( - ((double)latrate / ((double)m_iRateRampSensitivity / 100.))); - - if (m_eRampBackMode == RATERAMP_RAMPBACK_PERIOD) - m_dRateTempRampbackChange = 0.0; - } - - } + 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_eRateRampMode == RampMode::Linear) { - if (m_ePbCurrent) { - // apply ramped pitchbending - if (m_ePbCurrent == RateControl::RATERAMP_UP) { - addRateTemp(m_dTemporaryRateChangeCoarse.getValue()); - } else if (m_ePbCurrent == RateControl::RATERAMP_DOWN) { - subRateTemp(m_dTemporaryRateChangeCoarse.getValue()); - } - } else if ((m_bTempStarted) - || ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) - && (m_dRateTemp != 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_dRateTemp / period); - } else if ((m_eRampBackMode != RATERAMP_RAMPBACK_NONE) - && (m_dRateTempRampbackChange == 0.0)) { - if (fabs(m_dRateTemp) < m_dRateTempRampbackChange) { - resetRateTemp(); - } else if (m_dRateTemp > 0) { - subRateTemp(m_dRateTempRampbackChange); - } else { - addRateTemp(m_dRateTempRampbackChange); + 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 { - resetRateTemp(); } } - } else if ((m_eRateRampMode == RampMode::Stepping) && (m_bTempStarted)) { - if (!m_ePbCurrent) { - m_bTempStarted = false; - resetRateTemp(); - } + } else if (m_bTempStarted) { + m_bTempStarted = false; + resetRateTemp(); } } double RateControl::getTempRate() { - return (m_pRateDir->get() * (m_dRateTemp * m_pRateRange->get())); -} - -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; + // qDebug() << m_tempRateRatio; + return m_tempRateRatio; +} + +void RateControl::setRateTemp(double v) { + 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/controls/ratecontrol.h b/src/engine/controls/ratecontrol.h index 97ea85c5b8..8bbc7acb55 100644 --- a/src/engine/controls/ratecontrol.h +++ b/src/engine/controls/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 { @@ -48,23 +49,8 @@ public: Linear = 1 // pitch moves up/down in a progressively 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 progressive 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); - // 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 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. @@ -99,14 +85,11 @@ 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); private: + void processTempRate(const int bufferSamples); double getJogFactor() const; double getWheelFactor() const; SyncMode getSyncMode() const; @@ -128,18 +111,18 @@ public: static ControlValueAtomic<double> m_dPermanentRateChangeCoarse; static ControlValueAtomic<double> m_dPermanentRateChangeFine; - ControlPushButton *buttonRateTempDown; - ControlPushButton *buttonRateTempDownSmall; - ControlPushButton *buttonRateTempUp; - ControlPushButton *buttonRateTempUpSmall; + ControlPushButton* m_pButtonRateTempDown; + ControlPushButton* m_pButtonRateTempDownSmall; + ControlPushButton* m_pButtonRateTempUp; + ControlPushButton* m_pButtonRateTempUpSmall; - ControlPushButton *buttonRatePermDown; - ControlPushButton *buttonRatePermDownSmall; - ControlPushButton *buttonRatePermUp; - ControlPushButton *buttonRatePermUpSmall; + ControlPushButton* m_pButtonRatePermDown; + ControlPushButton* m_pButtonRatePermDownSmall; + ControlPushButton* m_pButtonRatePermUp; + ControlPushButton* m_pButtonRatePermUpSmall; - ControlObject *m_pRateDir; - ControlObject *m_pRateRange; + ControlObject* m_pRateDir; + ControlObject* m_pRateRange; ControlPotmeter* m_pRateSlider; ControlPotmeter* m_pRateSearch; ControlPushButton* m_pReverseButton; @@ -167,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 @@ -183,10 +161,9 @@ 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; - enum RATERAMP_RAMPBACK_MODE m_eRampBackMode; - // Return speed for temporary rate change - double m_dRateTempRampbackChange; + double m_tempRateRatio; + // Speed for temporary rate change + double m_dRateTempRampChange; }; #endif /* RATECONTROL_H */ diff --git a/src/engine/enginebuffer.h b/src/engine/enginebuffer.h index 36a6975880..4b0a4f4f16 100644 --- a/src/engine/enginebuffer.h +++ b/src/engine/enginebuffer.h @@ -358,6 +358,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/enginemaster.cpp b/src/engine/enginemaster.cpp index c0a94426f4..8d2afe2829 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 @@ -449,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. |