1#ifndef MCC_RHYTHM_METER_H
2#define MCC_RHYTHM_METER_H
6#include <MCC_BuildSettings.h>
7#include <MCC/Rhythm/NoteValue.h>
39 static constexpr bool LooksCompound(int32_t numerator)
noexcept {
40 return numerator >= 6 && numerator % 3 == 0;
43 static constexpr bool IsUsable(
45 return numerator >= 1 && numerator <= 255 && IsUndotted(pulseValue) &&
49 static MCC_CONSTEXPR14 uint16_t GreatestCommonDivisor(
50 uint16_t a, uint16_t b)
noexcept {
52 const uint16_t remainder =
static_cast<uint16_t
>(a % b);
61 constexpr Meter() noexcept : _numerator(0u), _pulseValue() {}
70 MCC_CONSTEXPR14
Meter(int32_t numerator, int32_t denominator) noexcept
77 : _numerator(IsUsable(numerator, pulseValue)
78 ?
static_cast<uint8_t
>(numerator)
80 _pulseValue(IsUsable(numerator, pulseValue)
101 return beatCount >= 1 && beatCount <= 4 && IsUndotted(beatValue)
102 ?
Meter(beatCount, beatValue)
116 if (beatCount < 2 || beatCount > 85 || !beatValue.IsValid() ||
117 beatValue.DotCount() != 1u || beatValue.BaseDenominator() > 128u) {
122 static_cast<int32_t
>(beatValue.BaseDenominator()) * 2);
126 constexpr bool IsValid() const noexcept {
return _numerator != 0u; }
129 constexpr uint8_t
Numerator() const noexcept {
return _numerator; }
133 return _pulseValue.BaseDenominator();
140 constexpr uint8_t
PulseCount() const noexcept {
return _numerator; }
144 return !
IsValid() ? MeterKind::Invalid
145 : (_numerator <= 4u ? MeterKind::Simple
146 : (LooksCompound(_numerator)
147 ? MeterKind::Compound
148 : MeterKind::Irregular));
151 constexpr bool IsSimple() const noexcept {
return Kind() == MeterKind::Simple; }
152 constexpr bool IsCompound() const noexcept {
return Kind() == MeterKind::Compound; }
153 constexpr bool IsIrregular() const noexcept {
return Kind() == MeterKind::Irregular; }
159 return IsSimple() ? _numerator
160 : (IsCompound() ?
static_cast<uint8_t
>(_numerator / 3u) : 0u);
185 const uint16_t divisor = GreatestCommonDivisor(_numerator,
Denominator());
186 return static_cast<uint16_t
>(_numerator / divisor);
194 const uint16_t divisor = GreatestCommonDivisor(_numerator,
Denominator());
195 return static_cast<uint16_t
>(
Denominator() / divisor);
200 return a._numerator == b._numerator && a._pulseValue == b._pulseValue;
203 friend constexpr bool operator!=(
Meter a,
Meter b)
noexcept {
209 return a.IsValid() != b.IsValid() ? a.IsValid()
210 : (!a.IsValid() ?
false
211 : (a._numerator != b._numerator
212 ? a._numerator < b._numerator
213 : a.Denominator() < b.Denominator()));
216 friend constexpr bool operator>(
Meter a,
Meter b)
noexcept {
return b < a; }
217 friend constexpr bool operator<=(
Meter a,
Meter b)
noexcept {
return !(b < a); }
218 friend constexpr bool operator>=(
Meter a,
Meter b)
noexcept {
return !(a < b); }
229 return a.IsValid() && b.IsValid() &&
230 static_cast<uint32_t
>(a.Numerator()) * b.Denominator() ==
231 static_cast<uint32_t
>(b.Numerator()) * a.Denominator();
Exact written time signature and its simple/compound interpretation.
Definition Meter.h:31
MCC_CONSTEXPR14 uint16_t MeasureDenominator() const noexcept
Reduced denominator of the measure length in whole notes.
Definition Meter.h:190
constexpr uint8_t PulseCount() const noexcept
Returns the number of denominator units in the measure.
Definition Meter.h:140
constexpr MeterKind Kind() const noexcept
Classifies this meter as simple, compound, irregular or invalid.
Definition Meter.h:143
static MCC_CONSTEXPR14 Meter CommonTime() noexcept
Returns common time (4/4).
Definition Meter.h:88
static MCC_CONSTEXPR14 Meter CutTime() noexcept
Returns cut time (2/2).
Definition Meter.h:91
constexpr uint8_t BeatCount() const noexcept
Returns the interpreted beat count, or 0 for irregular/invalid.
Definition Meter.h:158
MCC_CONSTEXPR14 MCC::NoteValue BeatValue() const noexcept
Returns the beat value, or invalid for irregular/invalid meters.
Definition Meter.h:169
static constexpr Meter Simple(int32_t beatCount, MCC::NoteValue beatValue=MCC::NoteValue::Quarter()) noexcept
Creates a simple meter from one to four undotted beats.
Definition Meter.h:98
friend constexpr bool operator<(Meter a, Meter b) noexcept
Written order by numerator then denominator; invalid sorts last.
Definition Meter.h:208
constexpr MCC::NoteValue PulseValue() const noexcept
Returns the denominator unit, or the invalid NoteValue.
Definition Meter.h:137
constexpr uint16_t Denominator() const noexcept
Returns the written denominator, or 0 for the invalid meter.
Definition Meter.h:132
constexpr Meter(int32_t numerator, MCC::NoteValue pulseValue) noexcept
Creates a meter from its numerator and undotted denominator unit.
Definition Meter.h:76
static constexpr Meter Invalid() noexcept
Returns the invalid meter.
Definition Meter.h:85
constexpr Meter() noexcept
Creates the invalid meter (SPEC-ERR-2).
Definition Meter.h:61
MCC_CONSTEXPR14 Meter(int32_t numerator, int32_t denominator) noexcept
Creates the written signature numerator / denominator.
Definition Meter.h:70
constexpr bool IsValid() const noexcept
Returns true unless this is the invalid meter.
Definition Meter.h:126
friend constexpr bool operator==(Meter a, Meter b) noexcept
Written equality; equivalent durations need not be equal.
Definition Meter.h:199
constexpr uint8_t Numerator() const noexcept
Returns the written numerator, or 0 for the invalid meter.
Definition Meter.h:129
MCC_CONSTEXPR14 uint16_t MeasureNumerator() const noexcept
Reduced numerator of the measure length in whole notes.
Definition Meter.h:181
static MCC_CONSTEXPR14 Meter Compound(int32_t beatCount, MCC::NoteValue beatValue=MCC::NoteValue::Quarter(1)) noexcept
Creates a compound meter from dotted beats.
Definition Meter.h:113
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
constexpr bool IsValid() const noexcept
Returns true unless this is the invalid note value.
Definition NoteValue.h:121
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
constexpr uint16_t BaseDenominator() const noexcept
Returns the undotted denominator (1 through 256), or 0.
Definition NoteValue.h:129
static constexpr NoteValue Quarter(int32_t dots=0) noexcept
Creates a quarter note, optionally augmented by dots.
Definition NoteValue.h:64
MeterKind
Rhythmic interpretation of a written meter.
Definition Meter.h:12
constexpr bool HasSameMeasureDuration(Meter a, Meter b) noexcept
Returns true when two valid meters span the same whole-note length.
Definition Meter.h:228
Music Composition Core public namespace.
Definition Version.h:4