summaryrefslogtreecommitdiffstats
path: root/src/engine/controls/loopingcontrol.cpp
diff options
context:
space:
mode:
authorPhilip Gottschling <gottschlingp@gmail.com>2019-09-17 17:41:49 +0200
committerPhilip Gottschling <gottschlingp@gmail.com>2019-09-22 14:09:46 +0200
commita39c37d98eb0e1bacfa8aa2209ea87868c6f78fb (patch)
tree335f3fccf8d28053e7d8a29ced1635d7eb19ac51 /src/engine/controls/loopingcontrol.cpp
parenta7ae01df752b557ddcff261b3500a5189143927b (diff)
beat loops snap to the closest (fractional) beat in quantized mode
Diffstat (limited to 'src/engine/controls/loopingcontrol.cpp')
-rw-r--r--src/engine/controls/loopingcontrol.cpp37
1 files changed, 26 insertions, 11 deletions
diff --git a/src/engine/controls/loopingcontrol.cpp b/src/engine/controls/loopingcontrol.cpp
index 02f9e10fb4..2e7ae26ccb 100644
--- a/src/engine/controls/loopingcontrol.cpp
+++ b/src/engine/controls/loopingcontrol.cpp
@@ -1060,16 +1060,16 @@ void LoopingControl::slotBeatLoop(double beats, bool keepStartPoint, bool enable
newloopSamples.start = currentSample;
}
} else {
- // loop_in is set to the previous beat if quantize is on. The
- // closest beat might be ahead of play position which would cause a seek.
- // TODO: If in reverse, should probably choose nextBeat.
+ // loop_in is set to the closest beat if quantize is on and the loop size is >= 1 beat.
+ // The closest beat might be ahead of play position and will cause a catching loop.
double prevBeat;
double nextBeat;
pBeats->findPrevNextBeats(currentSample, &prevBeat, &nextBeat);
if (m_pQuantizeEnabled->toBool() && prevBeat != -1) {
+ double closestBeat = pBeats->findClosestBeat(currentSample);
if (beats >= 1.0) {
- newloopSamples.start = prevBeat;
+ newloopSamples.start = closestBeat;
} else {
// In case of beat length less then 1 beat:
// (| - beats, ^ - current track's position):
@@ -1078,13 +1078,28 @@ void LoopingControl::slotBeatLoop(double beats, bool keepStartPoint, bool enable
//
// If we press 1/2 beatloop we want loop from 50% to 100%,
// If I press 1/4 beatloop, we want loop from 50% to 75% etc
- double beat_len = nextBeat - prevBeat;
- double loops_per_beat = 1.0 / beats;
- double beat_pos = currentSample - prevBeat;
- int beat_frac =
- static_cast<int>(floor((beat_pos / beat_len) *
- loops_per_beat));
- newloopSamples.start = prevBeat + beat_len / loops_per_beat * beat_frac;
+ double beatLength = nextBeat - prevBeat;
+ double beatPos = currentSample - prevBeat;
+
+ // find the two closest beat fractions and place the new loop start to the closer one
+ double fractionBeatLength = beatLength * beats;
+ double previousFractionBeat = prevBeat + (floor(beatPos / fractionBeatLength)) * fractionBeatLength;
+ double nextFractionBeat = prevBeat + (floor(beatPos / fractionBeatLength) + 1) * fractionBeatLength;
+
+ if (abs(previousFractionBeat - currentSample) <= abs(nextFractionBeat - currentSample)) {
+ newloopSamples.start = previousFractionBeat;
+ } else {
+ newloopSamples.start = nextFractionBeat;
+ }
+
+ // If running reverse, move the loop one fractional beat to the left.
+ // Thus, the loop end is (time-wise) in front of the current position.
+ //
+ // TODO: There must be a better way of checking if we are running reverse. Getting the "old_reverse" from the EngineBuffer somehow seems wrong.
+ // Furthermore, it does not work when we are not playing and the reverse button is held.
+ if (getEngineBuffer()->isReverse()) {
+ newloopSamples.start -= fractionBeatLength;
+ }
}
} else {