From 1fa0c48aad9ddcdee756394f4ea16a7d25fa0186 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sat, 11 May 2024 21:48:43 +0200 Subject: [PATCH] feat: add support for scaling BPM by different ratios --- src/controllers/controlpickermenu.cpp | 24 +++++++++ src/engine/controls/bpmcontrol.cpp | 76 +++++++++++++++++++++++++++ src/engine/controls/bpmcontrol.h | 8 +++ 3 files changed, 108 insertions(+) diff --git a/src/controllers/controlpickermenu.cpp b/src/controllers/controlpickermenu.cpp index 039e3e4a018..1369065434c 100644 --- a/src/controllers/controlpickermenu.cpp +++ b/src/controllers/controlpickermenu.cpp @@ -262,6 +262,30 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent) 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"), diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp index 90bdd09ba66..0f9d6c271b5 100644 --- a/src/engine/controls/bpmcontrol.cpp +++ b/src/engine/controls/bpmcontrol.cpp @@ -108,6 +108,66 @@ BpmControl::BpmControl(const QString& group, &BpmControl::slotTranslateBeatsMove, Qt::DirectConnection); + m_pBeatsHalve = std::make_unique(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( + 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( + 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( + 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( + 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( + 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. @@ -282,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) { diff --git a/src/engine/controls/bpmcontrol.h b/src/engine/controls/bpmcontrol.h index 90f46339eff..53409f58725 100644 --- a/src/engine/controls/bpmcontrol.h +++ b/src/engine/controls/bpmcontrol.h @@ -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; @@ -147,6 +148,13 @@ class BpmControl : public EngineControl { std::unique_ptr m_pTranslateBeatsLater; ControlEncoder* m_pTranslateBeatsMove; + std::unique_ptr m_pBeatsHalve; + std::unique_ptr m_pBeatsTwoThirds; + std::unique_ptr m_pBeatsThreeFourths; + std::unique_ptr m_pBeatsFourThirds; + std::unique_ptr m_pBeatsThreeHalves; + std::unique_ptr m_pBeatsDouble; + std::unique_ptr m_pBpmLock; // The current effective BPM of the engine