F.E.I.S/src/better_timing.hpp

121 lines
3.3 KiB
C++
Raw Normal View History

#pragma once
#include <SFML/Config.hpp>
#include <algorithm>
#include <iterator>
#include <map>
2022-04-06 15:47:04 +02:00
#include <set>
#include <sstream>
#include <vector>
2022-04-14 01:26:31 +02:00
#include <json.hpp>
#include <SFML/System/Time.hpp>
#include "special_numeric_types.hpp"
namespace better {
struct SecondsAtBeat {
Decimal seconds;
Fraction beats;
};
class BPMAtBeat {
public:
2022-04-03 15:59:05 +02:00
BPMAtBeat(Decimal bpm, Fraction beats);
Decimal get_bpm() const;
2022-04-09 00:54:06 +02:00
double get_bpm_as_double() const;
2022-04-03 15:59:05 +02:00
Fraction get_beats() const;
private:
Decimal bpm;
2022-04-09 00:54:06 +02:00
double bpm_as_double;
2022-04-03 15:59:05 +02:00
Fraction beats;
};
class BPMEvent {
public:
BPMEvent(Fraction beats, double seconds, Decimal bpm);
Decimal get_bpm() const;
2022-04-09 00:54:06 +02:00
double get_bpm_as_double() const;
Fraction get_beats() const;
2022-04-09 00:54:06 +02:00
double get_seconds() const;
2022-04-14 00:13:38 +02:00
bool operator==(const BPMEvent&) const = default;
friend std::ostream& operator<<(std::ostream& out, const BPMEvent& b);
private:
Decimal bpm;
2022-04-09 00:54:06 +02:00
double bpm_as_double;
Fraction beats;
double seconds;
};
2022-04-04 22:03:10 +02:00
struct OrderByBeats {
2022-04-06 15:47:04 +02:00
template<class T>
bool operator()(const T& a, const T& b) const {
return a.get_beats() < b.get_beats();
}
};
2022-04-04 22:03:10 +02:00
struct OrderBySeconds {
2022-04-06 15:47:04 +02:00
template<class T>
bool operator()(const T& a, const T& b) const {
return a.get_seconds() < b.get_seconds();
}
};
class Timing {
public:
2022-04-01 02:30:32 +02:00
Timing();
Timing(const std::vector<BPMAtBeat>& events, const Decimal& offset);
double seconds_at(Fraction beats) const;
double seconds_between(Fraction beat_a, Fraction beat_b) const;
sf::Time time_at(Fraction beats) const;
2022-03-17 02:50:30 +01:00
sf::Time time_between(Fraction beat_a, Fraction beat_b) const;
2022-03-17 02:50:30 +01:00
Fraction beats_at(sf::Time time) const;
Fraction beats_at(double seconds) const;
2022-04-02 04:10:09 +02:00
nlohmann::ordered_json dump_to_memon_1_0_0() const;
2022-04-03 15:59:05 +02:00
static Timing load_from_memon_1_0_0(const nlohmann::json& json);
static Timing load_from_memon_legacy(const nlohmann::json& metadata);
bool operator==(const Timing&) const = default;
friend std::ostream& operator<<(std::ostream& out, const Timing& t);
friend fmt::formatter<better::Timing>;
private:
2022-04-09 00:54:06 +02:00
Decimal offset;
double offset_as_double;
2022-04-04 22:03:10 +02:00
std::set<BPMEvent, OrderByBeats> events_by_beats;
std::set<BPMEvent, OrderBySeconds> events_by_seconds;
};
2022-04-14 01:26:31 +02:00
}
template <>
struct fmt::formatter<better::BPMEvent>: formatter<string_view> {
2022-04-14 01:26:31 +02:00
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(const better::BPMEvent& b, FormatContext& ctx) {
2022-04-14 01:26:31 +02:00
return format_to(
ctx.out(),
"BPMEvent(beats: {}, bpm: {})",
b.get_beats(),
b.get_bpm()
);
}
};
template <>
struct fmt::formatter<better::Timing>: formatter<string_view> {
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(const better::Timing& t, FormatContext& ctx) {
return format_to(
ctx.out(),
"Timing(offset: {}, events: [{}])",
t.offset,
fmt::join(t.events_by_beats, ", ")
2022-04-14 01:26:31 +02:00
);
}
};