From 944ad6a5bd61e32601aab6a79161f59e2be149f2 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Mon, 13 Sep 2021 21:50:39 +0300 Subject: [PATCH] Improve BPM calculation (not really (it's bad...)) --- include/tools/beatutils.h | 4 +-- include/tools/bpmcalculator.h | 2 ++ include/tools/mathutils.h | 1 + src/gui/widgets/bpmcalculatorwidget.cpp | 38 +++++++++++++++++++++---- src/gui/widgets/bpmcalculatorwidget.h | 3 ++ src/tools/beatutils.cpp | 5 ++-- src/tools/bpmcalculator.cpp | 15 ++++++---- 7 files changed, 54 insertions(+), 14 deletions(-) diff --git a/include/tools/beatutils.h b/include/tools/beatutils.h index 4adf37e..32018f8 100644 --- a/include/tools/beatutils.h +++ b/include/tools/beatutils.h @@ -7,8 +7,8 @@ namespace beat_utils { struct BeatInfo { - long double rate_per_microsecond = 0.; - microsec average_interval = 0; + int BPM = 0; + microsec interval = 0; }; BeatInfo calculateBeatRateInfo(const std::vector& approximate_deltas); diff --git a/include/tools/bpmcalculator.h b/include/tools/bpmcalculator.h index 31bf18f..55a259a 100644 --- a/include/tools/bpmcalculator.h +++ b/include/tools/bpmcalculator.h @@ -16,6 +16,8 @@ public: void stop(); void click(); + bool calculating() const; + const beat_utils::BeatInfo& fetchApproximatedInfo(); microsec fetchTimeUntilNextBeat(); diff --git a/include/tools/mathutils.h b/include/tools/mathutils.h index cd50180..cdc12cc 100644 --- a/include/tools/mathutils.h +++ b/include/tools/mathutils.h @@ -3,6 +3,7 @@ #include using microsec = sf::Int64; +using minute = int; struct Coordinates { diff --git a/src/gui/widgets/bpmcalculatorwidget.cpp b/src/gui/widgets/bpmcalculatorwidget.cpp index 7f70cdc..88e9afc 100644 --- a/src/gui/widgets/bpmcalculatorwidget.cpp +++ b/src/gui/widgets/bpmcalculatorwidget.cpp @@ -41,12 +41,12 @@ void BPMCalculatorWidget::update(const sf::Time& dt) Window::update(dt); const auto beat_info = _bpm_calculator->fetchApproximatedInfo(); - if (beat_info.rate_per_microsecond != 0) + if (beat_info.BPM != 0) { - _bpm_value.setString(std::to_string(static_cast(beat_info.rate_per_microsecond))); + _bpm_value.setString(std::to_string(static_cast(beat_info.BPM))); const microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(); - const auto time_relation = static_cast(beat_info.average_interval) / static_cast(until_beat); + const auto time_relation = static_cast(beat_info.interval) / static_cast(until_beat); const auto slider_path_left = _slider->rect().width / time_relation; if (slider_path_left < 50) { @@ -69,6 +69,7 @@ void BPMCalculatorWidget::draw(sf::RenderTarget& target, sf::RenderStates states { _slider->draw(target, states); _button_start->draw(target, states); + _button_stop->draw(target, states); target.draw(_bpm_value, states); } } @@ -84,6 +85,10 @@ void BPMCalculatorWidget::setRect(const sf::FloatRect& rect) _button_start->setPosition({_window_content.getGlobalBounds().left + rect.width / 7, _window_content.getGlobalBounds().top + _window_content.getGlobalBounds().height - 40}); + _button_stop->setRect(sf::FloatRect{0, 0, rect.width / 10 * 3, 30}); + _button_stop->setPosition({_window_content.getGlobalBounds().left + rect.width / 7, + _window_content.getGlobalBounds().top + _window_content.getGlobalBounds().height - 40}); + _bpm_value.setPosition({_window_content.getGlobalBounds().left + rect.width / 8, _window_content.getGlobalBounds().top + rect.height / 8 }); } @@ -105,12 +110,35 @@ void BPMCalculatorWidget::init() auto& bpm_calculator = _bpm_calculator; _button_start = std::make_shared("Start", _font); - _button_start->setCallback([bpm_calculator, button_start=_button_start]() + _button_stop = std::make_shared("Stop", _font); + + _button_start->setCallback([bpm_calculator, button_start=_button_start, button_stop=_button_stop]() { - bpm_calculator->music()->play(); + bpm_calculator->music()->play(); // Remove when global play/stop available bpm_calculator->start(); button_start->setVisibility(false); + button_stop->setVisibility(true); + }); + + _button_stop->setCallback([bpm_calculator, button_start=_button_start, button_stop=_button_stop]() + { + bpm_calculator->music()->stop(); // Remove when global play/stop available + bpm_calculator->stop(); + button_start->setVisibility(true); + button_stop->setVisibility(false); }); addChild(_button_start); + addChild(_button_stop); + + _button_stop->setVisibility(false); +} + +void BPMCalculatorWidget::setVisibility(bool is_visible) +{ + Window::setVisibility(is_visible); + + bool can_stop = _bpm_calculator->calculating(); + _button_stop->setVisibility(can_stop); + _button_start->setVisibility(!can_stop); } diff --git a/src/gui/widgets/bpmcalculatorwidget.h b/src/gui/widgets/bpmcalculatorwidget.h index 61433e9..2d2f14d 100644 --- a/src/gui/widgets/bpmcalculatorwidget.h +++ b/src/gui/widgets/bpmcalculatorwidget.h @@ -23,10 +23,13 @@ public: virtual void setPosition(const sf::Vector2f& position) override; virtual void move(const sf::Vector2f& delta) override; + virtual void setVisibility(bool is_visible = true) override; + void init(); private: std::shared_ptr _button_start; + std::shared_ptr _button_stop; std::shared_ptr _bpm_calculator; std::shared_ptr _slider; diff --git a/src/tools/beatutils.cpp b/src/tools/beatutils.cpp index 86275be..a9f444f 100644 --- a/src/tools/beatutils.cpp +++ b/src/tools/beatutils.cpp @@ -13,11 +13,12 @@ auto beat_utils::calculateBeatRateInfo(const std::vector& approximate_ long double average = static_cast(sum) / static_cast(amount); + const int bpm = static_cast(60000000. / average); return BeatInfo { - 60000000. / average, - static_cast(average) + bpm, + static_cast(1. / static_cast(bpm) * 60000000.) }; } diff --git a/src/tools/bpmcalculator.cpp b/src/tools/bpmcalculator.cpp index 6970ab7..52f1540 100644 --- a/src/tools/bpmcalculator.cpp +++ b/src/tools/bpmcalculator.cpp @@ -41,6 +41,11 @@ void BPMCalculator::stop() _calculating = false; } +bool BPMCalculator::calculating() const +{ + return _calculating; +} + void BPMCalculator::click() { if (!_calculating) @@ -64,10 +69,10 @@ void BPMCalculator::click() const beat_utils::BeatInfo& BPMCalculator::fetchApproximatedInfo() { - //if (!_need_recalculate) - //return _approximated_info; + if (!_need_recalculate) + return _approximated_info; - //_need_recalculate = false; + _need_recalculate = false; bool hasEnoughDeltas = _deltas.size() >= 8; @@ -95,7 +100,7 @@ void BPMCalculator::moveStartingOffsetBy(microsec shift) microsec BPMCalculator::fetchTimeUntilNextBeat() { - const microsec actual_offset = _music->fetchOffset() - _first_click_offset; + const microsec actual_offset = _music->fetchOffset() - getStartingOffset(); - return actual_offset % fetchApproximatedInfo().average_interval; + return actual_offset % fetchApproximatedInfo().interval; }