diff options
Diffstat (limited to 'src/engine/controls/clockcontrol.cpp')
-rw-r--r-- | src/engine/controls/clockcontrol.cpp | 179 |
1 files changed, 108 insertions, 71 deletions
diff --git a/src/engine/controls/clockcontrol.cpp b/src/engine/controls/clockcontrol.cpp index 10218cec94..6622685689 100644 --- a/src/engine/controls/clockcontrol.cpp +++ b/src/engine/controls/clockcontrol.cpp @@ -17,6 +17,9 @@ ClockControl::ClockControl(const QString& group, UserSettingsPointer pConfig) m_InternalState = StateMachine::outsideIndicationArea; m_NextBeatSamples = 0; m_blinkIntervalSamples = 0; + m_pLoopEnabled = new ControlProxy(group, "loop_enabled", this); + m_pLoopStartPosition = new ControlProxy(group, "loop_start_position", this); + m_pLoopEndPosition = new ControlProxy(group, "loop_end_position", this); } ClockControl::~ClockControl() { @@ -47,7 +50,8 @@ void ClockControl::process(const double dRate, } void ClockControl::updateIndicators(const double dRate, - const double currentSample) { + const double currentSample, + const double sampleRate) { /* This method sets the control beat_active is set to the following values: * +1.0 --> Forward playing, set at the beat and set back to 0.0 at 20% of beat distance * 0.0 --> No beat indication (ouside 20% area or play direction changed while indication was on) @@ -56,94 +60,127 @@ void ClockControl::updateIndicators(const double dRate, // TODO(XXX) should this be customizable, or latency dependent? const double kBlinkInterval = 0.20; // LED is on 20% of the beat period + const double kStandStillTolerance = + 0.0025; // (seconds) Minimum change, to he last evaluated position - if ((currentSample == m_lastEvaluatedSample) || + if (((currentSample <= (m_lastEvaluatedSample + kStandStillTolerance * sampleRate)) && + (currentSample >= (m_lastEvaluatedSample - kStandStillTolerance * sampleRate))) || (dRate == 0.0)) { - return; // No position change (e.g. deck stopped) -> No indicator update needed + return; // No position change since last indicator update (e.g. deck stopped) -> No indicator update needed } + double prevIndicatorSamples; + double nextIndicatorSamples; + mixxx::BeatsPointer pBeats = m_pBeats; if (pBeats) { if ((currentSample >= m_NextBeatSamples) || (currentSample <= m_PrevBeatSamples)) { - /*qDebug() << "### findPrevNextBeats ### " << - " currentSample: " << currentSample << - " m_lastEvaluatedSample: " << m_lastEvaluatedSample - << " m_PrevBeatSamples: " << m_PrevBeatSamples - << " m_NextBeatSamples: " << m_NextBeatSamples;*/ - pBeats->findPrevNextBeats(currentSample, &m_PrevBeatSamples, &m_NextBeatSamples, true); // Precise compare without tolerance needed + } + } else { + m_PrevBeatSamples = -1; + m_NextBeatSamples = -1; + } - m_blinkIntervalSamples = (m_NextBeatSamples - m_PrevBeatSamples) * kBlinkInterval; + // Loops need special handling + if (m_pLoopEnabled->toBool()) { + const double loop_start_position = m_pLoopStartPosition->get(); + const double loop_end_position = m_pLoopEndPosition->get(); + + if ((m_PrevBeatSamples < loop_start_position) && (m_NextBeatSamples >= loop_end_position)) { + // No beat inside loop -> show beat indication at loop_start_position + prevIndicatorSamples = loop_start_position; + nextIndicatorSamples = loop_end_position; + } else { + prevIndicatorSamples = m_PrevBeatSamples; + nextIndicatorSamples = m_NextBeatSamples; } - /*qDebug() << "dRate:" << dRate << - " m_lastPlayDirection:" << m_lastPlayDirection << - " m_pCOBeatActive->get(): " << m_pCOBeatActive->get() << - " currentSample: " << currentSample << - " m_lastEvaluatedSample: " << m_lastEvaluatedSample << - " m_PrevBeatSamples: " << m_PrevBeatSamples << - " m_NextBeatSamples: " << m_NextBeatSamples << - " m_blinkIntervalSamples: " << m_blinkIntervalSamples;*/ - - // The m_InternalState needs to be taken into account, to show a reliable beat indication for loops - if (dRate >= 0.0) { - if (m_lastPlayDirection == true) { - if ((currentSample > m_PrevBeatSamples) && - (currentSample < - m_PrevBeatSamples + m_blinkIntervalSamples) && - (m_InternalState != StateMachine::afterBeatActive) && - (m_InternalState != StateMachine::afterBeatDirectionChanged)) { - m_InternalState = StateMachine::afterBeatActive; - m_pCOBeatActive->forceSet(1.0); - } else if ((currentSample > m_PrevBeatSamples + - m_blinkIntervalSamples) && - ((m_InternalState == StateMachine::afterBeatActive) || - (m_InternalState == StateMachine::afterBeatDirectionChanged))) { - m_InternalState = StateMachine::outsideIndicationArea; - m_pCOBeatActive->forceSet(0.0); - } + + if ((m_PrevBeatSamples != -1) && (m_NextBeatSamples != -1)) { + // Don't overwrite interval at begin/end of track + if ((loop_end_position - loop_start_position) < + (m_NextBeatSamples - m_PrevBeatSamples)) { + // Loops smaller than beat distance -> Set m_blinkIntervalSamples based on loop period + m_blinkIntervalSamples = + (loop_end_position - loop_start_position) * + kBlinkInterval; } else { - // Play direction changed while beat indicator was on and forward playing - if ((currentSample < m_NextBeatSamples) && - (currentSample >= - m_NextBeatSamples - m_blinkIntervalSamples) && - (m_InternalState != StateMachine::beforeBeatDirectionChanged)) { - m_InternalState = StateMachine::beforeBeatDirectionChanged; - m_pCOBeatActive->forceSet(0.0); - } + m_blinkIntervalSamples = + (nextIndicatorSamples - prevIndicatorSamples) * + kBlinkInterval; + } + } + } else { + prevIndicatorSamples = m_PrevBeatSamples; + nextIndicatorSamples = m_NextBeatSamples; + + if ((prevIndicatorSamples != -1) && (nextIndicatorSamples != -1)) { + // Don't overwrite interval at begin/end of track + m_blinkIntervalSamples = + (nextIndicatorSamples - prevIndicatorSamples) * + kBlinkInterval; + } + } + + // The m_InternalState needs to be taken into account, to show a reliable beat indication for loops + if (dRate > 0.0) { + if (m_lastPlayDirection == true) { + if ((currentSample > prevIndicatorSamples) && + (currentSample < + prevIndicatorSamples + m_blinkIntervalSamples) && + (m_InternalState != StateMachine::afterBeatActive) && + (m_InternalState != StateMachine::afterBeatDirectionChanged)) { + m_InternalState = StateMachine::afterBeatActive; + m_pCOBeatActive->forceSet(1.0); + } else if ((currentSample > prevIndicatorSamples + + m_blinkIntervalSamples) && + ((m_InternalState == StateMachine::afterBeatActive) || + (m_InternalState == StateMachine::afterBeatDirectionChanged))) { + m_InternalState = StateMachine::outsideIndicationArea; + m_pCOBeatActive->forceSet(0.0); } - m_lastPlayDirection = true; // Forward } else { - if (m_lastPlayDirection == false) { - if ((currentSample < m_NextBeatSamples) && - (currentSample > - m_NextBeatSamples - m_blinkIntervalSamples) && - (m_InternalState != StateMachine::beforeBeatActive) && - (m_InternalState != StateMachine::beforeBeatDirectionChanged)) { - m_InternalState = StateMachine::beforeBeatActive; - m_pCOBeatActive->forceSet(-1.0); - } else if ((currentSample < m_NextBeatSamples - - m_blinkIntervalSamples) && - ((m_InternalState == StateMachine::beforeBeatActive) || - (m_InternalState == StateMachine::beforeBeatDirectionChanged))) { - m_InternalState = StateMachine::outsideIndicationArea; - m_pCOBeatActive->forceSet(0.0); - } - } else { - // Play direction changed while beat indicator was on and reverse playing - if ((currentSample > m_PrevBeatSamples) && - (currentSample <= - m_PrevBeatSamples + m_blinkIntervalSamples) && - (m_InternalState != StateMachine::afterBeatDirectionChanged)) { - m_InternalState = StateMachine::afterBeatDirectionChanged; - m_pCOBeatActive->forceSet(0.0); - } + // Play direction changed while beat indicator was on and forward playing + if ((currentSample < nextIndicatorSamples) && + (currentSample >= + nextIndicatorSamples - m_blinkIntervalSamples) && + (m_InternalState != StateMachine::beforeBeatDirectionChanged)) { + m_InternalState = StateMachine::beforeBeatDirectionChanged; + m_pCOBeatActive->forceSet(0.0); + } + } + m_lastPlayDirection = true; // Forward + } else if (dRate < 0.0) { + if (m_lastPlayDirection == false) { + if ((currentSample < nextIndicatorSamples) && + (currentSample > + nextIndicatorSamples - m_blinkIntervalSamples) && + (m_InternalState != StateMachine::beforeBeatActive) && + (m_InternalState != StateMachine::beforeBeatDirectionChanged)) { + m_InternalState = StateMachine::beforeBeatActive; + m_pCOBeatActive->forceSet(-1.0); + } else if ((currentSample < nextIndicatorSamples - + m_blinkIntervalSamples) && + ((m_InternalState == StateMachine::beforeBeatActive) || + (m_InternalState == StateMachine::beforeBeatDirectionChanged))) { + m_InternalState = StateMachine::outsideIndicationArea; + m_pCOBeatActive->forceSet(0.0); + } + } else { + // Play direction changed while beat indicator was on and reverse playing + if ((currentSample > prevIndicatorSamples) && + (currentSample <= + prevIndicatorSamples + m_blinkIntervalSamples) && + (m_InternalState != StateMachine::afterBeatDirectionChanged)) { + m_InternalState = StateMachine::afterBeatDirectionChanged; + m_pCOBeatActive->forceSet(0.0); } - m_lastPlayDirection = false; // Reverse } - m_lastEvaluatedSample = currentSample; + m_lastPlayDirection = false; // Reverse } + m_lastEvaluatedSample = currentSample; } |