8#include "utils/traits.h"
9#include "utils/types.h"
11#include <fmt/format.h>
12#include <nlohmann/json.hpp>
13#include <type_safe/strong_typedef.hpp>
19 : type_safe::strong_typedef<FramesPerTick, double>,
20 type_safe::strong_typedef_op::equality_comparison<FramesPerTick>,
21 type_safe::strong_typedef_op::relational_comparison<FramesPerTick>
23 using FramesPerTickTag = void;
24 using type_safe::strong_typedef<FramesPerTick,
double>::strong_typedef;
26 explicit FramesPerTick () =
default;
30static_assert (std::regular<FramesPerTick>);
33 : type_safe::strong_typedef<TicksPerFrame, double>,
34 type_safe::strong_typedef_op::equality_comparison<TicksPerFrame>,
35 type_safe::strong_typedef_op::relational_comparison<TicksPerFrame>
37 using TicksPerFrameTag = void;
38 using type_safe::strong_typedef<TicksPerFrame,
double>::strong_typedef;
40 explicit TicksPerFrame () =
default;
44static_assert (std::regular<TicksPerFrame>);
49 return TicksPerFrame (1.0 / type_safe::get (frames_per_tick));
51static constexpr FramesPerTick
52to_frames_per_tick (
const TicksPerFrame &ticks_per_frame)
54 return FramesPerTick (1.0 / type_safe::get (ticks_per_frame));
74 static constexpr int TICKS_PER_QUARTER_NOTE = 960;
75 static constexpr int TICKS_PER_SIXTEENTH_NOTE = 240;
76 static constexpr double TICKS_PER_QUARTER_NOTE_DBL = 960.0;
77 static constexpr double TICKS_PER_SIXTEENTH_NOTE_DBL = 240.0;
78 static constexpr double TICKS_PER_NINETYSIXTH_NOTE_DBL = 40.0;
79 static constexpr int POSITION_MAX_BAR = 160000;
83 Position () =
default;
93 int sixteenths_per_beat,
105 from_frames (frames, ticks_per_frame);
132 bool ticks_equal (
const Position &other)
const
135 <= std::numeric_limits<double>::epsilon ();
139 static const Position &
get_min (
const Position &p1,
const Position &p2)
145 static const Position &
get_max (
const Position &p1,
const Position &p2)
150 bool is_positive ()
const {
return frames_ >= 0 &&
ticks_ >= 0; }
175 bool is_between_excl_both (
const Position &start,
const Position &end)
const
181 is_between_excl_1st_incl_2nd (
const Position &start,
const Position &end)
const
231 add_ms (ms, sample_rate, ticks_per_frame);
238 add_bars (bars, ticks_per_bar, frames_per_tick);
242 add_bars (
int bars,
int ticks_per_bar, dsp::FramesPerTick frames_per_tick);
245 add_beats (
int beats,
int ticks_per_beat, dsp::FramesPerTick frames_per_tick);
247 void add_sixteenths (
int sixteenths, dsp::FramesPerTick frames_per_tick)
249 add_ticks (sixteenths * TICKS_PER_SIXTEENTH_NOTE_DBL, frames_per_tick);
252 void add_ticks (
double ticks, dsp::FramesPerTick frames_per_tick)
272 tmp.from_frames (frames, ticks_per_frame);
279 add_frames (ms_to_frames (ms, sample_rate), ticks_per_frame);
283 add_minutes (
int mins,
sample_rate_t sample_rate, TicksPerFrame ticks_per_frame)
285 add_frames (ms_to_frames (mins * 60 * 1'000, sample_rate), ticks_per_frame);
291 TicksPerFrame ticks_per_frame)
294 ms_to_frames (
static_cast<double> (seconds * 1'000), sample_rate),
327 const Position &start_pos,
328 const Position &end_pos,
340 int sixteenths_per_beat,
342 int decimal_places = 4)
const;
346 int sixteenths_per_beat,
349 int decimal_places = 4)
const;
356 int sixteenths_per_beat,
359 static void print_range (
361 int sixteenths_per_beat,
373 bool include_current,
384 bool include_current,
414 int get_bars (
bool start_at_one,
int ticks_per_bar)
const;
424 get_beats (
bool start_at_one,
int beats_per_bar,
int ticks_per_beat)
const;
436 int sixteenths_per_beat,
446 void set_to_position (
const Position &pos)
469 friend auto operator<=> (
const Position &lhs,
const Position &rhs)
476 return (lhs <=> rhs) == 0;
507 return fmt::format (
"{:.3f} ticks ({} frames)", p.
ticks_, p.
frames_);
Represents the position of an object.
bool is_between_excl_2nd(const Position &start, const Position &end) const
Returns if the position is after or equal to start and before end.
int get_total_sixteenths(bool include_current, dsp::FramesPerTick frames_per_tick) const
Returns the total number of sixteenths not including the current one.
static const Position & get_min(const Position &p1, const Position &p2)
Returns minimum of p1 and p2.
int get_total_beats(bool include_current, int beats_per_bar, int ticks_per_beat, FramesPerTick frames_per_tick) const
Returns the total number of beats.
int get_sixteenths(bool start_at_one, int beats_per_bar, int sixteenths_per_beat, FramesPerTick frames_per_tick) const
Gets the sixteenths of the position.
static const Position & get_max(const Position &p1, const Position &p2)
Returns maximum of p1 and p2.
void update_ticks_from_frames(TicksPerFrame ticks_per_frame)
Updates ticks.
void from_seconds(double secs, sample_rate_t sample_rate, TicksPerFrame ticks_per_frame)
Converts seconds to position and puts the result in the given Position.
Position(const char *str, int beats_per_bar, int sixteenths_per_beat, FramesPerTick frames_per_tick)
Parses a position from the given string.
void print(int beats_per_bar, int sixteenths_per_beat, FramesPerTick frames_per_tick) const
Prints the Position in the "0.0.0.0" form.
void change_sign()
Changes the sign of the position.
friend auto operator<=>(const Position &lhs, const Position &rhs)
Note: only checks frames.
void update_frames_from_ticks(FramesPerTick frames_per_tick)
Updates frames.
signed_ms_t to_ms(sample_rate_t sample_rate) const
Returns the Position in milliseconds.
double get_total_ticks() const
Getter.
bool is_between_incl_2nd(const Position &start, const Position &end) const
Returns if the position is after or equal to start and before or equal to end (ie,...
int get_bars(bool start_at_one, int ticks_per_bar) const
Gets the bars of the position.
signed_frame_t frames_
Position in frames (samples).
void add_frames(signed_frame_t frames, TicksPerFrame ticks_per_frame)
Adds the frames to the position and updates the rest of the fields, and makes sure the frames are sti...
void set_to_bar(int bar, int ticks_per_bar, dsp::FramesPerTick frames_per_tick)
Sets position to given bar.
std::string to_string(int beats_per_bar, int sixteenths_per_beat, FramesPerTick frames_per_tick, int decimal_places=4) const
Creates a string in the form of "0.0.0.0" from the given position.
static signed_frame_t get_frames_from_ticks(double ticks, dsp::FramesPerTick frames_per_tick)
Converts ticks to frames.
Position(signed_frame_t frames, TicksPerFrame ticks_per_frame)
Construct from total number of frames.
bool is_between_frames_excluding_2nd(signed_frame_t f1, signed_frame_t f2) const
Whether the position starts on or after f1 and before f2 (ie, the position is between f1 and f2,...
static signed_frame_t compare_frames(const Position &p1, const Position &p2)
Compares 2 positions based on their frames.
Position & get_closest_position(Position &p1, Position &p2) const
Returns the closest position.
Position(double ticks, dsp::FramesPerTick frames_per_tick)
Construct from total number of ticks.
void from_ticks(double ticks, dsp::FramesPerTick frames_per_tick)
Sets position to the given total tick count.
int get_total_bars(bool include_current, int ticks_per_bar, FramesPerTick frames_per_tick) const
Returns the total number of beats.
int get_beats(bool start_at_one, int beats_per_bar, int ticks_per_beat) const
Gets the beats of the position.
double ticks_
Precise total number of ticks.
void set_to_midway_pos(const Position &start_pos, const Position &end_pos, FramesPerTick frames_per_tick)
Sets the position to the midway point between the two given positions.
signed_frame_t get_total_frames() const
Getter.
double get_ticks_part(FramesPerTick frames_per_tick) const
Gets the ticks of the position.
uint32_t sample_rate_t
Sample rate.
signed_frame_t signed_ms_t
Signed millisecond index.
signed_frame_t signed_sec_t
Signed second index.
int_fast64_t signed_frame_t
Signed type for frame index.