summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoergAtGithub <JoergAtGithub@worldwartweb.com>2021-02-27 17:23:09 +0100
committerJoergAtGithub <JoergAtGithub@worldwartweb.com>2021-02-27 19:48:43 +0100
commitdd1b2b174db90739915f42dcc55aeb58b5bd08a9 (patch)
tree9683cd13654c9673f7365a60c01163812a79ddf9
parent5cb6696d2bf75d436e5f114196fdcfd83fb47482 (diff)
Added the loop cases:
-quantized loop on beat -loop smaller than beat distance -loop without a beat inside
-rw-r--r--src/engine/controls/clockcontrol.cpp179
-rw-r--r--src/engine/controls/clockcontrol.h8
-rw-r--r--src/engine/enginebuffer.cpp2
3 files changed, 116 insertions, 73 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;
}
diff --git a/src/engine/controls/clockcontrol.h b/src/engine/controls/clockcontrol.h
index dccbe1b182..7c1c7c1cc8 100644
--- a/src/engine/controls/clockcontrol.h
+++ b/src/engine/controls/clockcontrol.h
@@ -20,7 +20,8 @@ class ClockControl: public EngineControl {
const int iBufferSize) override;
void updateIndicators(const double dRate,
- const double currentSample);
+ const double currentSample,
+ const double sampleRate);
void trackLoaded(TrackPointer pNewTrack) override;
void trackBeatsUpdated(mixxx::BeatsPointer pBeats) override;
@@ -28,6 +29,11 @@ class ClockControl: public EngineControl {
private:
ControlObject* m_pCOBeatActive;
+ // ControlObjects that come from LoopingControl
+ ControlProxy* m_pLoopEnabled;
+ ControlProxy* m_pLoopStartPosition;
+ ControlProxy* m_pLoopEndPosition;
+
double m_lastEvaluatedSample;
enum class StateMachine : int {
diff --git a/src/engine/enginebuffer.cpp b/src/engine/enginebuffer.cpp
index 0f3cc43a65..cae33bd1b3 100644
--- a/src/engine/enginebuffer.cpp
+++ b/src/engine/enginebuffer.cpp
@@ -1351,7 +1351,7 @@ void EngineBuffer::updateIndicators(double speed, int iBufferSize) {
fractionalPlayposFromAbsolute(m_dSlipPosition),
tempoTrackSeconds);
- m_pClockControl->updateIndicators(speed * m_baserate_old, m_filepos_play);
+ m_pClockControl->updateIndicators(speed * m_baserate_old, m_filepos_play, m_pSampleRate->get());
}
void EngineBuffer::hintReader(const double dRate) {