Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix undesired jump-cuts in auto DJ #4693

Merged
merged 7 commits into from
Mar 21, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 68 additions & 50 deletions src/library/autodj/autodjprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const double kKeepPosition = -1.0;

const mixxx::audio::ChannelCount kChannelCount = mixxx::kEngineChannelCount;

static const bool sDebug = false;
constexpr bool sDebug = false;
} // anonymous namespace

DeckAttributes::DeckAttributes(int index,
Expand Down Expand Up @@ -621,11 +621,6 @@ void AutoDJProcessor::crossfaderChanged(double value) {

void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes,
double thisPlayPosition) {
if (sDebug) {
//qDebug() << this << "playerPositionChanged" << pAttributes->group
// << thisPlayPosition;
}

// Auto-DJ needs at least two decks
VERIFY_OR_DEBUG_ASSERT(m_decks.length() > 1) {
return;
Expand Down Expand Up @@ -697,6 +692,10 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes,
} else {
// At least right deck is playing
// Set crossfade thresholds for right deck.
if constexpr (sDebug) {
qDebug() << this << "playerPositionChanged"
<< "right deck playing";
}
calculateTransition(rightDeck, leftDeck, false);
}
emitAutoDJStateChanged(m_eState);
Expand Down Expand Up @@ -743,6 +742,10 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes,
// recalculated here.
// Don't adjust transition when reaching the end. In this case it is
// always stopped.
if constexpr (sDebug) {
qDebug() << this << "playerPositionChanged"
<< "cueing seek";
}
calculateTransition(otherDeck, thisDeck, false);
} else if (thisDeck->isRepeat()) {
// repeat pauses auto DJ
Expand Down Expand Up @@ -778,6 +781,12 @@ void AutoDJProcessor::playerPositionChanged(DeckAttributes* pAttributes,
// that was "on deck" from the top of the queue.
// Note: This is a DB call and takes long.
removeLoadedTrackFromTopOfQueue(*otherDeck);
} else {
if constexpr (sDebug) {
qDebug() << this << "playerPositionChanged()"
<< pAttributes->group << thisPlayPosition
<< "but not playing";
}
}
}

Expand Down Expand Up @@ -935,7 +944,7 @@ void AutoDJProcessor::maybeFillRandomTracks() {
}

void AutoDJProcessor::playerPlayChanged(DeckAttributes* thisDeck, bool playing) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerPlayChanged" << thisDeck->group << playing;
}

Expand All @@ -956,40 +965,42 @@ void AutoDJProcessor::playerPlayChanged(DeckAttributes* thisDeck, bool playing)
return;
}

if (playing && !otherDeck->isPlaying()) {
// In case both decks were stopped and now this one just started, make
// this deck the "from deck".
calculateTransition(thisDeck, getOtherDeck(thisDeck), false);
}

// If the user manually pressed play on the "to deck" before fading, for
// example to adjust the intro/outro cues, and lets the deck play until the
// end, seek back to the start point instead of keeping the deck stopped at
// the end.
if (!playing && thisDeck->playPosition() >= 1.0 && !thisDeck->isFromDeck) {
// toDeck has stopped at the end. Recalculate the transition, because
// it has been done from a now irrelevant previous position.
// This forces the other deck to be the fromDeck.
thisDeck->startPos = kKeepPosition;
calculateTransition(otherDeck, thisDeck, true);
if (thisDeck->startPos != kKeepPosition) {
// Note: this seek will trigger the playerPositionChanged slot
// which may calls the calculateTransition() again without seek = true;
thisDeck->setPlayPosition(thisDeck->startPos);
if (playing) {
if (!otherDeck->isPlaying()) {
// In case both decks were stopped and now this one just started, make
// this deck the "from deck".
calculateTransition(thisDeck, getOtherDeck(thisDeck), false);
}
} else {
// Deck paused
// This may happen if the user has previously pressed play on the "to deck"
// before fading, for example to adjust the intro/outro cues, and lets the
// deck play until the end, seek back to the start point instead of keeping
if (thisDeck->playPosition() >= 1.0 && !thisDeck->isFromDeck) {
// toDeck has stopped at the end. Recalculate the transition, because
// it has been done from a now irrelevant previous position.
// This forces the other deck to be the fromDeck.
thisDeck->startPos = kKeepPosition;
calculateTransition(otherDeck, thisDeck, true);
if (thisDeck->startPos != kKeepPosition) {
// Note: this seek will trigger the playerPositionChanged slot
// which may calls the calculateTransition() again without seek = true;
thisDeck->setPlayPosition(thisDeck->startPos);
}
}
}
}

void AutoDJProcessor::playerIntroStartChanged(DeckAttributes* pAttributes, double position) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerIntroStartChanged" << pAttributes->group << position;
}
// nothing to do, because we want not to re-cue the toDeck and the from
// Deck has already passed the intro
}

void AutoDJProcessor::playerIntroEndChanged(DeckAttributes* pAttributes, double position) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerIntroEndChanged" << pAttributes->group << position;
}

Expand All @@ -1010,7 +1021,7 @@ void AutoDJProcessor::playerIntroEndChanged(DeckAttributes* pAttributes, double
}

