1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// QuantizeControl.cpp
// Created on Sat 5, 2011
// Author: pwhelan
#include "engine/controls/quantizecontrol.h"
#include <QtDebug>
#include "control/controlobject.h"
#include "control/controlpushbutton.h"
#include "engine/controls/enginecontrol.h"
#include "preferences/usersettings.h"
#include "track/track.h"
#include "util/assert.h"
QuantizeControl::QuantizeControl(QString group,
UserSettingsPointer pConfig)
: EngineControl(group, pConfig) {
// Turn quantize OFF by default. See Bug #898213
m_pCOQuantizeEnabled = new ControlPushButton(ConfigKey(group, "quantize"), true);
m_pCOQuantizeEnabled->setButtonMode(ControlPushButton::TOGGLE);
m_pCONextBeat = new ControlObject(ConfigKey(group, "beat_next"));
m_pCONextBeat->set(-1);
m_pCOPrevBeat = new ControlObject(ConfigKey(group, "beat_prev"));
m_pCOPrevBeat->set(-1);
m_pCOClosestBeat = new ControlObject(ConfigKey(group, "beat_closest"));
m_pCOClosestBeat->set(-1);
}
QuantizeControl::~QuantizeControl() {
delete m_pCOQuantizeEnabled;
delete m_pCONextBeat;
delete m_pCOPrevBeat;
delete m_pCOClosestBeat;
}
void QuantizeControl::trackLoaded(TrackPointer pNewTrack) {
if (pNewTrack) {
m_pBeats = pNewTrack->getBeats();
// Initialize prev and next beat as if current position was zero.
// If there is a cue point, the value will be updated.
lookupBeatPositions(0.0);
updateClosestBeat(0.0);
} else {
m_pBeats.clear();
m_pCOPrevBeat->set(-1);
m_pCONextBeat->set(-1);
m_pCOClosestBeat->set(-1);
}
}
void QuantizeControl::trackBeatsUpdated(mixxx::BeatsPointer pBeats) {
m_pBeats = pBeats;
double current = getSampleOfTrack().current;
lookupBeatPositions(current);
updateClosestBeat(current);
}
void QuantizeControl::setCurrentSample(const double dCurrentSample,
const double dTotalSamples,
const double dTrackSampleRate) {
EngineControl::setCurrentSample(dCurrentSample, dTotalSamples, dTrackSampleRate);
playPosChanged(dCurrentSample);
}
void QuantizeControl::notifySeek(double dNewPlaypos) {
EngineControl::notifySeek(dNewPlaypos);
playPosChanged(dNewPlaypos);
}
void QuantizeControl::playPosChanged(double dNewPlaypos) {
// We only need to update the prev or next if the current sample is
// out of range of the existing beat positions or if we've been forced to
// do so.
// NOTE: This bypasses the epsilon calculation, but is there a way
// that could actually cause a problem?
if (dNewPlaypos < m_pCOPrevBeat->get() || dNewPlaypos > m_pCONextBeat->get()) {
lookupBeatPositions(dNewPlaypos);
}
updateClosestBeat(dNewPlaypos);
}
void QuantizeControl::lookupBeatPositions(double dCurrentSample) {
mixxx::BeatsPointer pBeats = m_pBeats;
if (pBeats) {
double prevBeat, nextBeat;
pBeats->findPrevNextBeats(dCurrentSample, &prevBeat, &nextBeat);
m_pCOPrevBeat->set(prevBeat);
m_pCONextBeat->set(nextBeat);
}
}
void QuantizeControl::updateClosestBeat(double dCurrentSample) {
if (!m_pBeats) {
return;
}
double prevBeat = m_pCOPrevBeat->get();
double nextBeat = m_pCONextBeat->get();
double closestBeat = m_pCOClosestBeat->get();
// Calculate closest beat by hand since we want the beat locations themselves
// and duplicating the work by calling the standard API would double
// the number of mutex locks.
if (prevBeat == -1) {
if (nextBeat != -1) {
m_pCOClosestBeat->set(nextBeat);
} else {
// Likely no beat information -- can't set closest beat value.
}
} else if (nextBeat == -1) {
m_pCOClosestBeat->set(prevBeat);
} else {
double currentClosestBeat =
(nextBeat - dCurrentSample > dCurrentSample - prevBeat) ?
prevBeat : nextBeat;
if (closestBeat != currentClosestBeat) {
m_pCOClosestBeat->set(currentClosestBeat);
}
}
}
|