Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
musical_scale.h
1// SPDX-FileCopyrightText: © 2018-2022, 2024-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "dsp/chord_descriptor.h"
7#include "utils/icloneable.h"
8
9#include <QtQmlIntegration>
10
11#include <boost/describe.hpp>
12
13namespace zrythm::dsp
14{
15
21class MusicalScale : public QObject
22{
23 Q_OBJECT
24 Q_PROPERTY (
25 ScaleType scaleType READ scaleType WRITE setScaleType NOTIFY scaleTypeChanged)
26 Q_PROPERTY (
27 zrythm::dsp::MusicalNote rootKey READ rootKey WRITE setRootKey NOTIFY
28 rootKeyChanged)
29 QML_ELEMENT
30 QML_EXTENDED_NAMESPACE (zrythm::dsp)
31
32public:
33 /**
34 * Scale type (name) eg Aeolian.
35 */
36 enum class ScaleType : std::uint8_t
37 {
40
41 /* --- popular scales --- */
42
43 Major,
44
47
49 Ionian,
50
51 Dorian,
52 Phrygian,
53 Lydian,
54 Mixolydian,
55
57 Aeolian,
58
59 Locrian,
60 MelodicMinor,
61 HarmonicMinor,
62 WholeTone,
63 MajorPentatonic,
64 MinorPentatonic,
65 OctatonicHalfWhole,
66 OctatonicWholeHalf,
67
68 /* --- exotic scales --- */
69
72
73 HarmonicMajor,
74 PhrygianDominant,
75 MajorLocrian,
76 Algerian,
77 Augmented,
78 DoubleHarmonic,
79 Chinese,
80 Diminished,
81 DominantDiminished,
82 Egyptian,
83 EightToneSpanish,
84 Enigmatic,
85 Geez,
86 Hindu,
87 Hirajoshi,
88 HungarianGypsy,
89 Insen,
90 NeapolitanMajor,
91 NeapolitanMinor,
92 Oriental,
93 RomanianMinor,
94 Altered,
95 Maqam,
96 Yo,
97 BebopLocrian,
98 BebopDominant,
99 BebopMajor,
100 SuperLocrian,
101 EnigmaticMinor,
102 Composite,
103 Bhairav,
104 HungarianMinor,
105 Persian,
106 Iwato,
107 Kumoi,
108 Pelog,
109 Prometheus,
110 PrometheusNeapolitan,
111 PrometheusLiszt,
112 Balinese,
113 Ragatodi,
114 Japanese1,
115 Japanese2,
116
117 /* --- TODO unimplemented --- */
118
119 Blues,
120 Flamenco,
121 Gypsy,
122 HalfDiminished,
123 In,
124 Istrian,
125 LydianAugmented,
126 Tritone,
127 UkranianDorian,
128 };
129 Q_ENUM (ScaleType)
130
131public:
132 MusicalScale (QObject * parent = nullptr) : QObject (parent) { }
133 MusicalScale (ScaleType type, MusicalNote root, QObject * parent = nullptr)
134 : MusicalScale (parent)
135 {
136 setScaleType (type);
137 setRootKey (root);
138 }
139 Z_DISABLE_COPY_MOVE (MusicalScale)
140 ~MusicalScale () override = default;
141
142 // ========================================================================
143 // QML Interface
144 // ========================================================================
145
146 auto scaleType () const { return type_; }
147 void setScaleType (ScaleType type)
148 {
149 type = std::clamp (type, ScaleType::Chromatic, ScaleType::UkranianDorian);
150 if (type_ != type)
151 {
152 type_ = type;
153 Q_EMIT scaleTypeChanged (type);
154 }
155 }
156 Q_SIGNAL void scaleTypeChanged (ScaleType type);
157
158 auto rootKey () const { return root_key_; }
159 void setRootKey (MusicalNote root_key)
160 {
161 root_key = std::clamp (root_key, MusicalNote::C, MusicalNote::B);
162 if (root_key_ != root_key)
163 {
164 root_key_ = root_key;
165 Q_EMIT rootKeyChanged (root_key);
166 }
167 }
168 Q_SIGNAL void rootKeyChanged (MusicalNote root_key);
169
170 Q_INVOKABLE QString toString () const { return to_string ().to_qstring (); }
171
177 Q_INVOKABLE bool containsNote (MusicalNote note) const;
178
179 // ========================================================================
180
187 static const bool * get_notes_for_type (ScaleType type, bool ascending);
188
198 static std::array<ChordType, 12>
199 get_triad_types_for_type (ScaleType type, bool ascending);
200
201 static utils::Utf8String type_to_string (ScaleType type);
202
207
211 bool contains_chord (const ChordDescriptor &chord) const;
212
216 bool is_accent_in_scale (
217 MusicalNote chord_root,
218 ChordType type,
219 ChordAccent chord_accent) const;
220
221 bool is_same_scale (const MusicalScale &other) const
222 {
223 return type_ == other.type_ && root_key_ == other.root_key_;
224 }
225
226private:
227 friend void init_from (
228 MusicalScale &obj,
229 const MusicalScale &other,
230 utils::ObjectCloneType clone_type)
231 {
232 obj.type_ = other.type_;
233 obj.root_key_ = other.root_key_;
234 }
235
236 NLOHMANN_DEFINE_TYPE_INTRUSIVE (MusicalScale, type_, root_key_)
237
238private:
241
243 MusicalNote root_key_ = MusicalNote::A;
244
245 BOOST_DESCRIBE_CLASS (MusicalScale, (), (), (), (type_, root_key_))
246};
247
248} // namespace zrythm::dsp
A ChordDescriptor describes a chord and is not linked to any specific object by itself.
Musical scale descriptor.
ScaleType
Scale type (name) eg Aeolian.
@ Ionian
Major (same as SCALE_MAJOR).
@ Aeolian
Natural minor (same as Minor).
Q_INVOKABLE bool containsNote(MusicalNote note) const
Returns if the given key is in the given MusicalScale.
utils::Utf8String to_string() const
Prints the MusicalScale to a string.
bool contains_chord(const ChordDescriptor &chord) const
Returns if all of the chord's notes are in the scale.
static const bool * get_notes_for_type(ScaleType type, bool ascending)
Returns the notes in the given scale.
bool is_accent_in_scale(MusicalNote chord_root, ChordType type, ChordAccent chord_accent) const
Returns if the accent is in the scale.
static std::array< ChordType, 12 > get_triad_types_for_type(ScaleType type, bool ascending)
Returns the triads in the given scale.
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38