Zrythm v2.0.0-alpha.1+31.4967fd053471
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
chord_suggestion.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <optional>
7#include <vector>
8
9#include "dsp/chord_descriptor.h"
10#include "dsp/musical_scale.h"
11
12namespace zrythm::dsp::chords
13{
14
15// ============================================================================
16// Enums
17// ============================================================================
18
20enum class ChordCandidateCategory : uint32_t
21{
22 DiatonicTriads = 1 << 0,
23 DiatonicSevenths = 1 << 1,
24 SecondaryDominants = 1 << 2,
25 BorrowedChords = 1 << 3,
26 LeadingTone = 1 << 4,
27};
28
29inline ChordCandidateCategory
30operator| (ChordCandidateCategory a, ChordCandidateCategory b) noexcept
31{
32 return static_cast<ChordCandidateCategory> (
33 static_cast<uint32_t> (a) | static_cast<uint32_t> (b));
34}
35
36inline ChordCandidateCategory
37operator& (ChordCandidateCategory a, ChordCandidateCategory b) noexcept
38{
39 return static_cast<ChordCandidateCategory> (
40 static_cast<uint32_t> (a) & static_cast<uint32_t> (b));
41}
42
44enum class HarmonicFunction
45{
46 Tonic,
47 Predominant,
48 Dominant,
49 Other,
50};
51
53enum class CandidateType
54{
55 DiatonicTriad,
56 DiatonicSeventh,
57 SecondaryDominant,
58 BorrowedChord,
59 LeadingTone,
60};
61
62// ============================================================================
63// Structs
64// ============================================================================
65
71{
72 MusicalNote root_note = MusicalNote::C;
73 ChordType type = ChordType::Major;
74 ChordAccent accent = ChordAccent::None;
75
76 bool operator== (const ChordKey &other) const
77 {
78 return root_note == other.root_note && type == other.type
79 && accent == other.accent;
80 }
81
84 {
85 return ChordDescriptor (root_note, type, accent);
86 }
87};
88
91{
92 ChordKey chord_key{};
93 CandidateType type = CandidateType::DiatonicTriad;
94 int scale_degree = -1;
95 std::optional<int> secondary_dominant_target_degree{};
96};
97
100{
101 ChordKey chord_key{};
102 CandidateType candidate_type = CandidateType::DiatonicTriad;
103 float overall_score = 0.0f;
104 float functional_score = 0.0f;
105 float root_motion_score = 0.0f;
106 float voice_leading_score = 0.0f;
107 int scale_degree = -1;
108 HarmonicFunction function = HarmonicFunction::Other;
109 int rank = 0;
110};
111
112// ============================================================================
113// Public API
114// ============================================================================
115
117bool
118is_minor_type (const MusicalScale &scale);
119
121int
122get_scale_degree (MusicalNote root, const MusicalScale &scale);
123
125float
126score_root_motion (MusicalNote prev_root, MusicalNote next_root);
127
129float
130score_voice_leading (const ChordKey &prev, const ChordKey &next);
131
133float
134score_diatonic_membership (const ChordKey &chord, const MusicalScale &scale);
135
137float
138score_functional_compatibility (
139 const ChordKey &prev,
140 const ChordKey &candidate,
141 const MusicalScale &scale);
142
145float
146score_seventh_resolution (
147 const ChordKey &prev,
148 const ChordKey &next,
149 const MusicalScale &scale);
150
152float
153score_secondary_dominant (
154 const CandidateChord &prev,
155 const CandidateChord &candidate,
156 const MusicalScale &scale);
157
159float
160score_leading_tone_resolution (
161 const ChordKey &prev,
162 const ChordKey &candidate,
163 const MusicalScale &scale);
164
172float
173score_borrowed_chord (const CandidateChord &candidate, const MusicalScale &scale);
174
176std::vector<CandidateChord>
177generate_candidates (
178 const MusicalScale &scale,
179 ChordCandidateCategory categories);
180
182std::vector<ChordSuggestion>
183suggest_next_chords (
184 const ChordKey &current_chord,
185 const MusicalScale &scale,
186 ChordCandidateCategory categories,
187 int max_results = 3);
188
189} // namespace zrythm::dsp::chords
Describes a musical chord by its root note, type, accent, inversion, and optional bass note.
Musical scale descriptor.
A candidate chord with metadata about how it was generated.
Lightweight POD storing just the chord identity (no QObject overhead).
ChordDescriptor make_descriptor() const
Constructs a temporary ChordDescriptor for method calls.
The result of scoring one candidate chord.