MCC
Loading...
Searching...
No Matches
NoteValue.h
1#ifndef MCC_RHYTHM_NOTE_VALUE_H
2#define MCC_RHYTHM_NOTE_VALUE_H
3
4#include <stdint.h>
5
6#include <MCC_BuildSettings.h>
7
8namespace MCC {
9
21class NoteValue {
22 static constexpr uint8_t InvalidBaseExponent = 0xFFu;
23 static constexpr uint8_t MaximumBaseExponent = 8u;
24
25 uint8_t _baseExponent;
26 uint8_t _dots;
27
28 static constexpr bool IsDotCountValid(int32_t dots) noexcept {
29 return dots >= 0 && dots <= 4;
30 }
31
32 constexpr NoteValue(uint8_t baseExponent, int32_t dots) noexcept
33 : _baseExponent(baseExponent <= MaximumBaseExponent && IsDotCountValid(dots)
34 ? baseExponent
35 : InvalidBaseExponent),
36 _dots(baseExponent <= MaximumBaseExponent && IsDotCountValid(dots)
37 ? static_cast<uint8_t>(dots)
38 : 0u) {}
39
40public:
42 static constexpr uint8_t MaximumDots = 4u;
43
45 static constexpr uint8_t InvalidDotCount = 0xFFu;
46
48 constexpr NoteValue() noexcept : _baseExponent(InvalidBaseExponent), _dots(0u) {}
49
51 static constexpr NoteValue Invalid() noexcept { return NoteValue(); }
52
54 static constexpr NoteValue Whole(int32_t dots = 0) noexcept {
55 return NoteValue(0u, dots);
56 }
57
59 static constexpr NoteValue Half(int32_t dots = 0) noexcept {
60 return NoteValue(1u, dots);
61 }
62
64 static constexpr NoteValue Quarter(int32_t dots = 0) noexcept {
65 return NoteValue(2u, dots);
66 }
67
69 static constexpr NoteValue Eighth(int32_t dots = 0) noexcept {
70 return NoteValue(3u, dots);
71 }
72
74 static constexpr NoteValue Sixteenth(int32_t dots = 0) noexcept {
75 return NoteValue(4u, dots);
76 }
77
79 static constexpr NoteValue ThirtySecond(int32_t dots = 0) noexcept {
80 return NoteValue(5u, dots);
81 }
82
84 static constexpr NoteValue SixtyFourth(int32_t dots = 0) noexcept {
85 return NoteValue(6u, dots);
86 }
87
89 static constexpr NoteValue OneHundredTwentyEighth(int32_t dots = 0) noexcept {
90 return NoteValue(7u, dots);
91 }
92
94 static constexpr NoteValue TwoHundredFiftySixth(int32_t dots = 0) noexcept {
95 return NoteValue(8u, dots);
96 }
97
104 static MCC_CONSTEXPR14 NoteValue FromDenominator(
105 int32_t baseDenominator, int32_t dots = 0) noexcept {
106 switch (baseDenominator) {
107 case 1: return Whole(dots);
108 case 2: return Half(dots);
109 case 4: return Quarter(dots);
110 case 8: return Eighth(dots);
111 case 16: return Sixteenth(dots);
112 case 32: return ThirtySecond(dots);
113 case 64: return SixtyFourth(dots);
114 case 128: return OneHundredTwentyEighth(dots);
115 case 256: return TwoHundredFiftySixth(dots);
116 default: return Invalid();
117 }
118 }
119
121 constexpr bool IsValid() const noexcept {
122 return _baseExponent != InvalidBaseExponent;
123 }
124
126 constexpr bool IsDotted() const noexcept { return IsValid() && _dots != 0u; }
127
129 constexpr uint16_t BaseDenominator() const noexcept {
130 return IsValid()
131 ? static_cast<uint16_t>(uint16_t(1u) << _baseExponent)
132 : uint16_t(0u);
133 }
134
136 constexpr uint8_t DotCount() const noexcept {
137 return IsValid() ? _dots : InvalidDotCount;
138 }
139
141 constexpr uint16_t Numerator() const noexcept {
142 return IsValid()
143 ? static_cast<uint16_t>((uint16_t(1u) << (_dots + 1u)) - 1u)
144 : uint16_t(0u);
145 }
146
148 constexpr uint16_t Denominator() const noexcept {
149 return IsValid()
150 ? static_cast<uint16_t>(uint16_t(1u) << (_baseExponent + _dots))
151 : uint16_t(0u);
152 }
153
155 constexpr NoteValue WithDots(int32_t dots) const noexcept {
156 return IsValid() ? NoteValue(_baseExponent, dots) : Invalid();
157 }
158
160 friend constexpr bool operator==(NoteValue a, NoteValue b) noexcept {
161 return a._baseExponent == b._baseExponent && a._dots == b._dots;
162 }
163
164 friend constexpr bool operator!=(NoteValue a, NoteValue b) noexcept {
165 return !(a == b);
166 }
167
173 friend constexpr bool operator<(NoteValue a, NoteValue b) noexcept {
174 return a.IsValid() != b.IsValid()
175 ? a.IsValid()
176 : (!a.IsValid()
177 ? false
178 : static_cast<uint32_t>(a.Numerator()) * b.Denominator()
179 < static_cast<uint32_t>(b.Numerator()) * a.Denominator());
180 }
181
182 friend constexpr bool operator>(NoteValue a, NoteValue b) noexcept {
183 return b < a;
184 }
185
186 friend constexpr bool operator<=(NoteValue a, NoteValue b) noexcept {
187 return !(b < a);
188 }
189
190 friend constexpr bool operator>=(NoteValue a, NoteValue b) noexcept {
191 return !(a < b);
192 }
193};
194
195} // namespace MCC
196
197#endif // MCC_RHYTHM_NOTE_VALUE_H
Exact written note length: a power-of-two base and zero to four dots.
Definition NoteValue.h:21
static constexpr NoteValue Invalid() noexcept
Returns the invalid note value.
Definition NoteValue.h:51
constexpr uint8_t DotCount() const noexcept
Returns the number of dots, or InvalidDotCount when invalid.
Definition NoteValue.h:136
static constexpr NoteValue TwoHundredFiftySixth(int32_t dots=0) noexcept
Creates a 256th note, optionally augmented by dots.
Definition NoteValue.h:94
static constexpr uint8_t MaximumDots
Largest supported number of augmentation dots.
Definition NoteValue.h:42
static constexpr NoteValue Eighth(int32_t dots=0) noexcept
Creates an eighth note, optionally augmented by dots.
Definition NoteValue.h:69
constexpr bool IsDotted() const noexcept
Returns true when this valid value has augmentation dots.
Definition NoteValue.h:126
constexpr bool IsValid() const noexcept
Returns true unless this is the invalid note value.
Definition NoteValue.h:121
constexpr uint16_t Numerator() const noexcept
Returns the exact reduced numerator relative to a whole note.
Definition NoteValue.h:141
static MCC_CONSTEXPR14 NoteValue FromDenominator(int32_t baseDenominator, int32_t dots=0) noexcept
Creates a value from the undotted base denominator.
Definition NoteValue.h:104
static constexpr NoteValue Sixteenth(int32_t dots=0) noexcept
Creates a sixteenth note, optionally augmented by dots.
Definition NoteValue.h:74
static constexpr NoteValue OneHundredTwentyEighth(int32_t dots=0) noexcept
Creates a 128th note, optionally augmented by dots.
Definition NoteValue.h:89
static constexpr NoteValue Half(int32_t dots=0) noexcept
Creates a half note, optionally augmented by dots.
Definition NoteValue.h:59
static constexpr NoteValue SixtyFourth(int32_t dots=0) noexcept
Creates a sixty-fourth note, optionally augmented by dots.
Definition NoteValue.h:84
static constexpr uint8_t InvalidDotCount
Sentinel returned by DotCount() for an invalid value.
Definition NoteValue.h:45
static constexpr NoteValue Whole(int32_t dots=0) noexcept
Creates a whole note, optionally augmented by dots.
Definition NoteValue.h:54
constexpr uint16_t Denominator() const noexcept
Returns the exact reduced denominator relative to a whole note.
Definition NoteValue.h:148
constexpr uint16_t BaseDenominator() const noexcept
Returns the undotted denominator (1 through 256), or 0.
Definition NoteValue.h:129
static constexpr NoteValue ThirtySecond(int32_t dots=0) noexcept
Creates a thirty-second note, optionally augmented by dots.
Definition NoteValue.h:79
constexpr NoteValue WithDots(int32_t dots) const noexcept
Returns the same base with dots, or invalid for bad input.
Definition NoteValue.h:155
friend constexpr bool operator<(NoteValue a, NoteValue b) noexcept
Orders by exact duration, with invalid values after valid values. Written values with equal duration ...
Definition NoteValue.h:173
static constexpr NoteValue Quarter(int32_t dots=0) noexcept
Creates a quarter note, optionally augmented by dots.
Definition NoteValue.h:64
friend constexpr bool operator==(NoteValue a, NoteValue b) noexcept
Written equality: the base and dot count must both match.
Definition NoteValue.h:160
constexpr NoteValue() noexcept
Creates the invalid note value.
Definition NoteValue.h:48
Music Composition Core public namespace.
Definition Version.h:4