Implement BPMCalculator for internal bpm calculation in level editor

selection
NaiJi ✨ 3 years ago
parent 8c3f2a112f
commit befd7e5cf9

@ -0,0 +1,23 @@
#pragma once
#include "tools/music.h"
#include <memory>
#include <vector>
class BPMCalculator
{
public:
explicit BPMCalculator(const std::shared_ptr<Music>& music);
void setMusic(const std::shared_ptr<Music>& music);
void startListening(const microsec& offset);
void stopListening();
void click();
int getCurrentApproximation() const;
private:
std::shared_ptr<Music> _music;
std::vector<microsec> _deltas;
microsec _previous_click_offset;
};

@ -1,4 +1,5 @@
#pragma once
#include <SFML/System/Clock.hpp>
using microsec = sf::Int64;

@ -0,0 +1,54 @@
#include "tools/bpmcalculator.h"
#include <cmath>
#include <numeric>
#include <iostream>
constexpr microsec MICROSECONDS_IN_MINUTE = 60000000;
BPMCalculator::BPMCalculator(const std::shared_ptr<Music>& music) :
_music(music),
_previous_click_offset(0)
{}
void BPMCalculator::setMusic(const std::shared_ptr<Music>& 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<int>(static_cast<float>(MICROSECONDS_IN_MINUTE) / (static_cast<float>(sum) / static_cast<float>(_deltas.size())));
}
Loading…
Cancel
Save