summaryrefslogtreecommitdiffstats
path: root/src/engine/controls/clockcontrol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/controls/clockcontrol.cpp')
-rw-r--r--src/engine/controls/clockcontrol.cpp179
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;
}