Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
beat_division.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <compare>
7#include <cstddef>
8#include <cstdint>
9#include <limits>
10
11namespace pulp::timebase {
12
13// Persisted ordinal vocabulary. New divisions are appended immediately before
14// Count; existing entries must never be reordered or reused.
39
41 std::int64_t numerator = 0;
42 std::int64_t denominator = 1;
43 constexpr auto operator<=>(const BeatFraction&) const = default;
44};
45
51
52namespace detail {
53
55 {4, 1}, {6, 1}, {8, 3}, {2, 1}, {3, 1}, {4, 3}, {1, 1}, {3, 2}, {2, 3}, {1, 2}, {3, 4},
56 {1, 3}, {1, 4}, {3, 8}, {1, 6}, {1, 8}, {3, 16}, {1, 12}, {1, 16}, {3, 32}, {1, 24},
57};
58
59static_assert(sizeof(kBeatDivisionFractions) / sizeof(kBeatDivisionFractions[0]) ==
60 static_cast<std::size_t>(BeatDivision::Count));
61
62} // namespace detail
63
68 BeatFraction fallback) noexcept {
69 const auto index = static_cast<std::uint8_t>(division);
70 if (index >= static_cast<std::uint8_t>(BeatDivision::Count))
71 return fallback;
73}
74
75// Exact quarter-note beat value. Fractions are reduced and positive.
77beat_fraction(BeatDivision division) noexcept {
78 const auto index = static_cast<std::uint8_t>(division);
79 if (index >= static_cast<std::uint8_t>(BeatDivision::Count))
81 return runtime::Ok(beat_fraction_or(division, {}));
82}
83
84// Converts the vocabulary to the repository's exact document tick lattice.
85// Failure is explicit if a future appended fraction does not divide that
86// lattice or would exceed TickDuration.
88division_ticks(BeatDivision division) noexcept {
89 const auto fraction = beat_fraction(division);
90 if (!fraction)
91 return runtime::Err(fraction.error());
92 const auto value = fraction.value();
93 if (value.denominator <= 0 || kTicksPerQuarter % value.denominator != 0)
95 const auto unit = kTicksPerQuarter / value.denominator;
96 if (value.numerator > 0 && unit > std::numeric_limits<std::int64_t>::max() / value.numerator)
98 return runtime::Ok(TickDuration{unit * value.numerator});
99}
100
101} // namespace pulp::timebase
Result<T, E> — either holds a T or an E, never both.
Definition result.hpp:76
Err(E) -> Err< E >
@ Ok
No error; bytes is authoritative.
Definition stream.hpp:32
Definition beat_division.hpp:52
constexpr BeatFraction kBeatDivisionFractions[]
Definition beat_division.hpp:54
Definition beat_division.hpp:11
BeatDivision
Definition beat_division.hpp:15
@ HalfDotted
Definition beat_division.hpp:20
@ ThirtySecond
Definition beat_division.hpp:31
@ SixteenthTriplet
Definition beat_division.hpp:30
@ SixteenthDotted
Definition beat_division.hpp:29
@ SixtyFourth
Definition beat_division.hpp:34
@ Eighth
Definition beat_division.hpp:25
@ EighthTriplet
Definition beat_division.hpp:27
@ ThirtySecondTriplet
Definition beat_division.hpp:33
@ WholeDotted
Definition beat_division.hpp:17
@ ThirtySecondDotted
Definition beat_division.hpp:32
@ QuarterTriplet
Definition beat_division.hpp:24
@ EighthDotted
Definition beat_division.hpp:26
@ Quarter
Definition beat_division.hpp:22
@ Half
Definition beat_division.hpp:19
@ Whole
Definition beat_division.hpp:16
@ SixtyFourthTriplet
Definition beat_division.hpp:36
@ Sixteenth
Definition beat_division.hpp:28
@ QuarterDotted
Definition beat_division.hpp:23
@ SixtyFourthDotted
Definition beat_division.hpp:35
@ HalfTriplet
Definition beat_division.hpp:21
@ Count
Definition beat_division.hpp:37
@ WholeTriplet
Definition beat_division.hpp:18
constexpr std::int64_t kTicksPerQuarter
Definition tick.hpp:54
runtime::Result< BeatFraction, BeatDivisionError > beat_fraction(BeatDivision division) noexcept
Definition beat_division.hpp:77
runtime::Result< TickDuration, BeatDivisionError > division_ticks(BeatDivision division) noexcept
Definition beat_division.hpp:88
BeatDivisionError
Definition beat_division.hpp:46
@ InvalidDivision
Definition beat_division.hpp:47
@ NotExactlyRepresentable
Definition beat_division.hpp:48
@ RangeExceeded
Definition beat_division.hpp:49
constexpr BeatFraction beat_fraction_or(BeatDivision division, BeatFraction fallback) noexcept
Returns the exact fraction for division, or fallback for an invalid ordinal.
Definition beat_division.hpp:67
Result<T, E> — success / failure union for fallible operations.
Definition beat_division.hpp:40
constexpr auto operator<=>(const BeatFraction &) const =default
std::int64_t denominator
Definition beat_division.hpp:42
std::int64_t numerator
Definition beat_division.hpp:41
Definition tick.hpp:56