MCC
Loading...
Searching...
No Matches
Chord.h
1#ifndef MCC_CHORD_CHORD_H
2#define MCC_CHORD_CHORD_H
3
4#include <MCC_BuildSettings.h>
5
6#include <stddef.h>
7#include <stdint.h>
8
9#include <MCC/Chord/ChordPattern.h>
10#include <MCC/Interval/Transposition.h>
11#include <MCC/Pitch/NoteName.h>
12#include <MCC/Pitch/Pitch.h>
13#include <MCC/Pitch/PitchClass.h>
14
15namespace MCC {
16
29class Chord {
30 NoteName _root;
31 ChordPattern _pattern;
32
33public:
35 constexpr Chord() noexcept : _root(), _pattern() {}
36
38 constexpr Chord(NoteName root, ChordPattern pattern) noexcept
39 : _root(root.IsValid() && pattern.IsValid() ? root : NoteName::Invalid()),
40 _pattern(root.IsValid() && pattern.IsValid() ? pattern : ChordPattern::Invalid()) {}
41
43 static constexpr Chord Invalid() noexcept { return Chord(); }
44
46 constexpr bool IsValid() const noexcept { return _pattern.IsValid(); }
47
49 constexpr NoteName Root() const noexcept { return _root; }
50
52 constexpr ChordPattern Pattern() const noexcept { return _pattern; }
53
55 MCC_CONSTEXPR14 uint8_t ToneCount() const noexcept { return _pattern.ToneCount(); }
56
61 MCC_CONSTEXPR14 NoteName ToneAt(int32_t tone) const noexcept {
62 return _root + _pattern.ToneInterval(tone);
63 }
64
69 MCC_CONSTEXPR14 MCC::Pitch PitchAt(int32_t tone, int32_t rootOctave) const noexcept {
70 return MCC::Pitch(_root, rootOctave) + _pattern.ToneInterval(tone);
71 }
72
74 MCC_CONSTEXPR14 bool Contains(NoteName noteName) const noexcept {
75 if (!noteName.IsValid()) {
76 return false;
77 }
78 const uint8_t count = ToneCount();
79 for (uint8_t tone = 1; tone <= count; ++tone) {
80 if (ToneAt(tone) == noteName) {
81 return true;
82 }
83 }
84 return false;
85 }
86
91 MCC_CONSTEXPR14 bool ContainsPitchClass(MCC::PitchClass pitchClass) const noexcept {
92 if (!IsValid() || !pitchClass.IsValid()) {
93 return false;
94 }
95 const int32_t offset =
96 ((static_cast<int32_t>(pitchClass.Value()) - _root.PitchClass().Value()) % 12 + 12) % 12;
97 return ((static_cast<uint32_t>(_pattern.PitchClassMask()) >> offset) & 1u) != 0;
98 }
99
110 size_t Voicing(int32_t inversion, int32_t rootOctave,
111 MCC::Pitch* pitches, size_t capacity) const noexcept {
112 const uint8_t count = ToneCount();
113 if (count == 0 || inversion < 0 || inversion >= count) {
114 return 0;
115 }
116 MCC::Pitch previous;
117 for (uint8_t i = 0; i < count; ++i) {
118 const int32_t tone = (inversion + i) % count + 1;
119 MCC::Pitch pitch = PitchAt(tone, rootOctave);
120 while (previous.IsValid() && pitch.IsValid() && !IsLowerThan(previous, pitch)) {
121 pitch = pitch.MovedByOctaves(1);
122 }
123 if (i < capacity) {
124 pitches[i] = pitch;
125 }
126 previous = pitch;
127 }
128 return count;
129 }
130
132 friend constexpr bool operator==(const Chord& a, const Chord& b) noexcept {
133 return a._root == b._root && a._pattern == b._pattern;
134 }
135
137 friend constexpr bool operator!=(const Chord& a, const Chord& b) noexcept {
138 return !(a == b);
139 }
140};
141
142} // namespace MCC
143
144#endif // MCC_CHORD_CHORD_H
Root-independent chord structure: up to seven ascending tones within two octaves.
Definition ChordPattern.h:33
static constexpr ChordPattern Invalid() noexcept
Returns the invalid pattern.
Definition ChordPattern.h:77
MCC_CONSTEXPR14 bool ContainsPitchClass(MCC::PitchClass pitchClass) const noexcept
Returns true when any tone sounds as pitchClass, regardless of spelling (explicit enharmonic membersh...
Definition Chord.h:91
friend constexpr bool operator==(const Chord &a, const Chord &b) noexcept
Compares roots by spelling and patterns by tones.
Definition Chord.h:132
MCC_CONSTEXPR14 NoteName ToneAt(int32_t tone) const noexcept
Returns the note name of tone (1-based), or the invalid note name outside the chord or when it cannot...
Definition Chord.h:61
MCC_CONSTEXPR14 bool Contains(NoteName noteName) const noexcept
Returns true when a tone is written exactly as noteName.
Definition Chord.h:74
MCC_CONSTEXPR14 uint8_t ToneCount() const noexcept
Returns the number of tones, or 0 for the invalid chord.
Definition Chord.h:55
constexpr ChordPattern Pattern() const noexcept
Returns the root-independent pattern.
Definition Chord.h:52
static constexpr Chord Invalid() noexcept
Returns the invalid chord.
Definition Chord.h:43
constexpr NoteName Root() const noexcept
Returns the root note name.
Definition Chord.h:49
MCC_CONSTEXPR14 MCC::Pitch PitchAt(int32_t tone, int32_t rootOctave) const noexcept
Returns the root-position pitch of tone when the root is placed in rootOctave; extensions keep their ...
Definition Chord.h:69
constexpr bool IsValid() const noexcept
Returns true unless this is the invalid chord.
Definition Chord.h:46
constexpr Chord() noexcept
Creates the invalid chord (SPEC-ERR-2).
Definition Chord.h:35
size_t Voicing(int32_t inversion, int32_t rootOctave, MCC::Pitch *pitches, size_t capacity) const noexcept
Writes a close-position voicing of inversion into pitches.
Definition Chord.h:110
constexpr Chord(NoteName root, ChordPattern pattern) noexcept
Spells pattern from root; invalid when either is invalid.
Definition Chord.h:38
friend constexpr bool operator!=(const Chord &a, const Chord &b) noexcept
Negation of operator==.
Definition Chord.h:137
Written note name: a letter plus an accidental, without octave.
Definition NoteName.h:29
static constexpr NoteName Invalid() noexcept
Returns the invalid note name.
Definition NoteName.h:59
Pitch class 0-11 with spelling discarded (C = 0).
Definition PitchClass.h:21
Written absolute pitch: a note name plus an octave.
Definition Pitch.h:35
constexpr bool IsValid() const noexcept
Returns true unless this is the invalid pitch.
Definition Pitch.h:83
MCC_CONSTEXPR14 Pitch MovedByOctaves(int32_t octaves) const noexcept
Moves the pitch by octaves octaves, keeping its spelling. The result is invalid outside [-128,...
Definition Pitch.h:175
MCC_CONSTEXPR14 bool IsLowerThan(Pitch a, Pitch b) noexcept
Pitch-height order (SPEC-ORD-6): true when a sounds lower than b, with enharmonic ties broken by writ...
Definition Pitch.h:250
Music Composition Core public namespace.
Definition Version.h:4