libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
midinote.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_MUSIC
13#include <cstdint>
14#include <promeki/string.h>
15
16PROMEKI_NAMESPACE_BEGIN
17
29class MidiNote {
30 public:
39 enum Value : uint8_t {
40 // Octave -1 (MIDI 0–11)
41 C_1 = 0,
42 Cs_1 = 1,
43 D_1 = 2,
44 Ds_1 = 3,
45 E_1 = 4,
46 F_1 = 5,
47 Fs_1 = 6,
48 G_1 = 7,
49 Gs_1 = 8,
50 A_1 = 9,
51 As_1 = 10,
52 B_1 = 11,
53 Db_1 = 1,
54 Eb_1 = 3,
55 Gb_1 = 6,
56 Ab_1 = 8,
57 Bb_1 = 10,
58
59 // Octave 0 (MIDI 12–23)
60 C0 = 12,
61 Cs0 = 13,
62 D0 = 14,
63 Ds0 = 15,
64 E0 = 16,
65 F0 = 17,
66 Fs0 = 18,
67 G0 = 19,
68 Gs0 = 20,
69 A0 = 21,
70 As0 = 22,
71 B0 = 23,
72 Db0 = 13,
73 Eb0 = 15,
74 Gb0 = 18,
75 Ab0 = 20,
76 Bb0 = 22,
77
78 // Octave 1 (MIDI 24–35)
79 C1 = 24,
80 Cs1 = 25,
81 D1 = 26,
82 Ds1 = 27,
83 E1 = 28,
84 F1 = 29,
85 Fs1 = 30,
86 G1 = 31,
87 Gs1 = 32,
88 A1 = 33,
89 As1 = 34,
90 B1 = 35,
91 Db1 = 25,
92 Eb1 = 27,
93 Gb1 = 30,
94 Ab1 = 32,
95 Bb1 = 34,
96
97 // Octave 2 (MIDI 36–47)
98 C2 = 36,
99 Cs2 = 37,
100 D2 = 38,
101 Ds2 = 39,
102 E2 = 40,
103 F2 = 41,
104 Fs2 = 42,
105 G2 = 43,
106 Gs2 = 44,
107 A2 = 45,
108 As2 = 46,
109 B2 = 47,
110 Db2 = 37,
111 Eb2 = 39,
112 Gb2 = 42,
113 Ab2 = 44,
114 Bb2 = 46,
115
116 // Octave 3 (MIDI 48–59)
117 C3 = 48,
118 Cs3 = 49,
119 D3 = 50,
120 Ds3 = 51,
121 E3 = 52,
122 F3 = 53,
123 Fs3 = 54,
124 G3 = 55,
125 Gs3 = 56,
126 A3 = 57,
127 As3 = 58,
128 B3 = 59,
129 Db3 = 49,
130 Eb3 = 51,
131 Gb3 = 54,
132 Ab3 = 56,
133 Bb3 = 58,
134
135 // Octave 4 (MIDI 60–71) — Middle C = C4
136 C4 = 60,
137 Cs4 = 61,
138 D4 = 62,
139 Ds4 = 63,
140 E4 = 64,
141 F4 = 65,
142 Fs4 = 66,
143 G4 = 67,
144 Gs4 = 68,
145 A4 = 69,
146 As4 = 70,
147 B4 = 71,
148 Db4 = 61,
149 Eb4 = 63,
150 Gb4 = 66,
151 Ab4 = 68,
152 Bb4 = 70,
153
154 // Octave 5 (MIDI 72–83)
155 C5 = 72,
156 Cs5 = 73,
157 D5 = 74,
158 Ds5 = 75,
159 E5 = 76,
160 F5 = 77,
161 Fs5 = 78,
162 G5 = 79,
163 Gs5 = 80,
164 A5 = 81,
165 As5 = 82,
166 B5 = 83,
167 Db5 = 73,
168 Eb5 = 75,
169 Gb5 = 78,
170 Ab5 = 80,
171 Bb5 = 82,
172
173 // Octave 6 (MIDI 84–95)
174 C6 = 84,
175 Cs6 = 85,
176 D6 = 86,
177 Ds6 = 87,
178 E6 = 88,
179 F6 = 89,
180 Fs6 = 90,
181 G6 = 91,
182 Gs6 = 92,
183 A6 = 93,
184 As6 = 94,
185 B6 = 95,
186 Db6 = 85,
187 Eb6 = 87,
188 Gb6 = 90,
189 Ab6 = 92,
190 Bb6 = 94,
191
192 // Octave 7 (MIDI 96–107)
193 C7 = 96,
194 Cs7 = 97,
195 D7 = 98,
196 Ds7 = 99,
197 E7 = 100,
198 F7 = 101,
199 Fs7 = 102,
200 G7 = 103,
201 Gs7 = 104,
202 A7 = 105,
203 As7 = 106,
204 B7 = 107,
205 Db7 = 97,
206 Eb7 = 99,
207 Gb7 = 102,
208 Ab7 = 104,
209 Bb7 = 106,
210
211 // Octave 8 (MIDI 108–119)
212 C8 = 108,
213 Cs8 = 109,
214 D8 = 110,
215 Ds8 = 111,
216 E8 = 112,
217 F8 = 113,
218 Fs8 = 114,
219 G8 = 115,
220 Gs8 = 116,
221 A8 = 117,
222 As8 = 118,
223 B8 = 119,
224 Db8 = 109,
225 Eb8 = 111,
226 Gb8 = 114,
227 Ab8 = 116,
228 Bb8 = 118,
229
230 // Octave 9 (MIDI 120–127, partial)
231 C9 = 120,
232 Cs9 = 121,
233 D9 = 122,
234 Ds9 = 123,
235 E9 = 124,
236 F9 = 125,
237 Fs9 = 126,
238 G9 = 127,
239 Db9 = 121,
240 Eb9 = 123,
241 Gb9 = 126,
242
243 // General MIDI Percussion (channel 10, notes 27–87)
244 GMP_HighQ = 27,
245 GMP_Slap = 28,
246 GMP_ScratchPush = 29,
247 GMP_ScratchPull = 30,
248 GMP_Sticks = 31,
249 GMP_SquareClick = 32,
250 GMP_MetronomeClick = 33,
251 GMP_MetronomeBell = 34,
252 GMP_AcousticBassDrum = 35,
253 GMP_BassDrum1 = 36,
254 GMP_SideStick = 37,
255 GMP_AcousticSnare = 38,
256 GMP_HandClap = 39,
257 GMP_ElectricSnare = 40,
258 GMP_LowFloorTom = 41,
259 GMP_ClosedHiHat = 42,
260 GMP_HighFloorTom = 43,
261 GMP_PedalHiHat = 44,
262 GMP_LowTom = 45,
263 GMP_OpenHiHat = 46,
264 GMP_LowMidTom = 47,
265 GMP_HiMidTom = 48,
266 GMP_CrashCymbal1 = 49,
267 GMP_HighTom = 50,
268 GMP_RideCymbal1 = 51,
269 GMP_ChineseCymbal = 52,
270 GMP_RideBell = 53,
271 GMP_Tambourine = 54,
272 GMP_SplashCymbal = 55,
273 GMP_Cowbell = 56,
274 GMP_CrashCymbal2 = 57,
275 GMP_Vibraslap = 58,
276 GMP_RideCymbal2 = 59,
277 GMP_HiBongo = 60,
278 GMP_LowBongo = 61,
279 GMP_MuteHiConga = 62,
280 GMP_OpenHiConga = 63,
281 GMP_LowConga = 64,
282 GMP_HighTimbale = 65,
283 GMP_LowTimbale = 66,
284 GMP_HighAgogo = 67,
285 GMP_LowAgogo = 68,
286 GMP_Cabasa = 69,
287 GMP_Maracas = 70,
288 GMP_ShortWhistle = 71,
289 GMP_LongWhistle = 72,
290 GMP_ShortGuiro = 73,
291 GMP_LongGuiro = 74,
292 GMP_Claves = 75,
293 GMP_HiWoodBlock = 76,
294 GMP_LowWoodBlock = 77,
295 GMP_MuteCuica = 78,
296 GMP_OpenCuica = 79,
297 GMP_MuteTriangle = 80,
298 GMP_OpenTriangle = 81,
299 GMP_Shaker = 82,
300 GMP_JingleBell = 83,
301 GMP_Belltree = 84,
302 GMP_Castanets = 85,
303 GMP_MuteSurdo = 86,
304 GMP_OpenSurdo = 87,
305
306 Invalid = 0xFF
307 };
308
310 MidiNote() : _value(Invalid) {}
311
313 MidiNote(Value v) : _value(v) {}
314
319 MidiNote(uint8_t v) : _value(v > 127 ? Invalid : static_cast<Value>(v)) {}
320
322 bool isValid() const { return _value != Invalid; }
323
325 Value value() const { return _value; }
326
328 uint8_t rawValue() const { return static_cast<uint8_t>(_value); }
329
331 operator uint8_t() const { return static_cast<uint8_t>(_value); }
332
333 // --- Instance methods (return values for this note) ---
334
336 const char *pitchClassName() const;
337
339 const char *pitchClassNameFlat() const;
340
342 int octave() const;
343
345 int pitchClass() const;
346
348 String name() const;
349
354 double frequency(double a4Hz = 440.0) const;
355
356 // --- Static methods (operate on raw values) ---
357
359 static const char *pitchClassName(int midiNote);
360
362 static const char *pitchClassNameFlat(int midiNote);
363
365 static int octave(int midiNote);
366
368 static int pitchClass(int midiNote);
369
371 static String nameFromMidiNote(int midiNote);
372
378 static MidiNote fromName(const String &name);
379
385 static double frequencyFromMidiNote(double midiNote, double a4Hz = 440.0);
386
392 static double midiNoteFromFrequency(double frequencyHz, double a4Hz = 440.0);
393
394 // --- Comparison operators ---
395
396 bool operator==(const MidiNote &other) const { return _value == other._value; }
397 bool operator!=(const MidiNote &other) const { return _value != other._value; }
398 bool operator<(const MidiNote &other) const { return _value < other._value; }
399 bool operator<=(const MidiNote &other) const { return _value <= other._value; }
400 bool operator>(const MidiNote &other) const { return _value > other._value; }
401 bool operator>=(const MidiNote &other) const { return _value >= other._value; }
402
403 private:
404 Value _value;
405};
406
407PROMEKI_NAMESPACE_END
408
409#endif // PROMEKI_ENABLE_MUSIC