1#ifndef MCC_SCALE_SCALE_PATTERN_H
2#define MCC_SCALE_SCALE_PATTERN_H
4#include <MCC_BuildSettings.h>
8#include <MCC/Interval/Interval.h>
14struct ScalePatternStorage;
38 friend struct Detail::ScalePatternStorage;
43 constexpr ScalePattern(uint16_t semitones, uint8_t steps0,
44 uint8_t steps1, uint8_t steps2,
45 uint8_t steps3, uint8_t steps4,
46 uint8_t steps5) noexcept
47 : _semitones(semitones),
48 _steps{steps0, steps1, steps2, steps3, steps4, steps5} {}
52 static constexpr int32_t NaturalSemitones(int32_t steps)
noexcept {
53 return steps * 2 - (steps >= 3 ? 1 : 0);
56 constexpr uint8_t StepsAt(uint8_t index)
const noexcept {
57 return static_cast<uint8_t
>((_steps[index / 2] >> ((index % 2) * 4)) & 0x0F);
60 MCC_CONSTEXPR14 int32_t SemitonesAt(uint8_t index)
const noexcept {
62 for (int32_t k = 0; k < 12; ++k) {
63 if ((
static_cast<uint32_t
>(_semitones) >> k) & 1u) {
75 constexpr ScalePattern() noexcept : _semitones(0), _steps{0, 0, 0, 0, 0, 0} {}
88 static MCC_CONSTEXPR14 ScalePattern
FromFormula(
const char* formula)
noexcept {
90 if (formula ==
nullptr) {
94 int32_t previous = -1;
99 while (formula[i] !=
'\0') {
100 if (formula[i] ==
' ') {
103 int32_t accidental = 0;
104 while (formula[i] ==
'b' || formula[i] ==
'#') {
105 accidental += (formula[i] ==
'#') ? 1 : -1;
108 if (formula[i] <
'1' || formula[i] >
'7') {
111 const int32_t steps = formula[i] -
'1';
113 if (formula[i] !=
' ' && formula[i] !=
'\0') {
116 const int32_t semitones = NaturalSemitones(steps) + accidental;
117 if (count ==
MaximumDegrees || semitones <= previous || semitones > 11 ||
118 (count == 0 && (steps != 0 || semitones != 0)) ||
122 pattern._semitones =
static_cast<uint16_t
>(pattern._semitones | (1u << semitones));
123 pattern._steps[count / 2] =
static_cast<uint8_t
>(
124 pattern._steps[count / 2] | (steps << ((count % 2) * 4)));
125 previous = semitones;
129 return count == 0 ?
Invalid() : pattern;
133 constexpr bool IsValid() const noexcept {
return _semitones != 0; }
138 for (int32_t k = 0; k < 12; ++k) {
139 count =
static_cast<uint8_t
>(count + ((
static_cast<uint32_t
>(_semitones) >> k) & 1u));
152 const uint8_t index =
static_cast<uint8_t
>(degree - 1);
161 const int32_t reduced = ((semitones % 12) + 12) % 12;
162 return IsValid() && ((
static_cast<uint32_t
>(_semitones) >> reduced) & 1u) != 0;
166 friend MCC_CONSTEXPR14
bool operator==(
const ScalePattern& a,
const ScalePattern& b)
noexcept {
167 if (a._semitones != b._semitones) {
170 for (uint8_t i = 0; i < 6; ++i) {
171 if (a._steps[i] != b._steps[i]) {
179 friend MCC_CONSTEXPR14
bool operator!=(
const ScalePattern& a,
const ScalePattern& b)
noexcept {
187struct ScalePatternStorage {
188 static constexpr ScalePattern Make(uint16_t semitones, uint8_t steps0,
189 uint8_t steps1, uint8_t steps2,
190 uint8_t steps3, uint8_t steps4,
191 uint8_t steps5)
noexcept {
192 return ScalePattern(semitones, steps0, steps1, steps2,
193 steps3, steps4, steps5);
Directed interval: a diatonic step count and a chromatic semitone count (SPEC-INT-1).
Definition Interval.h:30
static MCC_CONSTEXPR14 Interval FromSteps(int32_t diatonicSteps, int32_t semitones) noexcept
Creates the interval spanning diatonicSteps letters and semitones semitones, both signed (SPEC-INT-1)...
Definition Interval.h:111
static constexpr Interval Invalid() noexcept
Returns the invalid interval.
Definition Interval.h:139
friend MCC_CONSTEXPR14 bool operator!=(const ScalePattern &a, const ScalePattern &b) noexcept
Negation of operator==.
Definition ScalePattern.h:179
MCC_CONSTEXPR14 bool ContainsSemitone(int32_t semitones) const noexcept
Returns true when a degree lies semitones (reduced modulo 12) above the root.
Definition ScalePattern.h:160
MCC_CONSTEXPR14 uint8_t DegreeCount() const noexcept
Returns the number of degrees, or 0 for the invalid pattern.
Definition ScalePattern.h:136
MCC_CONSTEXPR14 Interval DegreeInterval(int32_t degree) const noexcept
Returns the ascending interval from the root to degree (1-based), or the invalid interval outside [1,...
Definition ScalePattern.h:148
static constexpr ScalePattern Invalid() noexcept
Returns the invalid pattern.
Definition ScalePattern.h:78
static constexpr uint8_t MaximumDegrees
Largest number of degrees: every chromatic semitone.
Definition ScalePattern.h:35
static MCC_CONSTEXPR14 ScalePattern FromFormula(const char *formula) noexcept
Builds a pattern from a degree formula such as "1 2 b3 4 5 b6 b7".
Definition ScalePattern.h:88
constexpr ScalePattern() noexcept
Creates the invalid pattern (SPEC-ERR-2).
Definition ScalePattern.h:75
constexpr bool IsValid() const noexcept
Returns true unless this is the invalid pattern.
Definition ScalePattern.h:133
friend MCC_CONSTEXPR14 bool operator==(const ScalePattern &a, const ScalePattern &b) noexcept
Compares degrees, including their written steps.
Definition ScalePattern.h:166
Music Composition Core public namespace.
Definition Version.h:4