#include "tools/bpmcalculator.h" #include #include #include BPMCalculator::BPMCalculator(const std::shared_ptr& music) : _music(music) { reset(); } void BPMCalculator::reset() { _calculating = false; _deltas.clear(); _previous_click_offset = 0; _first_click_offset = 0; _need_recalculate = true; } void BPMCalculator::setMusic(const std::shared_ptr& music) { _music = music; reset(); } std::shared_ptr BPMCalculator::music() const { return _music; } void BPMCalculator::start() { reset(); _calculating = true; } void BPMCalculator::stop() { _calculating = false; } bool BPMCalculator::calculating() const { return _calculating; } void BPMCalculator::click() { if (!_calculating) return; const microsec click_offset = _music->fetchOffset(); _need_recalculate = true; if (_previous_click_offset == 0) { _previous_click_offset = click_offset; _first_click_offset = click_offset; return; } const microsec delta = click_offset - _previous_click_offset; _deltas.emplace_back(delta); _previous_click_offset = click_offset; } const beat_utils::BeatInfo& BPMCalculator::fetchApproximatedInfo() { if (!_need_recalculate) return _approximated_info; _need_recalculate = false; bool hasEnoughDeltas = _deltas.size() >= 8; _approximated_info = (!hasEnoughDeltas) ? beat_utils::BeatInfo{} : beat_utils::calculateBeatRateInfo(_deltas); return _approximated_info; } microsec BPMCalculator::getStartingOffset() const { return _first_click_offset; } void BPMCalculator::setStartingOffset(microsec offset) { _first_click_offset = offset; } void BPMCalculator::moveStartingOffsetBy(microsec shift) { _first_click_offset += shift; } microsec BPMCalculator::fetchTimeUntilNextBeat() { const microsec actual_offset = _music->fetchOffset() - getStartingOffset(); return actual_offset % fetchApproximatedInfo().interval; }