diff --git a/include/tools/bpmcalculator.h b/include/tools/bpmcalculator.h new file mode 100644 index 0000000..04ae469 --- /dev/null +++ b/include/tools/bpmcalculator.h @@ -0,0 +1,23 @@ +#pragma once + +#include "tools/music.h" +#include +#include + +class BPMCalculator +{ +public: + explicit BPMCalculator(const std::shared_ptr& music); + void setMusic(const std::shared_ptr& music); + + void startListening(const microsec& offset); + void stopListening(); + + void click(); + int getCurrentApproximation() const; + +private: + std::shared_ptr _music; + std::vector _deltas; + microsec _previous_click_offset; +}; diff --git a/include/tools/mathutils.h b/include/tools/mathutils.h index bcf58a4..cd50180 100644 --- a/include/tools/mathutils.h +++ b/include/tools/mathutils.h @@ -1,4 +1,5 @@ #pragma once + #include using microsec = sf::Int64; diff --git a/src/tools/bpmcalculator.cpp b/src/tools/bpmcalculator.cpp new file mode 100644 index 0000000..21a8caf --- /dev/null +++ b/src/tools/bpmcalculator.cpp @@ -0,0 +1,54 @@ +#include "tools/bpmcalculator.h" +#include +#include +#include + +constexpr microsec MICROSECONDS_IN_MINUTE = 60000000; + +BPMCalculator::BPMCalculator(const std::shared_ptr& music) : + _music(music), + _previous_click_offset(0) +{} + +void BPMCalculator::setMusic(const std::shared_ptr& music) +{ + _music = music; +} + +void BPMCalculator::startListening(const microsec &offset) +{ + _deltas.clear(); + _previous_click_offset = 0; + _music->setOffset(offset); + _music->play(); +} + +void BPMCalculator::stopListening() +{ + _music->stop(); +} + +void BPMCalculator::click() +{ + const microsec click_offset = _music->fetchOffset(); + + if (_previous_click_offset == 0) + { + _previous_click_offset = click_offset; + return; + } + + const microsec delta = click_offset - _previous_click_offset; + _deltas.emplace_back(delta); + + _previous_click_offset = click_offset; +} + +int BPMCalculator::getCurrentApproximation() const +{ + const microsec sum = std::accumulate(_deltas.begin(), _deltas.end(), 0); + + return (sum == 0) + ? 0. + : static_cast(static_cast(MICROSECONDS_IN_MINUTE) / (static_cast(sum) / static_cast(_deltas.size()))); +}