Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for scaling BPM by different ratios using ControlPushButton #1

Merged
merged 3 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
55 changes: 49 additions & 6 deletions src/controllers/controlpickermenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,55 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)

// BPM / Beatgrid
QMenu* pBpmMenu = addSubmenu(tr("BPM / Beatgrid"));
addDeckAndSamplerControl("bpm", tr("BPM"), tr("BPM"), pBpmMenu, true);
addDeckAndSamplerControl("bpm_up", tr("BPM +1"), tr("Increase BPM by 1"), pBpmMenu);
addDeckAndSamplerControl("bpm_down", tr("BPM -1"), tr("Decrease BPM by 1"), pBpmMenu);
addDeckAndSamplerControl("bpm_up_small", tr("BPM +0.1"), tr("Increase BPM by 0.1"), pBpmMenu);
addDeckAndSamplerControl("bpm_down_small", tr("BPM -0.1"), tr("Decrease BPM by 0.1"), pBpmMenu);
addDeckAndSamplerControl("bpm_tap", tr("BPM Tap"), tr("BPM tap button"), pBpmMenu);
addDeckAndSamplerControl("bpm",
tr("BPM"),
tr("BPM"),
pBpmMenu,
true);
addDeckAndSamplerControl("bpm_up",
tr("BPM +1"),
tr("Increase BPM by 1"),
pBpmMenu);
addDeckAndSamplerControl("bpm_down",
tr("BPM -1"),
tr("Decrease BPM by 1"),
pBpmMenu);
addDeckAndSamplerControl("bpm_up_small",
tr("BPM +0.1"),
tr("Increase BPM by 0.1"),
pBpmMenu);
addDeckAndSamplerControl("bpm_down_small",
tr("BPM -0.1"),
tr("Decrease BPM by 0.1"),
pBpmMenu);
addDeckAndSamplerControl("bpm_tap",
tr("BPM Tap"),
tr("BPM tap button"),
pBpmMenu);
addDeckAndSamplerControl("beats_set_halve",
tr("Halve BPM"),
tr("Multiply current BPM by 0.5"),
pBpmMenu);
addDeckAndSamplerControl("beats_set_twothirds",
tr("2/3 BPM"),
tr("Multiply current BPM by 0.666"),
pBpmMenu);
addDeckAndSamplerControl("beats_set_threefourths",
tr("3/4 BPM"),
tr("Multiply current BPM by 0.75"),
pBpmMenu);
addDeckAndSamplerControl("beats_set_fourthirds",
tr("4/3 BPM"),
tr("Multiply current BPM by 1.333"),
pBpmMenu);
addDeckAndSamplerControl("beats_set_threehalves",
tr("3/2 BPM"),
tr("Multiply current BPM by 1.5"),
pBpmMenu);
addDeckAndSamplerControl("beats_set_double",
tr("Double BPM"),
tr("Multiply current BPM by 2"),
pBpmMenu);
pBpmMenu->addSeparator();
addDeckAndSamplerControl("beats_adjust_faster",
tr("Adjust Beatgrid Faster +.01"),
Expand Down
118 changes: 102 additions & 16 deletions src/engine/controls/bpmcontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,39 @@ BpmControl::BpmControl(const QString& group,
m_pLoopEndPosition = new ControlProxy(group, "loop_end_position", this);

m_pLocalBpm = new ControlObject(ConfigKey(group, "local_bpm"));
m_pAdjustBeatsFaster = new ControlPushButton(ConfigKey(group, "beats_adjust_faster"), false);

m_pAdjustBeatsFaster = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_adjust_faster"), false);
m_pAdjustBeatsFaster->setKbdRepeatable(true);
connect(m_pAdjustBeatsFaster, &ControlObject::valueChanged,
this, &BpmControl::slotAdjustBeatsFaster,
connect(m_pAdjustBeatsFaster.get(),
&ControlObject::valueChanged,
this,
&BpmControl::slotAdjustBeatsFaster,
Qt::DirectConnection);
m_pAdjustBeatsSlower = new ControlPushButton(ConfigKey(group, "beats_adjust_slower"), false);
m_pAdjustBeatsSlower = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_adjust_slower"), false);
m_pAdjustBeatsSlower->setKbdRepeatable(true);
connect(m_pAdjustBeatsSlower, &ControlObject::valueChanged,
this, &BpmControl::slotAdjustBeatsSlower,
connect(m_pAdjustBeatsSlower.get(),
&ControlObject::valueChanged,
this,
&BpmControl::slotAdjustBeatsSlower,
Qt::DirectConnection);
m_pTranslateBeatsEarlier = new ControlPushButton(ConfigKey(group, "beats_translate_earlier"), false);

m_pTranslateBeatsEarlier = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_translate_earlier"), false);
m_pTranslateBeatsEarlier->setKbdRepeatable(true);
connect(m_pTranslateBeatsEarlier, &ControlObject::valueChanged,
this, &BpmControl::slotTranslateBeatsEarlier,
connect(m_pTranslateBeatsEarlier.get(),
&ControlObject::valueChanged,
this,
&BpmControl::slotTranslateBeatsEarlier,
Qt::DirectConnection);
m_pTranslateBeatsLater = new ControlPushButton(ConfigKey(group, "beats_translate_later"), false);
m_pTranslateBeatsLater = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_translate_later"), false);
m_pTranslateBeatsLater->setKbdRepeatable(true);
connect(m_pTranslateBeatsLater, &ControlObject::valueChanged,
this, &BpmControl::slotTranslateBeatsLater,
connect(m_pTranslateBeatsLater.get(),
&ControlObject::valueChanged,
this,
&BpmControl::slotTranslateBeatsLater,
Qt::DirectConnection);
m_pTranslateBeatsMove = new ControlEncoder(ConfigKey(group, "beats_translate_move"), false);
connect(m_pTranslateBeatsMove,
Expand All @@ -94,6 +108,66 @@ BpmControl::BpmControl(const QString& group,
&BpmControl::slotTranslateBeatsMove,
Qt::DirectConnection);

m_pBeatsHalve = std::make_unique<ControlPushButton>(ConfigKey(group, "beats_set_halve"), false);
connect(m_pBeatsHalve.get(),
&ControlObject::valueChanged,
this,
[this](int value) {
if (value > 0) {
slotScaleBpm(mixxx::Beats::BpmScale::Halve);
}
});
m_pBeatsTwoThirds = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_set_twothirds"), false);
connect(m_pBeatsTwoThirds.get(),
&ControlObject::valueChanged,
this,
[this](int value) {
if (value > 0) {
slotScaleBpm(mixxx::Beats::BpmScale::TwoThirds);
}
});
m_pBeatsThreeFourths = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_set_threefourths"), false);
connect(m_pBeatsThreeFourths.get(),
&ControlObject::valueChanged,
this,
[this](int value) {
if (value > 0) {
slotScaleBpm(mixxx::Beats::BpmScale::ThreeFourths);
}
});
m_pBeatsFourThirds = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_set_fourthirds"), false);
connect(m_pBeatsFourThirds.get(),
&ControlObject::valueChanged,
this,
[this](int value) {
if (value > 0) {
slotScaleBpm(mixxx::Beats::BpmScale::FourThirds);
}
});
m_pBeatsThreeHalves = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_set_threehalves"), false);
connect(m_pBeatsThreeHalves.get(),
&ControlObject::valueChanged,
this,
[this](int value) {
if (value > 0) {
slotScaleBpm(mixxx::Beats::BpmScale::ThreeHalves);
}
});
m_pBeatsDouble = std::make_unique<ControlPushButton>(
ConfigKey(group, "beats_set_double"), false);
connect(m_pBeatsDouble.get(),
&ControlObject::valueChanged,
this,
[this](int value) {
if (value > 0) {
slotScaleBpm(mixxx::Beats::BpmScale::Double);
}
});

// Pick a wide range (kBpmRangeMin to kBpmRangeMax) and allow out of bounds sets. This lets you
// map a soft-takeover MIDI knob to the BPM. This also creates bpm_up and
// bpm_down controls.
Expand Down Expand Up @@ -156,11 +230,7 @@ BpmControl::~BpmControl() {
delete m_pButtonTap;
delete m_pTranslateBeats;
delete m_pBeatsTranslateMatchAlignment;
delete m_pTranslateBeatsEarlier;
delete m_pTranslateBeatsLater;
delete m_pTranslateBeatsMove;
delete m_pAdjustBeatsFaster;
delete m_pAdjustBeatsSlower;
delete m_pBeatsUndo;
}

Expand Down Expand Up @@ -291,6 +361,22 @@ void BpmControl::slotTapFilter(double averageLength, int numSamples) {
pTrack->trySetBeats(*newBeats);
}

void BpmControl::slotScaleBpm(mixxx::Beats::BpmScale bpmScale) {
const TrackPointer pTrack = getEngineBuffer()->getLoadedTrack();
if (!pTrack) {
return;
}
const mixxx::BeatsPointer pBeats = pTrack->getBeats();
if (!pBeats) {
return;
}
const auto newBeats = pBeats->tryScale(bpmScale);
if (!newBeats) {
return;
}
pTrack->trySetBeats(*newBeats);
}

// static
double BpmControl::shortestPercentageChange(const double& current_percentage,
const double& target_percentage) {
Expand Down
16 changes: 12 additions & 4 deletions src/engine/controls/bpmcontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class BpmControl : public EngineControl {
}
double calcSyncAdjustment(bool userTweakingSync);
void adjustBeatsBpm(double deltaBpm);
void slotScaleBpm(mixxx::Beats::BpmScale bpmScale);

friend class SyncControl;

Expand All @@ -142,13 +143,20 @@ class BpmControl : public EngineControl {

// The average bpm around the current playposition;
ControlObject* m_pLocalBpm;
ControlPushButton* m_pAdjustBeatsFaster;
ControlPushButton* m_pAdjustBeatsSlower;
ControlPushButton* m_pTranslateBeatsEarlier;
ControlPushButton* m_pTranslateBeatsLater;
std::unique_ptr<ControlPushButton> m_pAdjustBeatsFaster;
std::unique_ptr<ControlPushButton> m_pAdjustBeatsSlower;
std::unique_ptr<ControlPushButton> m_pTranslateBeatsEarlier;
std::unique_ptr<ControlPushButton> m_pTranslateBeatsLater;
ControlEncoder* m_pTranslateBeatsMove;
ControlPushButton* m_pBeatsUndo;

std::unique_ptr<ControlPushButton> m_pBeatsHalve;
std::unique_ptr<ControlPushButton> m_pBeatsTwoThirds;
std::unique_ptr<ControlPushButton> m_pBeatsThreeFourths;
std::unique_ptr<ControlPushButton> m_pBeatsFourThirds;
std::unique_ptr<ControlPushButton> m_pBeatsThreeHalves;
std::unique_ptr<ControlPushButton> m_pBeatsDouble;

std::unique_ptr<ControlPushButton> m_pBpmLock;

// The current effective BPM of the engine
Expand Down
Loading