From abcd88e20a85591b2e74500eb5768a3461892dae Mon Sep 17 00:00:00 2001 From: davidlmorris Date: Sun, 1 Sep 2024 08:14:32 +0800 Subject: [PATCH 1/4] AutoDj Crossfader to the center Option to set the Crossfader to the center as AutoDj starts a crossfade so the track starts at full volume. --- src/library/autodj/autodjprocessor.cpp | 28 +++++++++++++++++----- src/library/autodj/autodjprocessor.h | 2 ++ src/preferences/dialog/dlgprefautodj.cpp | 8 +++++++ src/preferences/dialog/dlgprefautodjdlg.ui | 23 +++++++++++++++++- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 165d2c6c4c9..74ed616c5eb 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -566,6 +566,8 @@ AutoDJProcessor::AutoDJError AutoDJProcessor::toggleAutoDJ(bool enable) { setCrossfader(1.0); } } + m_crossfaderStartCenter = m_pConfig->getValue(ConfigKey(kConfigKey, + QStringLiteral("center_xfader_when_starting_xfade"))); emitAutoDJStateChanged(m_eState); } else { // Disable Auto DJ m_pEnabledAutoDJ->setAndConfirm(0.0); @@ -832,6 +834,7 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes, double crossfaderTarget; if (m_eState == ADJ_LEFT_FADING) { crossfaderTarget = 1.0; + } else if (m_eState == ADJ_RIGHT_FADING) { crossfaderTarget = -1.0; } else { @@ -859,17 +862,29 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes, double transitionProgress = (thisPlayPosition - thisDeck->fadeBeginPos) / (thisDeck->fadeEndPos - thisDeck->fadeBeginPos); double transitionStep = transitionProgress - m_transitionProgress; + + if ((transitionProgress == 0.0) && + (m_crossfaderStartCenter)) + { + setCrossfader(0.0); // So we start at the mid point before we make any fader moves. + } if (transitionStep > 0.0) { // We have made progress. // Backward seeks pause the transitions; forward seeks speed up // the transitions. If there has been a seek beyond endPos, end // the transition immediately. - double remainingCrossfader = crossfaderTarget - currentCrossfader; - double adjustment = remainingCrossfader / - (1.0 - m_transitionProgress) * transitionStep; - // we move the crossfader linearly with - // movements in this track's play position. - setCrossfader(currentCrossfader + adjustment); + if ((m_crossfaderStartCenter) && + (transitionProgress <= ((thisDeck->fadeEndPos - thisDeck->fadeBeginPos)/2))) { + // We want the cross fader to remain in the middle. + setCrossfader(0.0); + } else { + double remainingCrossfader = crossfaderTarget - currentCrossfader; + double adjustment = remainingCrossfader / + (1.0 - m_transitionProgress) * transitionStep; + // we move the crossfader linearly with + // movements in this track's play position. + setCrossfader(currentCrossfader + adjustment); + } } m_transitionProgress = transitionProgress; // if we are at 1.0 here, we need an additional callback until the last @@ -1343,6 +1358,7 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck, } switch (m_transitionMode) { +// case TransitionMode::RadioFullIntroOutro: case TransitionMode::FullIntroOutro: { // Use the outro or intro length for the transition time, whichever is // shorter. Let the full outro and intro play; do not cut off any part diff --git a/src/library/autodj/autodjprocessor.h b/src/library/autodj/autodjprocessor.h index 600cf7bfb70..9ef9a9a2178 100644 --- a/src/library/autodj/autodjprocessor.h +++ b/src/library/autodj/autodjprocessor.h @@ -285,9 +285,11 @@ class AutoDJProcessor : public QObject { double m_transitionProgress; double m_transitionTime; // the desired value set by the user TransitionMode m_transitionMode; + bool m_crossfaderStartCenter; QList m_decks; + ControlProxy* m_pCOCrossfader; ControlProxy* m_pCOCrossfaderReverse; diff --git a/src/preferences/dialog/dlgprefautodj.cpp b/src/preferences/dialog/dlgprefautodj.cpp index 69e5069698c..c296600221c 100644 --- a/src/preferences/dialog/dlgprefautodj.cpp +++ b/src/preferences/dialog/dlgprefautodj.cpp @@ -61,6 +61,10 @@ void DlgPrefAutoDJ::slotUpdate() { // Re-center the crossfader instantly when AutoDJ is disabled CenterXfaderCheckBox->setChecked(m_pConfig->getValue( ConfigKey("[Auto DJ]", "center_xfader_when_disabling"), false)); + + CrossfaderStartCenterCheckBox->setChecked(m_pConfig->getValue( + ConfigKey("[Auto DJ]", "center_xfader_when_starting_xfade"), false)); + } void DlgPrefAutoDJ::slotApply() { @@ -81,8 +85,11 @@ void DlgPrefAutoDJ::slotApply() { m_pConfig->setValue(ConfigKey("[Auto DJ]", "center_xfader_when_disabling"), CenterXfaderCheckBox->isChecked()); + m_pConfig->setValue(ConfigKey("[Auto DJ]", "center_xfader_when_starting_xfade"), + CrossfaderStartCenterCheckBox->isChecked()); } + void DlgPrefAutoDJ::slotResetToDefaults() { MinimumAvailableSpinBox->setValue(20); @@ -96,6 +103,7 @@ void DlgPrefAutoDJ::slotResetToDefaults() { RandomQueueMinimumSpinBox->setValue(5); CenterXfaderCheckBox->setChecked(false); + CrossfaderStartCenterCheckBox->setChecked(false); } void DlgPrefAutoDJ::slotToggleRequeueIgnore(int buttonState) { diff --git a/src/preferences/dialog/dlgprefautodjdlg.ui b/src/preferences/dialog/dlgprefautodjdlg.ui index 7836ebf4c53..d0a841efa1d 100644 --- a/src/preferences/dialog/dlgprefautodjdlg.ui +++ b/src/preferences/dialog/dlgprefautodjdlg.ui @@ -284,6 +284,27 @@ + + + + + 0 + 0 + + + + Set the Crossfader to the center as AutoDj starts a crossfade so the track starts at full volume + + + CrossfaderStartCenterCheckBox + + + + + + + + @@ -298,7 +319,7 @@ - + From 8da30a150bb37de3d47e2d1bfddcdc9e918c6c59 Mon Sep 17 00:00:00 2001 From: davidlmorris Date: Mon, 2 Sep 2024 10:44:02 +0800 Subject: [PATCH 2/4] Update autodjprocessor.cpp --- src/library/autodj/autodjprocessor.cpp | 56 ++++++++++++-------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 74ed616c5eb..4d9d6bb4aa9 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -44,12 +44,9 @@ DeckAttributes::DeckAttributes(int index, m_sampleRate(group, "track_samplerate"), m_rateRatio(group, "rate_ratio"), m_pPlayer(pPlayer) { - connect(m_pPlayer, &BaseTrackPlayer::newTrackLoaded, - this, &DeckAttributes::slotTrackLoaded); - connect(m_pPlayer, &BaseTrackPlayer::loadingTrack, - this, &DeckAttributes::slotLoadingTrack); - connect(m_pPlayer, &BaseTrackPlayer::playerEmpty, - this, &DeckAttributes::slotPlayerEmpty); + connect(m_pPlayer, &BaseTrackPlayer::newTrackLoaded, this, &DeckAttributes::slotTrackLoaded); + connect(m_pPlayer, &BaseTrackPlayer::loadingTrack, this, &DeckAttributes::slotLoadingTrack); + connect(m_pPlayer, &BaseTrackPlayer::playerEmpty, this, &DeckAttributes::slotPlayerEmpty); m_playPos.connectValueChanged(this, &DeckAttributes::slotPlayPosChanged); m_play.connectValueChanged(this, &DeckAttributes::slotPlayChanged); m_introStartPos.connectValueChanged(this, &DeckAttributes::slotIntroStartPositionChanged); @@ -91,7 +88,7 @@ void DeckAttributes::slotTrackLoaded(TrackPointer pTrack) { } void DeckAttributes::slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack) { - //qDebug() << "DeckAttributes::slotLoadingTrack"; + // qDebug() << "DeckAttributes::slotLoadingTrack"; emit loadingTrack(this, pNewTrack, pOldTrack); } @@ -120,20 +117,17 @@ AutoDJProcessor::AutoDJProcessor( m_eState(ADJ_DISABLED), m_transitionProgress(0.0), m_transitionTime(kTransitionPreferenceDefault) { - m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollectionManager, - "mixxx.db.model.autodj"); + m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollectionManager, "mixxx.db.model.autodj"); m_pAutoDJTableModel->selectPlaylist(iAutoDJPlaylistId); m_pAutoDJTableModel->select(); m_pShufflePlaylist = new ControlPushButton( ConfigKey("[AutoDJ]", "shuffle_playlist")); - connect(m_pShufflePlaylist, &ControlPushButton::valueChanged, - this, &AutoDJProcessor::controlShuffle); + connect(m_pShufflePlaylist, &ControlPushButton::valueChanged, this, &AutoDJProcessor::controlShuffle); m_pSkipNext = new ControlPushButton( ConfigKey("[AutoDJ]", "skip_next")); - connect(m_pSkipNext, &ControlObject::valueChanged, - this, &AutoDJProcessor::controlSkipNext); + connect(m_pSkipNext, &ControlObject::valueChanged, this, &AutoDJProcessor::controlSkipNext); m_pAddRandomTrack = new ControlPushButton( ConfigKey("[AutoDJ]", "add_random_track")); @@ -144,8 +138,7 @@ AutoDJProcessor::AutoDJProcessor( m_pFadeNow = new ControlPushButton( ConfigKey("[AutoDJ]", "fade_now")); - connect(m_pFadeNow, &ControlObject::valueChanged, - this, &AutoDJProcessor::controlFadeNow); + connect(m_pFadeNow, &ControlObject::valueChanged, this, &AutoDJProcessor::controlFadeNow); m_pEnabledAutoDJ = new ControlPushButton( ConfigKey("[AutoDJ]", "enabled")); @@ -364,7 +357,7 @@ AutoDJProcessor::AutoDJError AutoDJProcessor::skipNext() { TrackId leftId = pLeftDeck->getLoadedTrack()->getId(); TrackId rightId = pRightDeck->getLoadedTrack()->getId(); if (nextId == leftId || nextId == rightId) { - // One of the playing tracks is still on top of playlist, remove second item + // One of the playing tracks is still on top of playlist, remove second item m_pAutoDJTableModel->removeTrack(m_pAutoDJTableModel->index(1, 0)); } else { m_pAutoDJTableModel->removeTrack(m_pAutoDJTableModel->index(0, 0)); @@ -662,7 +655,7 @@ void AutoDJProcessor::crossfaderChanged(double value) { } void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes, - double thisPlayPosition) { + double thisPlayPosition) { // qDebug() << "player" << pAttributes->group << "PositionChanged(" << value << ")"; if (m_eState == ADJ_DISABLED) { // nothing to do @@ -863,18 +856,17 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes, (thisDeck->fadeEndPos - thisDeck->fadeBeginPos); double transitionStep = transitionProgress - m_transitionProgress; - if ((transitionProgress == 0.0) && - (m_crossfaderStartCenter)) - { + if ((transitionProgress == 0.0) && + (m_crossfaderStartCenter)) { setCrossfader(0.0); // So we start at the mid point before we make any fader moves. - } + } if (transitionStep > 0.0) { // We have made progress. // Backward seeks pause the transitions; forward seeks speed up // the transitions. If there has been a seek beyond endPos, end // the transition immediately. if ((m_crossfaderStartCenter) && - (transitionProgress <= ((thisDeck->fadeEndPos - thisDeck->fadeBeginPos)/2))) { + (transitionProgress <= ((thisDeck->fadeEndPos - thisDeck->fadeBeginPos) / 2))) { // We want the cross fader to remain in the middle. setCrossfader(0.0); } else { @@ -898,7 +890,8 @@ TrackPointer AutoDJProcessor::getNextTrackFromQueue() { bool randomQueueEnabled = m_pConfig->getValue( ConfigKey("[Auto DJ]", "EnableRandomQueue")); int minAutoDJCrateTracks = m_pConfig->getValueString( - ConfigKey(kConfigKey, "RandomQueueMinimumAllowed")).toInt(); + ConfigKey(kConfigKey, "RandomQueueMinimumAllowed")) + .toInt(); int tracksToAdd = minAutoDJCrateTracks - m_pAutoDJTableModel->rowCount(); // In case we start off with < minimum tracks if (randomQueueEnabled && (tracksToAdd > 0)) { @@ -907,7 +900,7 @@ TrackPointer AutoDJProcessor::getNextTrackFromQueue() { while (true) { TrackPointer nextTrack = m_pAutoDJTableModel->getTrack( - m_pAutoDJTableModel->index(0, 0)); + m_pAutoDJTableModel->index(0, 0)); if (nextTrack) { if (nextTrack->getFileInfo().checkFileExists()) { @@ -986,9 +979,11 @@ bool AutoDJProcessor::removeTrackFromTopOfQueue(TrackPointer pTrack) { void AutoDJProcessor::maybeFillRandomTracks() { int minAutoDJCrateTracks = m_pConfig->getValueString( - ConfigKey(kConfigKey, "RandomQueueMinimumAllowed")).toInt(); + ConfigKey(kConfigKey, "RandomQueueMinimumAllowed")) + .toInt(); bool randomQueueEnabled = (((m_pConfig->getValueString( - ConfigKey("[Auto DJ]", "EnableRandomQueue")).toInt())) == 1); + ConfigKey("[Auto DJ]", "EnableRandomQueue")) + .toInt())) == 1); int tracksToAdd = minAutoDJCrateTracks - m_pAutoDJTableModel->rowCount(); if (randomQueueEnabled && (tracksToAdd > 0)) { @@ -1358,7 +1353,7 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck, } switch (m_transitionMode) { -// case TransitionMode::RadioFullIntroOutro: + // case TransitionMode::RadioFullIntroOutro: case TransitionMode::FullIntroOutro: { // Use the outro or intro length for the transition time, whichever is // shorter. Let the full outro and intro play; do not cut off any part @@ -1490,7 +1485,7 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck, startPoint = toDeckPositionSeconds; } useFixedFadeTime(pFromDeck, pToDeck, fromDeckPosition, fromDeckEndPosition, startPoint); - } + } } // These are expected to be a fraction of the track length. @@ -1621,7 +1616,8 @@ void AutoDJProcessor::playerTrackLoaded(DeckAttributes* pDeck, TrackPointer pTra } void AutoDJProcessor::playerLoadingTrack(DeckAttributes* pDeck, - TrackPointer pNewTrack, TrackPointer pOldTrack) { + TrackPointer pNewTrack, + TrackPointer pOldTrack) { if constexpr (sDebug) { qDebug() << this << "playerLoadingTrack" << pDeck->group << "new:" << (pNewTrack ? pNewTrack->getLocation() : "(null)") @@ -1691,7 +1687,7 @@ void AutoDJProcessor::setTransitionTime(int time) { // Update the transition time first. m_pConfig->set(ConfigKey(kConfigKey, kTransitionPreferenceName), - ConfigValue(time)); + ConfigValue(time)); m_transitionTime = time; // Then re-calculate fade thresholds for the decks. From e56ebe87eec0450f9a31c3f67f5e216092731a15 Mon Sep 17 00:00:00 2001 From: davidlmorris Date: Wed, 4 Sep 2024 08:45:45 +0800 Subject: [PATCH 3/4] Update src/library/autodj/autodjprocessor.cpp Co-authored-by: ronso0 --- src/library/autodj/autodjprocessor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 4d9d6bb4aa9..7b9bad22fc1 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -560,7 +560,8 @@ AutoDJProcessor::AutoDJError AutoDJProcessor::toggleAutoDJ(bool enable) { } } m_crossfaderStartCenter = m_pConfig->getValue(ConfigKey(kConfigKey, - QStringLiteral("center_xfader_when_starting_xfade"))); + QStringLiteral("center_xfader_when_starting_xfade")), + false); emitAutoDJStateChanged(m_eState); } else { // Disable Auto DJ m_pEnabledAutoDJ->setAndConfirm(0.0); From bc9e06813038c7ceba927dd80f2ec33bd07b2eb0 Mon Sep 17 00:00:00 2001 From: davidlmorris Date: Wed, 4 Sep 2024 08:58:23 +0800 Subject: [PATCH 4/4] Update src/library/autodj/autodjprocessor.cpp Co-authored-by: ronso0 --- src/library/autodj/autodjprocessor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 7b9bad22fc1..68312e1e467 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -868,7 +868,9 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes, // the transition immediately. if ((m_crossfaderStartCenter) && (transitionProgress <= ((thisDeck->fadeEndPos - thisDeck->fadeBeginPos) / 2))) { - // We want the cross fader to remain in the middle. + // For the first half of the transition we want the "from" deck + // to play at full volume like with a full crossfade transition, + // hence we keep the crossfader in the middle. setCrossfader(0.0); } else { double remainingCrossfader = crossfaderTarget - currentCrossfader;