void AutoDJProcessor::playerOutroStartChanged(DeckAttributes* pAttributes, double position) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerOutroStartChanged" << pAttributes->group << position;
}

Expand All @@ -1027,7 +1038,7 @@ void AutoDJProcessor::playerOutroStartChanged(DeckAttributes* pAttributes, doubl
}

void AutoDJProcessor::playerOutroEndChanged(DeckAttributes* pAttributes, double position) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerOutroEndChanged" << pAttributes->group << position;
}

Expand Down Expand Up @@ -1137,7 +1148,7 @@ double AutoDJProcessor::samplePositionToSeconds(double samplePosition, DeckAttri
void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
DeckAttributes* pToDeck,
bool seekToStartPoint) {
if (pFromDeck == nullptr || pToDeck == nullptr) {
VERIFY_OR_DEBUG_ASSERT(pFromDeck && pToDeck) {
return;
}
if (pFromDeck->loading || pToDeck->loading) {
Expand All @@ -1146,8 +1157,6 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
return;
}

qDebug() << "player" << pFromDeck->group << "calculateTransition()";

// We require ADJ_IDLE to prevent changing the thresholds in the middle of a
// fade.
VERIFY_OR_DEBUG_ASSERT(m_eState == ADJ_IDLE) {
Expand All @@ -1169,7 +1178,7 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
pToDeck->startPos = kKeepPosition;
return;
}
if (toDeckDuration <= 0) {
VERIFY_OR_DEBUG_ASSERT(toDeckDuration > 0) {
// Playing Track has no duration. This should not happen, because short
// tracks are skipped after load.
loadNextTrackFromQueue(*pToDeck, false);
Expand Down Expand Up @@ -1216,15 +1225,20 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
introStart = toDeckPositionSeconds;
}

double introEnd = getIntroEndSecond(pToDeck);
if (introEnd < introStart) {
// introEnd is invalid. Assume a zero length intro.
// The introStart is automatically placed by AnalyzerSilence, so use
// that as a fallback if the user has not placed introEnd.
introEnd = introStart;
double introLength = 0;
const double introEndSample = pToDeck->introEndPosition();
if (introEndSample != Cue::kNoPosition) {
const double introEnd = samplePositionToSeconds(introEndSample, pToDeck);
if (introStart < introEnd) {
introLength = introEnd - introStart;
}
}

double introLength = introEnd - introStart;
if constexpr (sDebug) {
qDebug() << this << "calculateTransition"
<< "introLength" << introLength
<< "outroLength" << outroLength;
}

switch (m_transitionMode) {
case TransitionMode::FullIntroOutro: {
Expand Down Expand Up @@ -1370,7 +1384,7 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
pFromDeck->fadeBeginPos = 1;
}

if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "calculateTransition" << pFromDeck->group
<< pFromDeck->fadeBeginPos << pFromDeck->fadeEndPos
<< pToDeck->startPos;
Expand Down Expand Up @@ -1421,7 +1435,7 @@ void AutoDJProcessor::useFixedFadeTime(
}

void AutoDJProcessor::playerTrackLoaded(DeckAttributes* pDeck, TrackPointer pTrack) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerTrackLoaded" << pDeck->group
<< (pTrack ? pTrack->getLocation() : "(null)");
}
Expand Down Expand Up @@ -1459,17 +1473,21 @@ void AutoDJProcessor::playerTrackLoaded(DeckAttributes* pDeck, TrackPointer pTra
// repeat a probably missed update
playerPositionChanged(fromDeck, 1.0);
}
} else {
if constexpr (sDebug) {
qDebug() << this << "playerTrackLoaded()" << pDeck->group << "but not a toDeck";
}
}
}
}
}

void AutoDJProcessor::playerLoadingTrack(DeckAttributes* pDeck,
TrackPointer pNewTrack, TrackPointer pOldTrack) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerLoadingTrack" << pDeck->group
<< "new:"<< (pNewTrack ? pNewTrack->getLocation() : "(null)")
<< "old:"<< (pOldTrack ? pOldTrack->getLocation() : "(null)");
<< "new:" << (pNewTrack ? pNewTrack->getLocation() : "(null)")
<< "old:" << (pOldTrack ? pOldTrack->getLocation() : "(null)");
}

pDeck->loading = true;
Expand All @@ -1495,7 +1513,7 @@ void AutoDJProcessor::playerLoadingTrack(DeckAttributes* pDeck,
}

void AutoDJProcessor::playerEmpty(DeckAttributes* pDeck) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerEmpty()" << pDeck->group;
}

Expand All @@ -1512,7 +1530,7 @@ void AutoDJProcessor::playerEmpty(DeckAttributes* pDeck) {
}

void AutoDJProcessor::playerRateChanged(DeckAttributes* pAttributes) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "playerRateChanged" << pAttributes->group;
}

Expand All @@ -1529,7 +1547,7 @@ void AutoDJProcessor::playerRateChanged(DeckAttributes* pAttributes) {
}

void AutoDJProcessor::setTransitionTime(int time) {
if (sDebug) {
if constexpr (sDebug) {
qDebug() << this << "setTransitionTime" << time;
}

Expand Down