Skip to content

Commit

Permalink
feat: add support for scaling BPM by different ratios
Browse files Browse the repository at this point in the history
  • Loading branch information
Milkii Brewster authored and ronso0 committed May 11, 2024
1 parent fc96155 commit 5daa61c
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 26 deletions.
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 @@ -149,11 +223,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;
}

mixxx::Bpm BpmControl::getBpm() const {
Expand Down Expand Up @@ -272,6 +342,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 @@ -120,6 +120,7 @@ class BpmControl : public EngineControl {
}
double calcSyncAdjustment(bool userTweakingSync);
void adjustBeatsBpm(double deltaBpm);
void slotScaleBpm(mixxx::Beats::BpmScale bpmScale);

friend class SyncControl;

Expand All @@ -141,12 +142,19 @@ 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;

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

0 comments on commit 5daa61c

Please sign in to comment.