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-2025 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
9namespace zrythm::structure::arrangement
10{
14enum class MidiModifier
15{
16 Velocity,
17 PitchWheel,
18 ModWheel,
19 Aftertouch,
20};
21
30{
31public:
32 auto get_custom_name () const { return custom_name_; }
33
34 void set_custom_name (const utils::Utf8String &str) { custom_name_ = str; }
35
36public:
40 int index_ = 0;
41
47 int value_ = 0;
48
50 bool visible_ = true;
51
58
61
64
66 bool marked_ = false;
67};
68
74class PianoRoll : public QObject
75{
76 Q_OBJECT
77 QML_ELEMENT
78 Q_PROPERTY (
80 getEditorSettings CONSTANT FINAL)
81 Q_PROPERTY (int keyHeight READ getKeyHeight NOTIFY keyHeightChanged)
82 QML_UNCREATABLE ("")
83
84public:
86 * Highlighting for the piano roll.
87 */
88 enum class Highlighting : std::uint8_t
89 {
90 None,
91 Chord,
92 Scale,
93 Both,
94 };
95
96 PianoRoll (QObject * parent = nullptr);
97
98private:
99 static constexpr std::array<bool, 12> BLACK_NOTES = {
100 false, true, false, true, false, false,
101 true, false, true, false, true, false
102 };
103
104public:
105 // ============================================================================
106 // QML Interface
107 // ============================================================================
108
109 auto getEditorSettings () const { return editor_settings_.get (); }
110
111 int getKeyHeight () const { return note_height_; }
112
113 Q_SIGNAL void keyHeightChanged ();
114
115 Q_INVOKABLE int getKeyAtY (double y) const;
117 * Returns if the key is black.
118 */
119 Q_INVOKABLE static constexpr bool isBlackKey (int note)
120 {
121 note = std::clamp (note, 0, 127);
122 return BLACK_NOTES.at (static_cast<size_t> (note) % 12);
123 }
124 Q_INVOKABLE static constexpr bool isWhiteKey (int note)
125 {
126 return !isBlackKey (note);
127 }
128
129 Q_INVOKABLE static constexpr bool isNextKeyBlack (int note)
130 {
131 return isBlackKey (note + 1);
132 }
133 Q_INVOKABLE static constexpr bool isNextKeyWhite (int note)
134 {
135 return isWhiteKey (note + 1);
136 }
137
138 Q_INVOKABLE static constexpr bool isPrevKeyBlack (int note)
139 {
140 return isBlackKey (note - 1);
141 }
142 Q_INVOKABLE static constexpr bool isPrevKeyWhite (int note)
143 {
144 return isWhiteKey (note - 1);
145 }
146
147 // ============================================================================
148
152 void add_current_note (int note);
153
157 void remove_current_note (int note);
158
162 bool contains_current_note (int note);
163
164 void set_notes_zoom (float notes_zoom, bool fire_events);
165
169 const MidiNoteDescriptor *
170 find_midi_note_descriptor_by_val (bool drum_mode, uint8_t val);
171
175 void set_highlighting (Highlighting highlighting);
176
180 void set_midi_modifier (MidiModifier modifier);
181
183 * Gets the visible notes.
184 */
185 void get_visible_notes (bool drum_mode, std::vector<MidiNoteDescriptor> &vec)
186 {
187 vec.clear ();
188
189 for (const auto i : std::views::iota (0_zu, 128_zu))
190 {
191 MidiNoteDescriptor * descr;
192 if (drum_mode)
193 descr = &drum_descriptors_[i];
194 else
195 descr = &piano_descriptors_[i];
196
197 if (descr->visible_)
198 {
199 vec.push_back (*descr);
200 }
201 }
202 }
203
207 void init ();
208
209 friend void init_from (
210 PianoRoll &obj,
211 const PianoRoll &other,
212 utils::ObjectCloneType clone_type)
213 {
214 obj.editor_settings_ =
215 utils::clone_unique_qobject (*other.editor_settings_, &obj);
216 }
217
218private:
219 static constexpr auto kEditorSettingsKey = "editorSettings"sv;
220 static constexpr auto kNotesZoomKey = "notesZoom"sv;
221 static constexpr auto kMidiModifierKey = "midiModifier"sv;
222 friend void to_json (nlohmann::json &j, const PianoRoll &piano_roll)
223 {
224 j[kEditorSettingsKey] = piano_roll.editor_settings_;
225 j[kNotesZoomKey] = piano_roll.notes_zoom_;
226 j[kMidiModifierKey] = piano_roll.midi_modifier_;
227 }
228 friend void from_json (const nlohmann::json &j, PianoRoll &piano_roll)
229 {
230 j.at (kEditorSettingsKey).get_to (piano_roll.editor_settings_);
231 j.at (kNotesZoomKey).get_to (piano_roll.notes_zoom_);
232 j.at (kMidiModifierKey).get_to (piano_roll.midi_modifier_);
233 }
234
241 void init_descriptors ();
242
243public:
247 float notes_zoom_ = 1.0f;
250 int note_height_{ 16 };
253 MidiModifier midi_modifier_ = MidiModifier::Velocity;
256 std::vector<int> current_notes_;
257
264 std::vector<MidiNoteDescriptor> piano_descriptors_ =
265 std::vector<MidiNoteDescriptor> (128);
266
270 Highlighting highlighting_ = Highlighting::None;
271
280 std::vector<MidiNoteDescriptor> drum_descriptors_ =
281 std::vector<MidiNoteDescriptor> (128);
282};
283}
A descriptor for a MidiNote, used by the piano roll.
Definition piano_roll.h:30
utils::Utf8String note_name_pango_
Note name with extra formatting.
Definition piano_roll.h:63
bool visible_
Whether the note is visible or not.
Definition piano_roll.h:50
int index_
The index to display the note at.
Definition piano_roll.h:40
utils::Utf8String note_name_
Name of the note, from C-2 to B8.
Definition piano_roll.h:60
utils::Utf8String custom_name_
Custom name, from midnam or GM MIDI specs, etc.
Definition piano_roll.h:57
bool marked_
Whether the note is highlighted/marked or not.
Definition piano_roll.h:66
Piano roll serializable backend.
Definition piano_roll.h:75
Highlighting
Highlighting for the piano roll.
Definition piano_roll.h:87
std::vector< MidiNoteDescriptor > drum_descriptors_
Drum mode descriptors.
Definition piano_roll.h:278
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:248
void set_midi_modifier(MidiModifier modifier)
Sets the MIDI modifier.
std::vector< MidiNoteDescriptor > piano_descriptors_
Piano roll mode descriptors.
Definition piano_roll.h:262
void get_visible_notes(bool drum_mode, std::vector< MidiNoteDescriptor > &vec)
Gets the visible notes.
Definition piano_roll.h:183
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:117
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:268
std::vector< int > current_notes_
Currently pressed notes (used only at runtime).
Definition piano_roll.h:254
MidiModifier midi_modifier_
Selected MidiModifier.
Definition piano_roll.h:251
A unique pointer for QObject objects that also works with QObject-based ownership.
Definition qt.h:38
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38