Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
9c5df56
introduce beatloop_size, beatloop_toggle, and beatloop_enabled COs
Be-ing Feb 15, 2017
d1a945e
add WNumberBeatSize widget
Be-ing Feb 15, 2017
2fa1af7
introduce beatlooproll_toggle CO
Be-ing Feb 15, 2017
5312d96
introduce loopauto_toggle and loopmanual_toggle COs
Be-ing Feb 15, 2017
697ef51
introduce loop_move_forward and loop_move_backward ControlPushButtons
Be-ing Feb 15, 2017
093829a
add seek_loop_in and seek_loop_out COs
Be-ing Feb 15, 2017
a7140c1
rename reloop_exit CO to reloop_toggle and alias old name
Be-ing Feb 15, 2017
5f173ff
clean up memory leaks
Be-ing Feb 15, 2017
07f9e67
replace WNumberBeatSize with WHalveDoubleSpinBox
Be-ing Feb 24, 2017
02b7b10
pretty fractions for WHalveDoubleSpinbox
Be-ing Feb 26, 2017
9aa79e0
remove unnecessary beatloop_enabled CO
Be-ing Feb 27, 2017
c41c2fe
add larger beatloop sizes
Be-ing Feb 27, 2017
d46b601
WHalveDoubleSpinBox clean up warnings
Be-ing Feb 27, 2017
bfe9efc
add beatjump_size, beatjump_forward, and beatjump_backward COs
Be-ing Feb 27, 2017
b503b44
do commonWidgetSetup for WHalveDoubleSpinBox
Be-ing Feb 27, 2017
7e36778
fix memory leaks
Be-ing Feb 27, 2017
bcc4cfc
rename WHalveDoubleSpinBox to WBeatSpinBox
Be-ing Feb 27, 2017
3c70f3f
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing Mar 1, 2017
1f82d6e
remove beatloop_enabled CO from tests
Be-ing Mar 8, 2017
8aa55cc
better variable names
Be-ing Mar 8, 2017
4fd3e1f
update beatjump_size with beatjump_X_forward/backward
Be-ing Mar 8, 2017
e5ecc9c
don't reactivate loop when releasing loopmanual_toggle button
Be-ing Mar 8, 2017
27140cb
keep beatloop_size in sync with loop size when using loop_halve & loo…
Be-ing Mar 8, 2017
d44c413
add reloop_cue ControlPushButton
Be-ing Mar 8, 2017
c01b058
rolling beatloop bug fixes
Be-ing Mar 8, 2017
91c9d64
add loop_move_[forward/backward]_beatloop_size ControlObjects
Be-ing Mar 9, 2017
1de1d9d
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing Mar 10, 2017
361c9ad
rename seek_loop_in/out COs to loop_in/out_goto
Be-ing Mar 13, 2017
de1ee1a
looping code cleanup
Be-ing Mar 17, 2017
5f957d0
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing Mar 17, 2017
ce9678b
prevent tab focusing of WBeatSpinBox
Be-ing Mar 19, 2017
d7cc055
set minimum and maximum sizes for beatloop_size
Be-ing Mar 19, 2017
71ae961
prevent loop_halve from losing connection with beatloop_size when loo…
Be-ing Mar 19, 2017
ff86890
prevent letters and other invalid characters from being typed into WB…
Be-ing Mar 19, 2017
92ecda5
make WBeatSpinBox blacklist regex static
Be-ing Mar 21, 2017
f03c137
various beatloop_size fixes and code clean up
Be-ing Mar 21, 2017
6c8746d
make LoopingControl::currentLoopMatchesBeatloopSize more accurate
Be-ing Mar 21, 2017
ad06cd5
don't resize inactive beatloops until beatloop_size matches length
Be-ing Mar 22, 2017
efaf993
let beatloop_size shrink if it is too big on track load
Be-ing Mar 22, 2017
e992966
don't update beatloop_X_enabled until after loop size checks
Be-ing Mar 24, 2017
241da8a
don't let WBeatSpinBox's value get out of sync with its ControlObject
Be-ing Mar 24, 2017
1a78278
jump to start of loop with reloop_toggle if not playing
Be-ing Mar 25, 2017
9726e70
add new "reloop" ControlPushButton
Be-ing Mar 25, 2017
0ae8805
fix memory leak
Be-ing Mar 28, 2017
98ef873
remove unnecessary mutex
Be-ing Mar 31, 2017
b410f99
rename beatlooproll_toggle -> beatlooproll_activate
Be-ing Mar 31, 2017
87d3518
rename reloop_cue -> reloop_andstop
Be-ing Mar 31, 2017
c97a5f4
add comments and small code cleanups
Be-ing Mar 31, 2017
38c9552
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing Mar 31, 2017
4888d2d
attempt to scale WBeatSpinBox with rest of skin
Be-ing Mar 31, 2017
732176d
do not resize manual loops when changing beatloop_size
Be-ing Apr 7, 2017
13f7b9e
remove loopauto_toggle
Be-ing Apr 7, 2017
ef92bce
rename loopmanual_toggle -> loopmanual_set
Be-ing Apr 7, 2017
eed25bd
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing Apr 7, 2017
8f770e4
add beatloop_size_indicator ControlObject
Be-ing Apr 7, 2017
3fb7b74
correct slot names
Be-ing Apr 7, 2017
22f78ef
fix manually typing number into WBeatSpinBox
Be-ing Apr 7, 2017
851d7d0
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing Apr 12, 2017
79ae33f
revert to Mixxx 2.0 behavior of loop_halve/double
Be-ing Apr 12, 2017
858bb2f
add beatloop_halve/double ControlPushbuttons
Be-ing Apr 12, 2017
5a392b5
hold loop_in/out to move loop boundaries; catch loop with reloop CO
Be-ing Apr 12, 2017
2afa5ef
remove loopmanual_set ControlPushbutton
Be-ing Apr 12, 2017
33b7c58
remove "reloop" CO, make "reloop_toggle" catch upcoming loops
Be-ing Apr 12, 2017
2f6687a
make loop_halve/double work better with beatloop_size again
Be-ing Apr 12, 2017
36ee15a
workaround for beatjump_size spinbox
Be-ing Apr 12, 2017
66c9487
update tooltips for new loop & beatjump controls
Be-ing Apr 12, 2017
05b6c60
don't assume constant beatgrid for loop moving & beatjumping
Be-ing Apr 14, 2017
fcf2aa7
code cleanup
Be-ing Apr 14, 2017
4cd2a3d
make LoopingControlTest.LoopMoveTest pass
Be-ing Apr 28, 2017
965ac88
remove unused beatloop_size_indicator ControlObject
Be-ing May 1, 2017
697695c
move loop if beatjumping when loop is enabled
Be-ing May 8, 2017
2c129ea
measure beatloop_size when setting manual loops with quantize
Be-ing May 8, 2017
4a9cc19
let loop_in/out be set without beatgrid when quantize is enabled
Be-ing May 8, 2017
7370c49
wait to update CO for WBeatSpinbox until user finishes typing
Be-ing May 8, 2017
8a535d0
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing May 11, 2017
5b60fcd
make pressing beatloop_toggle always set a loop
Be-ing May 14, 2017
9bd5ff8
Merge remote-tracking branch 'upstream/master' into beatloop_size
Be-ing May 17, 2017
50546a4
Seek into phase, even if we have to jump back because of loop end.
daschuer May 19, 2017
0dbdf38
Merge pull request #7 from daschuer/beatloop_size
Be-ing May 20, 2017
997d056
fix LoopingControlTests after changing beatloop_toggle behavior
Be-ing May 20, 2017
d283d63
rename beatloop_toggle to beatloop_set
Be-ing May 20, 2017
a1768b0
fix loop in/out quantization tests
Be-ing May 21, 2017
a296ce1
update loop and beatjump tooltips
Be-ing May 21, 2017
6481479
rename beatloop_set to beatloop_activate
Be-ing May 21, 2017
1318638
sync phase when pressing play only to a playing sync target, bug #166…
daschuer May 21, 2017
1f5de0c
don't update beatjump_size when using beatjump_X_forward/backward
Be-ing May 22, 2017
1d64530
Merge pull request #8 from daschuer/beatloop_size
Be-ing May 22, 2017
e06f629
don't shift whole loop when holding loop_in/out and beatjumping
Be-ing May 22, 2017
811162b
remove loop_move_forward/backward(_beatloop_size) ControlObjects
Be-ing May 22, 2017
d6f8a9e
update beatjump/loop move tooltips
Be-ing May 22, 2017
07a3f96
snap to previous/next beats when adjusting loop in/out points with qu…
Be-ing May 23, 2017
6c5722c
fix beatjumping while holding loop_in/out
Be-ing May 24, 2017
9b4400a
Step from the intermediate value in the beat spin box
daschuer May 24, 2017
2c1408c
use locale decimal sparator
daschuer May 24, 2017
5277cc1
Ommit trailing zeros in beat size spin box
daschuer May 24, 2017
a17d590
Merge pull request #9 from daschuer/beatloop_size
Be-ing May 24, 2017
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
1 change: 1 addition & 0 deletions build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ def sources(self, build):
"widget/wlabel.cpp",
"widget/wtracktext.cpp",
"widget/wnumber.cpp",
"widget/wbeatspinbox.cpp",
"widget/wnumberdb.cpp",
"widget/wnumberpos.cpp",
"widget/wnumberrate.cpp",
Expand Down
114 changes: 63 additions & 51 deletions src/engine/bpmcontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ double BpmControl::calcSyncedRate(double userTweak) {

// Now that we have our beat distance we can also check how large the
// current loop is. If we are in a <1 beat loop, don't worry about offset.
const bool loop_enabled = m_pLoopEnabled->get() > 0.0;
const bool loop_enabled = m_pLoopEnabled->toBool();
const double loop_size = (m_pLoopEndPosition->get() -
m_pLoopStartPosition->get()) /
dBeatLength;
Expand Down Expand Up @@ -567,14 +567,14 @@ bool BpmControl::getBeatContextNoLookup(
return true;
}

double BpmControl::getPhaseOffset(double dThisPosition) {
double BpmControl::getNearestPositionInPhase(double dThisPosition, bool respectLoops, bool playing) {
// Without a beatgrid, we don't know the phase offset.
if (!m_pBeats) {
return 0;
return dThisPosition;
}
// Master buffer is always in sync!
if (getSyncMode() == SYNC_MASTER) {
return 0;
return dThisPosition;
}

// Get the current position of this deck.
Expand All @@ -588,13 +588,13 @@ double BpmControl::getPhaseOffset(double dThisPosition) {
if (!getBeatContext(m_pBeats, dThisPosition,
&dThisPrevBeat, &dThisNextBeat,
&dThisBeatLength, NULL)) {
return 0;
return dThisPosition;
}
} else {
if (!getBeatContextNoLookup(dThisPosition,
dThisPrevBeat, dThisNextBeat,
&dThisBeatLength, NULL)) {
return 0;
return dThisPosition;
}
}

Expand All @@ -606,15 +606,23 @@ double BpmControl::getPhaseOffset(double dThisPosition) {
// If not, we have to figure it out
EngineBuffer* pOtherEngineBuffer = pickSyncTarget();
if (pOtherEngineBuffer == NULL) {
return 0;
return dThisPosition;
}

if (playing) {
// "this" track is playing, or just starting
// only match phase if the sync target is playing as well
if (pOtherEngineBuffer->getSpeed() == 0.0) {
return dThisPosition;
}
}

TrackPointer otherTrack = pOtherEngineBuffer->getLoadedTrack();
BeatsPointer otherBeats = otherTrack ? otherTrack->getBeats() : BeatsPointer();

// If either track does not have beats, then we can't adjust the phase.
if (!otherBeats) {
return 0;
return dThisPosition;
}

double dOtherLength = ControlObject::getControl(
Expand All @@ -624,7 +632,7 @@ double BpmControl::getPhaseOffset(double dThisPosition) {

if (!BpmControl::getBeatContext(otherBeats, dOtherPosition,
NULL, NULL, NULL, &dOtherBeatFraction)) {
return 0.0;
return dThisPosition;
}
}

Expand Down Expand Up @@ -658,51 +666,55 @@ double BpmControl::getPhaseOffset(double dThisPosition) {
dNewPlaypos += dThisPrevBeat;
}

// We might be seeking outside the loop.
const bool loop_enabled = m_pLoopEnabled->get() > 0.0;
const double loop_start_position = m_pLoopStartPosition->get();
const double loop_end_position = m_pLoopEndPosition->get();

// Cases for sanity:
//
// CASE 1
// Two identical 1-beat loops, out of phase by X samples.
// Other deck is at its loop start.
// This deck is half way through. We want to jump forward X samples to the loop end point.
//
// Two identical 1-beat loop, out of phase by X samples.
// Other deck is

// If sync target is 50% through the beat,
// If we are at the loop end point and hit sync, jump forward X samples.


// TODO(rryan): Revise this with something that keeps a broader number of
// cases in sync. This at least prevents breaking out of the loop.
if (loop_enabled) {
const double loop_length = loop_end_position - loop_start_position;
if (loop_length <= 0.0) {
return false;
}

// TODO(rryan): If loop_length is not a multiple of dThisBeatLength should
// we bail and not sync phase?

// Syncing to after the loop end.
double end_delta = dNewPlaypos - loop_end_position;
if (end_delta > 0) {
int i = end_delta / loop_length;
dNewPlaypos = loop_start_position + end_delta - i * loop_length;
}

// Syncing to before the loop beginning.
double start_delta = loop_start_position - dNewPlaypos;
if (start_delta > 0) {
int i = start_delta / loop_length;
dNewPlaypos = loop_end_position - start_delta + i * loop_length;
if (respectLoops) {
// We might be seeking outside the loop.
const bool loop_enabled = m_pLoopEnabled->toBool();
const double loop_start_position = m_pLoopStartPosition->get();
const double loop_end_position = m_pLoopEndPosition->get();

// Cases for sanity:
//
// CASE 1
// Two identical 1-beat loops, out of phase by X samples.
// Other deck is at its loop start.
// This deck is half way through. We want to jump forward X samples to the loop end point.
//
// Two identical 1-beat loop, out of phase by X samples.
// Other deck is

// If sync target is 50% through the beat,
// If we are at the loop end point and hit sync, jump forward X samples.


// TODO(rryan): Revise this with something that keeps a broader number of
// cases in sync. This at least prevents breaking out of the loop.
if (loop_enabled &&
dThisPosition <= loop_end_position) {
const double loop_length = loop_end_position - loop_start_position;
const double end_delta = dNewPlaypos - loop_end_position;

// Syncing to after the loop end.
if (end_delta > 0 && loop_length > 0.0) {
int i = end_delta / loop_length;
dNewPlaypos = loop_start_position + end_delta - i * loop_length;

// Move new position after loop jump into phase as well.
// This is a recursive call, called only twice because of
// respectLoops = false
dNewPlaypos = getNearestPositionInPhase(dNewPlaypos, false, playing);
}

// Note: Syncing to before the loop beginning is allowed, because
// loops are catching
}
}

return dNewPlaypos;
}

double BpmControl::getPhaseOffset(double dThisPosition) {
// This does not respect looping
double dNewPlaypos = getNearestPositionInPhase(dThisPosition, false, false);
return dNewPlaypos - dThisPosition;
}

Expand Down
3 changes: 2 additions & 1 deletion src/engine/bpmcontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class BpmControl : public EngineControl {
// out of sync.
double calcSyncedRate(double userTweak);
// Get the phase offset from the specified position.
double getPhaseOffset(double reference_position);
double getNearestPositionInPhase(double dThisPosition, bool respectLoops, bool playing);
double getPhaseOffset(double dThisPosition);
double getBeatDistance(double dThisPosition) const;
double getPreviousSample() const { return m_dPreviousSample; }

Expand Down
2 changes: 1 addition & 1 deletion src/engine/enginebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@ void EngineBuffer::processSeek(bool paused) {
}

if ((seekType & SEEK_PHASE) && !paused && m_pQuantize->toBool()) {
position += m_pBpmControl->getPhaseOffset(position);
position = m_pBpmControl->getNearestPositionInPhase(position, true, true);
}

double newPlayFrame = position / kSamplesPerFrame;
Expand Down
5 changes: 4 additions & 1 deletion src/engine/enginebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,12 @@ class EngineBuffer : public EngineObject {
UserSettingsPointer m_pConfig;

LoopingControl* m_pLoopingControl;
FRIEND_TEST(LoopingControlTest, LoopHalveButton_HalvesLoop);
FRIEND_TEST(LoopingControlTest, LoopScale_HalvesLoop);
FRIEND_TEST(LoopingControlTest, LoopMoveTest);
FRIEND_TEST(LoopingControlTest, LoopResizeSeek);
FRIEND_TEST(LoopingControlTest, ReloopToggleButton_DoesNotJumpAhead);
FRIEND_TEST(LoopingControlTest, ReloopAndStopButton);
FRIEND_TEST(LoopingControlTest, Beatjump_JumpsByBeats);
FRIEND_TEST(SyncControlTest, TestDetermineBpmMultiplier);
FRIEND_TEST(EngineSyncTest, HalfDoubleBpmTest);
FRIEND_TEST(EngineSyncTest, HalfDoubleThenPlay);
Expand Down
Loading