Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
piano_roll.h
1// SPDX-FileCopyrightText: © 2019-2021, 2023-2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "structure/arrangement/editor_settings.h"
7#include "utils/icloneable.h"
8#include "utils/utf8_string.h"
9
10namespace zrythm::structure::arrangement
11{
15enum class MidiModifier
16{
17 Velocity,
18 PitchWheel,
19 ModWheel,
20 Aftertouch,
21};
22
31{
32public:
33 auto get_custom_name () const { return custom_name_; }
34
35 void set_custom_name (const utils::Utf8String &str) { custom_name_ = str; }
36
37public:
41 int index_ = 0;
42
48 int value_ = 0;
49
51 bool visible_ = true;
52
59
62
65
67 bool marked_ = false;
68};
69
75class PianoRoll : public QObject
76{
77 Q_OBJECT
78 QML_ELEMENT
79 Q_PROPERTY (
81 getEditorSettings CONSTANT FINAL)
82 Q_PROPERTY (int keyHeight READ getKeyHeight NOTIFY keyHeightChanged)
83 QML_UNCREATABLE ("")
84
85public:
87 * Highlighting for the piano roll.
88 */
89 enum class Highlighting : std::uint8_t
90 {
91 None,
92 Chord,
93 Scale,
94 Both,
95 };
96
97 PianoRoll (QObject * parent = nullptr);
98
99private:
100 static constexpr std::array<bool, 12> BLACK_NOTES = {
101 false, true, false, true, false, false,
102 true, false, true, false, true, false
103 };
104
105public:
106 // ============================================================================
107 // QML Interface
108 // ============================================================================
109
110 auto getEditorSettings () const { return editor_settings_.get (); }
111
112 int getKeyHeight () const { return note_height_; }
113
114 Q_SIGNAL void keyHeightChanged ();
115
116 Q_INVOKABLE int getKeyAtY (double y) const;
118 * Returns if the key is black.
119 */
120 Q_INVOKABLE static constexpr bool isBlackKey (int note)
121 {
122 note = std::clamp (note, 0, 127);
123 return BLACK_NOTES.at (static_cast<size_t> (note) % 12);
124 }
125 Q_INVOKABLE static constexpr bool isWhiteKey (int note)
126 {
127 return !isBlackKey (note);
128 }
129
130 Q_INVOKABLE static constexpr bool isNextKeyBlack (int note)
131 {
132 return isBlackKey (note + 1);
133 }
134 Q_INVOKABLE static constexpr bool isNextKeyWhite (int note)
135 {
136 return isWhiteKey (note + 1);
137 }
138
139 Q_INVOKABLE static constexpr bool isPrevKeyBlack (int note)
140 {
141 return isBlackKey (note - 1);
142 }
143 Q_INVOKABLE static constexpr bool isPrevKeyWhite (int note)
144 {
145 return isWhiteKey (note - 1);
146 }
147
148 // ============================================================================
149
153 void add_current_note (int note);
154
158 void remove_current_note (int note);
159
163 bool contains_current_note (int note);
164
165 void set_notes_zoom (float notes_zoom, bool fire_events);
166
170 const MidiNoteDescriptor *
171 find_midi_note_descriptor_by_val (bool drum_mode, uint8_t val);
172
176 void set_highlighting (Highlighting highlighting);
177
181 void set_midi_modifier (MidiModifier modifier);
182
184 * Gets the visible notes.
185 */
186 void get_visible_notes (bool drum_mode, std::vector<MidiNoteDescriptor> &vec)
187 {
188 vec.clear ();
189
190 for (const auto i : std::views::iota (0zu, 128zu))
191 {
192 MidiNoteDescriptor * descr;
193 if (drum_mode)
194 descr = &drum_descriptors_[i];
195 else
196 descr = &piano_descriptors_[i];
197
198 if (descr->visible_)
199 {
200 vec.push_back (*descr);
201 }
202 }
203 }
204
208 void init ();
209
210 friend void init_from (
211 PianoRoll &obj,
212 const PianoRoll &other,
213 utils::ObjectCloneType clone_type)
214 {
215 obj.editor_settings_ =
216 utils::clone_unique_qobject (*other.editor_settings_, &obj);
217 }
218
219private:
220 static constexpr auto kEditorSettingsKey = "editorSettings"sv;
221 static constexpr auto kNotesZoomKey = "notesZoom"sv;
222 static constexpr auto kMidiModifierKey = "midiModifier"sv;
223 friend void to_json (nlohmann::json &j, const PianoRoll &piano_roll);
224 friend void from_json (const nlohmann::json &j, PianoRoll &piano_roll);
225
232 void init_descriptors ();
233
234public:
238 float notes_zoom_ = 1.0f;
241 int note_height_{ 16 };
244 MidiModifier midi_modifier_ = MidiModifier::Velocity;
247 std::vector<int> current_notes_;
248
255 std::vector<MidiNoteDescriptor> piano_descriptors_ =
256 std::vector<MidiNoteDescriptor> (128);
257
261 Highlighting highlighting_ = Highlighting::None;
262
271 std::vector<MidiNoteDescriptor> drum_descriptors_ =
272 std::vector<MidiNoteDescriptor> (128);
273};
274}
A descriptor for a MidiNote, used by the piano roll.
Definition piano_roll.h:31
utils::Utf8String note_name_pango_
Note name with extra formatting.
Definition piano_roll.h:64
bool visible_
Whether the note is visible or not.
Definition piano_roll.h:51
int index_
The index to display the note at.
Definition piano_roll.h:41
utils::Utf8String note_name_
Name of the note, from C-2 to B8.
Definition piano_roll.h:61
utils::Utf8String custom_name_
Custom name, from midnam or GM MIDI specs, etc.
Definition piano_roll.h:58
bool marked_
Whether the note is highlighted/marked or not.
Definition piano_roll.h:67
Piano roll serializable backend.
Definition piano_roll.h:76
Highlighting
Highlighting for the piano roll.
Definition piano_roll.h:88
std::vector< MidiNoteDescriptor > drum_descriptors_
Drum mode descriptors.
Definition piano_roll.h:269
const MidiNoteDescriptor * find_midi_note_descriptor_by_val(bool drum_mode, uint8_t val)
Returns the MidiNoteDescriptor matching the value (0-127).
void add_current_note(int note)
Adds the note if it doesn't exist in current_notes_.
int note_height_
Visual height per key in pixels.
Definition piano_roll.h:239
void set_midi_modifier(MidiModifier modifier)
Sets the MIDI modifier.
std::vector< MidiNoteDescriptor > piano_descriptors_
Piano roll mode descriptors.
Definition piano_roll.h:253
void get_visible_notes(bool drum_mode, std::vector< MidiNoteDescriptor > &vec)
Gets the visible notes.
Definition piano_roll.h:184
void set_highlighting(Highlighting highlighting)
Updates the highlighting and notifies the UI.
static Q_INVOKABLE constexpr bool isBlackKey(int note)
Returns if the key is black.
Definition piano_roll.h:118
bool contains_current_note(int note)
Returns whether the note exists in current_notes_.
void init()
Initializes the PianoRoll.
void remove_current_note(int note)
Removes the note if it exists in current_notes_.
Highlighting highlighting_
Highlighting notes depending on the current chord or scale.
Definition piano_roll.h:259
std::vector< int > current_notes_
Currently pressed notes (used only at runtime).
Definition piano_roll.h:245
MidiModifier midi_modifier_
Selected MidiModifier.
Definition piano_roll.h:242
A unique pointer for QObject objects that also works with QObject-based ownership.
Definition qt.h:36
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:37