Zrythm v2.0.0-alpha.1+31.4967fd053471
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
midi_editor.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/project/editor_settings.h"
7#include "utils/utf8_string.h"
8
9#include <QtQmlIntegration/qqmlintegration.h>
10
11#include <nlohmann/json_fwd.hpp>
12
13namespace zrythm::structure::project
14{
15
19enum class MidiModifier
20{
21 Velocity,
22 PitchWheel,
23 ModWheel,
24 Aftertouch,
25};
26
35{
36public:
37 auto custom_name () const { return custom_name_; }
38
39 void set_custom_name (const utils::Utf8String &str) { custom_name_ = str; }
40
41public:
45 int index_ = 0;
46
52 int value_ = 0;
53
55 bool visible_ = true;
56
63
66
69
71 bool marked_ = false;
72};
73
79class MidiEditor : public EditorSettings
80{
81 Q_OBJECT
82 QML_ELEMENT
83 Q_PROPERTY (int keyHeight READ keyHeight NOTIFY keyHeightChanged)
84 QML_UNCREATABLE ("")
85
86public:
90 enum class Highlighting : std::uint8_t
91 {
92 None,
93 Chord,
94 Scale,
95 Both,
96 };
97 Q_ENUM (Highlighting)
98
99 MidiEditor (QObject * parent = nullptr);
100
101private:
102 static constexpr std::array<bool, 12> BLACK_NOTES = {
103 false, true, false, true, false, false,
104 true, false, true, false, true, false
105 };
106
107public:
108 // ============================================================================
109 // QML Interface
110 // ============================================================================
111
112 int keyHeight () const { return note_height_; }
113
114 Q_SIGNAL void keyHeightChanged ();
115
116 Q_INVOKABLE int getKeyAtY (double y) const;
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_midi_modifier (MidiModifier modifier);
177
181 void get_visible_notes (bool drum_mode, std::vector<MidiNoteDescriptor> &vec)
182 {
183 vec.clear ();
184
185 for (const auto i : std::views::iota (0zu, 128zu))
186 {
187 MidiNoteDescriptor * descr;
188 if (drum_mode)
189 descr = &drum_descriptors_[i];
190 else
191 descr = &piano_descriptors_[i];
192
193 if (descr->visible_)
194 {
195 vec.push_back (*descr);
196 }
197 }
198 }
199
203 void init ();
204
205private:
206 friend void init_from (
207 MidiEditor &obj,
208 const MidiEditor &other,
209 utils::ObjectCloneType clone_type);
210 friend void to_json (nlohmann::json &j, const MidiEditor &midi_editor);
211 friend void from_json (const nlohmann::json &j, MidiEditor &midi_editor);
212
213private:
214 static constexpr auto kNotesZoomKey = "notesZoom"sv;
215 static constexpr auto kMidiModifierKey = "midiModifier"sv;
216
223 void init_descriptors ();
224
225public:
227 float notes_zoom_ = 1.0f;
228
230 int note_height_{ 16 };
231
233 MidiModifier midi_modifier_ = MidiModifier::Velocity;
234
236 std::vector<int> current_notes_;
237
244 std::vector<MidiNoteDescriptor> piano_descriptors_ =
245 std::vector<MidiNoteDescriptor> (128);
246
255 std::vector<MidiNoteDescriptor> drum_descriptors_ =
256 std::vector<MidiNoteDescriptor> (128);
257};
258
259}
MIDI editor serializable backend.
Definition midi_editor.h:80
static Q_INVOKABLE constexpr bool isBlackKey(int note)
Returns if the key is black.
int note_height_
Visual height per key in pixels.
void init()
Initializes the MidiEditor.
Highlighting
Highlighting for the piano roll.
Definition midi_editor.h:91
void add_current_note(int note)
Adds the note if it doesn't exist in current_notes_.
const MidiNoteDescriptor * find_midi_note_descriptor_by_val(bool drum_mode, uint8_t val)
Returns the MidiNoteDescriptor matching the value (0-127).
void set_midi_modifier(MidiModifier modifier)
Sets the MIDI modifier.
MidiModifier midi_modifier_
Selected MidiModifier.
void get_visible_notes(bool drum_mode, std::vector< MidiNoteDescriptor > &vec)
Gets the visible notes.
void remove_current_note(int note)
Removes the note if it exists in current_notes_.
std::vector< MidiNoteDescriptor > drum_descriptors_
Drum mode descriptors.
bool contains_current_note(int note)
Returns whether the note exists in current_notes_.
std::vector< MidiNoteDescriptor > piano_descriptors_
Piano roll mode descriptors.
std::vector< int > current_notes_
Currently pressed notes (used only at runtime).
A descriptor for a MidiNote, used by the piano roll.
Definition midi_editor.h:35
int index_
The index to display the note at.
Definition midi_editor.h:45
utils::Utf8String note_name_pango_
Note name with extra formatting.
Definition midi_editor.h:68
utils::Utf8String note_name_
Name of the note, from C-2 to B8.
Definition midi_editor.h:65
utils::Utf8String custom_name_
Custom name, from midnam or GM MIDI specs, etc.
Definition midi_editor.h:62
bool marked_
Whether the note is highlighted/marked or not.
Definition midi_editor.h:71
bool visible_
Whether the note is visible or not.
Definition midi_editor.h:55
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:37