OpenShot Audio Library | OpenShotAudio: juce_MidiMessage.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.0

Loading...
Searching...
No Matches
juce_MidiMessage.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26namespace MidiHelpers
27{
28 inline uint8 initialByte (const int type, const int channel) noexcept
29 {
30 return (uint8) (type | jlimit (0, 15, channel - 1));
31 }
32
33 inline uint8 validVelocity (const int v) noexcept
34 {
35 return (uint8) jlimit (0, 127, v);
36 }
37}
38
39//==============================================================================
40uint8 MidiMessage::floatValueToMidiByte (const float v) noexcept
41{
42 jassert (v >= 0 && v <= 1.0f); // if your value is > 1, maybe you're passing an
43 // integer value to a float method by mistake?
44
45 return MidiHelpers::validVelocity (roundToInt (v * 127.0f));
46}
47
48uint16 MidiMessage::pitchbendToPitchwheelPos (const float pitchbend,
49 const float pitchbendRange) noexcept
50{
51 // can't translate a pitchbend value that is outside of the given range!
52 jassert (std::abs (pitchbend) <= pitchbendRange);
53
54 return static_cast<uint16> (pitchbend > 0.0f
55 ? jmap (pitchbend, 0.0f, pitchbendRange, 8192.0f, 16383.0f)
56 : jmap (pitchbend, -pitchbendRange, 0.0f, 0.0f, 8192.0f));
57}
58
59//==============================================================================
60 int MidiMessage::readVariableLengthVal (const uint8* data, int& numBytesUsed) noexcept
61{
62 numBytesUsed = 0;
63 int v = 0, i;
64
65 do
66 {
67 i = (int) *data++;
68
69 if (++numBytesUsed > 6)
70 break;
71
72 v = (v << 7) + (i & 0x7f);
73
74 } while (i & 0x80);
75
76 return v;
77}
78
79 int MidiMessage::getMessageLengthFromFirstByte (const uint8 firstByte) noexcept
80{
81 // this method only works for valid starting bytes of a short midi message
82 jassert (firstByte >= 0x80 && firstByte != 0xf0 && firstByte != 0xf7);
83
84 static const char messageLengths[] =
85 {
86 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
87 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
88 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
89 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
90 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
91 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
92 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
93 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
94 };
95
96 return messageLengths[firstByte & 0x7f];
97}
98
99//==============================================================================
100MidiMessage::MidiMessage() noexcept
101 : size (2)
102{
103 packedData.asBytes[0] = 0xf0;
104 packedData.asBytes[1] = 0xf7;
105}
106
107 MidiMessage::MidiMessage (const void* const d, const int dataSize, const double t)
108 : timeStamp (t), size (dataSize)
109{
110 jassert (dataSize > 0);
111 // this checks that the length matches the data..
112 jassert (dataSize > 3 || *(uint8*)d >= 0xf0 || getMessageLengthFromFirstByte (*(uint8*)d) == size);
113
114 memcpy (allocateSpace (dataSize), d, (size_t) dataSize);
115}
116
117 MidiMessage::MidiMessage (const int byte1, const double t) noexcept
118 : timeStamp (t), size (1)
119{
120 packedData.asBytes[0] = (uint8) byte1;
121
122 // check that the length matches the data..
123 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 1);
124}
125
126 MidiMessage::MidiMessage (const int byte1, const int byte2, const double t) noexcept
127 : timeStamp (t), size (2)
128{
129 packedData.asBytes[0] = (uint8) byte1;
130 packedData.asBytes[1] = (uint8) byte2;
131
132 // check that the length matches the data..
133 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 2);
134}
135
136 MidiMessage::MidiMessage (const int byte1, const int byte2, const int byte3, const double t) noexcept
137 : timeStamp (t), size (3)
138{
139 packedData.asBytes[0] = (uint8) byte1;
140 packedData.asBytes[1] = (uint8) byte2;
141 packedData.asBytes[2] = (uint8) byte3;
142
143 // check that the length matches the data..
144 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 3);
145}
146
147 MidiMessage::MidiMessage (const MidiMessage& other)
148 : timeStamp (other.timeStamp), size (other.size)
149{
150 if (isHeapAllocated())
151 memcpy (allocateSpace (size), other.getData(), (size_t) size);
152 else
153 packedData.allocatedData = other.packedData.allocatedData;
154}
155
156 MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp)
157 : timeStamp (newTimeStamp), size (other.size)
158{
159 if (isHeapAllocated())
160 memcpy (allocateSpace (size), other.getData(), (size_t) size);
161 else
162 packedData.allocatedData = other.packedData.allocatedData;
163}
164
165 MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte,
166 double t, bool sysexHasEmbeddedLength)
167 : timeStamp (t)
168{
169 auto src = static_cast<const uint8*> (srcData);
170 auto byte = (unsigned int) *src;
171
172 if (byte < 0x80)
173 {
174 byte = (unsigned int) lastStatusByte;
175 numBytesUsed = -1;
176 }
177 else
178 {
179 numBytesUsed = 0;
180 --sz;
181 ++src;
182 }
183
184 if (byte >= 0x80)
185 {
186 if (byte == 0xf0)
187 {
188 auto d = src;
189 bool haveReadAllLengthBytes = ! sysexHasEmbeddedLength;
190 int numVariableLengthSysexBytes = 0;
191
192 while (d < src + sz)
193 {
194 if (*d >= 0x80)
195 {
196 if (*d == 0xf7)
197 {
198 ++d; // include the trailing 0xf7 when we hit it
199 break;
200 }
201
202 if (haveReadAllLengthBytes) // if we see a 0x80 bit set after the initial data length
203 break; // bytes, assume it's the end of the sysex
204
205 ++numVariableLengthSysexBytes;
206 }
207 else if (! haveReadAllLengthBytes)
208 {
209 haveReadAllLengthBytes = true;
210 ++numVariableLengthSysexBytes;
211 }
212
213 ++d;
214 }
215
216 src += numVariableLengthSysexBytes;
217 size = 1 + (int) (d - src);
218
219 auto dest = allocateSpace (size);
220 *dest = (uint8) byte;
221 memcpy (dest + 1, src, (size_t) (size - 1));
222
223 numBytesUsed += (numVariableLengthSysexBytes + size); // (these aren't counted in the size)
224 }
225 else if (byte == 0xff)
226 {
227 if (sz == 1)
228 {
229 size = 1;
230 }
231 else
232 {
233 int n;
234 const int bytesLeft = readVariableLengthVal (src + 1, n);
235 size = jmin (sz + 1, n + 2 + bytesLeft);
236 }
237
238 auto dest = allocateSpace (size);
239 *dest = (uint8) byte;
240 memcpy (dest + 1, src, (size_t) size - 1);
241
242 numBytesUsed += size;
243 }
244 else
245 {
246 size = getMessageLengthFromFirstByte ((uint8) byte);
247 packedData.asBytes[0] = (uint8) byte;
248
249 if (size > 1)
250 {
251 packedData.asBytes[1] = (sz > 0 ? src[0] : 0);
252
253 if (size > 2)
254 packedData.asBytes[2] = (sz > 1 ? src[1] : 0);
255 }
256
257 numBytesUsed += jmin (size, sz + 1);
258 }
259 }
260 else
261 {
262 packedData.allocatedData = nullptr;
263 size = 0;
264 }
265}
266
267 MidiMessage& MidiMessage::operator= (const MidiMessage& other)
268{
269 if (this != &other)
270 {
271 if (other.isHeapAllocated())
272 {
273 if (isHeapAllocated())
274 packedData.allocatedData = static_cast<uint8*> (std::realloc (packedData.allocatedData, (size_t) other.size));
275 else
276 packedData.allocatedData = static_cast<uint8*> (std::malloc ((size_t) other.size));
277
278 memcpy (packedData.allocatedData, other.packedData.allocatedData, (size_t) other.size);
279 }
280 else
281 {
282 if (isHeapAllocated())
283 std::free (packedData.allocatedData);
284
285 packedData.allocatedData = other.packedData.allocatedData;
286 }
287
288 timeStamp = other.timeStamp;
289 size = other.size;
290 }
291
292 return *this;
293}
294
295 MidiMessage::MidiMessage (MidiMessage&& other) noexcept
296 : timeStamp (other.timeStamp), size (other.size)
297{
298 packedData.allocatedData = other.packedData.allocatedData;
299 other.size = 0;
300}
301
302 MidiMessage& MidiMessage::operator= (MidiMessage&& other) noexcept
303{
304 packedData.allocatedData = other.packedData.allocatedData;
305 timeStamp = other.timeStamp;
306 size = other.size;
307 other.size = 0;
308 return *this;
309}
310
311MidiMessage::~MidiMessage() noexcept
312{
313 if (isHeapAllocated())
314 std::free (packedData.allocatedData);
315}
316
317uint8* MidiMessage::allocateSpace (int bytes)
318{
319 if (bytes > (int) sizeof (packedData))
320 {
321 auto d = static_cast<uint8*> (std::malloc ((size_t) bytes));
322 packedData.allocatedData = d;
323 return d;
324 }
325
326 return packedData.asBytes;
327}
328
329 String MidiMessage::getDescription() const
330{
331 if (isNoteOn()) return "Note on " + MidiMessage::getMidiNoteName (getNoteNumber(), true, true, 3) + " Velocity " + String (getVelocity()) + " Channel " + String (getChannel());
332 if (isNoteOff()) return "Note off " + MidiMessage::getMidiNoteName (getNoteNumber(), true, true, 3) + " Velocity " + String (getVelocity()) + " Channel " + String (getChannel());
333 if (isProgramChange()) return "Program change " + String (getProgramChangeNumber()) + " Channel " + String (getChannel());
334 if (isPitchWheel()) return "Pitch wheel " + String (getPitchWheelValue()) + " Channel " + String (getChannel());
335 if (isAftertouch()) return "Aftertouch " + MidiMessage::getMidiNoteName (getNoteNumber(), true, true, 3) + ": " + String (getAfterTouchValue()) + " Channel " + String (getChannel());
336 if (isChannelPressure()) return "Channel pressure " + String (getChannelPressureValue()) + " Channel " + String (getChannel());
337 if (isAllNotesOff()) return "All notes off Channel " + String (getChannel());
338 if (isAllSoundOff()) return "All sound off Channel " + String (getChannel());
339 if (isMetaEvent()) return "Meta event";
340
341 if (isController())
342 {
343 String name (MidiMessage::getControllerName (getControllerNumber()));
344
345 if (name.isEmpty())
346 name = String (getControllerNumber());
347
348 return "Controller " + name + ": " + String (getControllerValue()) + " Channel " + String (getChannel());
349 }
350
351 return String::toHexString (getRawData(), getRawDataSize());
352}
353
354 MidiMessage MidiMessage::withTimeStamp (double newTimestamp) const
355{
356 return { *this, newTimestamp };
357}
358
359 int MidiMessage::getChannel() const noexcept
360{
361 auto data = getRawData();
362
363 if ((data[0] & 0xf0) != 0xf0)
364 return (data[0] & 0xf) + 1;
365
366 return 0;
367}
368
369 bool MidiMessage::isForChannel (const int channel) const noexcept
370{
371 jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
372
373 auto data = getRawData();
374
375 return ((data[0] & 0xf) == channel - 1)
376 && ((data[0] & 0xf0) != 0xf0);
377}
378
379 void MidiMessage::setChannel (const int channel) noexcept
380{
381 jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
382
383 auto data = getData();
384
385 if ((data[0] & 0xf0) != (uint8) 0xf0)
386 data[0] = (uint8) ((data[0] & (uint8) 0xf0)
387 | (uint8)(channel - 1));
388}
389
390 bool MidiMessage::isNoteOn (const bool returnTrueForVelocity0) const noexcept
391{
392 auto data = getRawData();
393
394 return ((data[0] & 0xf0) == 0x90)
395 && (returnTrueForVelocity0 || data[2] != 0);
396}
397
398 bool MidiMessage::isNoteOff (const bool returnTrueForNoteOnVelocity0) const noexcept
399{
400 auto data = getRawData();
401
402 return ((data[0] & 0xf0) == 0x80)
403 || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90));
404}
405
406 bool MidiMessage::isNoteOnOrOff() const noexcept
407{
408 auto d = getRawData()[0] & 0xf0;
409 return (d == 0x90) || (d == 0x80);
410}
411
412 int MidiMessage::getNoteNumber() const noexcept
413{
414 return getRawData()[1];
415}
416
417 void MidiMessage::setNoteNumber (const int newNoteNumber) noexcept
418{
419 if (isNoteOnOrOff() || isAftertouch())
420 getData()[1] = (uint8) (newNoteNumber & 127);
421}
422
423uint8 MidiMessage::getVelocity() const noexcept
424{
425 if (isNoteOnOrOff())
426 return getRawData()[2];
427
428 return 0;
429}
430
431 float MidiMessage::getFloatVelocity() const noexcept
432{
433 return getVelocity() * (1.0f / 127.0f);
434}
435
436 void MidiMessage::setVelocity (const float newVelocity) noexcept
437{
438 if (isNoteOnOrOff())
439 getData()[2] = floatValueToMidiByte (newVelocity);
440}
441
442 void MidiMessage::multiplyVelocity (const float scaleFactor) noexcept
443{
444 if (isNoteOnOrOff())
445 {
446 auto data = getData();
447 data[2] = MidiHelpers::validVelocity (roundToInt (scaleFactor * data[2]));
448 }
449}
450
451 bool MidiMessage::isAftertouch() const noexcept
452{
453 return (getRawData()[0] & 0xf0) == 0xa0;
454}
455
456 int MidiMessage::getAfterTouchValue() const noexcept
457{
458 jassert (isAftertouch());
459 return getRawData()[2];
460}
461
462 MidiMessage MidiMessage::aftertouchChange (const int channel,
463 const int noteNum,
464 const int aftertouchValue) noexcept
465{
466 jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
467 jassert (isPositiveAndBelow (noteNum, 128));
468 jassert (isPositiveAndBelow (aftertouchValue, 128));
469
470 return MidiMessage (MidiHelpers::initialByte (0xa0, channel),
471 noteNum & 0x7f,
472 aftertouchValue & 0x7f);
473}
474
475 bool MidiMessage::isChannelPressure() const noexcept
476{
477 return (getRawData()[0] & 0xf0) == 0xd0;
478}
479
480 int MidiMessage::getChannelPressureValue() const noexcept
481{
482 jassert (isChannelPressure());
483 return getRawData()[1];
484}
485
486 MidiMessage MidiMessage::channelPressureChange (const int channel, const int pressure) noexcept
487{
488 jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
489 jassert (isPositiveAndBelow (pressure, 128));
490
491 return MidiMessage (MidiHelpers::initialByte (0xd0, channel), pressure & 0x7f);
492}
493
494 bool MidiMessage::isSustainPedalOn() const noexcept { return isControllerOfType (0x40) && getRawData()[2] >= 64; }
495 bool MidiMessage::isSustainPedalOff() const noexcept { return isControllerOfType (0x40) && getRawData()[2] < 64; }
496
497 bool MidiMessage::isSostenutoPedalOn() const noexcept { return isControllerOfType (0x42) && getRawData()[2] >= 64; }
498 bool MidiMessage::isSostenutoPedalOff() const noexcept { return isControllerOfType (0x42) && getRawData()[2] < 64; }
499
500 bool MidiMessage::isSoftPedalOn() const noexcept { return isControllerOfType (0x43) && getRawData()[2] >= 64; }
501 bool MidiMessage::isSoftPedalOff() const noexcept { return isControllerOfType (0x43) && getRawData()[2] < 64; }
502
503
504 bool MidiMessage::isProgramChange() const noexcept
505{
506 return (getRawData()[0] & 0xf0) == 0xc0;
507}
508
509 int MidiMessage::getProgramChangeNumber() const noexcept
510{
511 jassert (isProgramChange());
512 return getRawData()[1];
513}
514
515 MidiMessage MidiMessage::programChange (const int channel, const int programNumber) noexcept
516{
517 jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
518
519 return MidiMessage (MidiHelpers::initialByte (0xc0, channel), programNumber & 0x7f);
520}
521
522 bool MidiMessage::isPitchWheel() const noexcept
523{
524 return (getRawData()[0] & 0xf0) == 0xe0;
525}
526
527 int MidiMessage::getPitchWheelValue() const noexcept
528{
529 jassert (isPitchWheel());
530 auto data = getRawData();
531 return data[1] | (data[2] << 7);
532}
533
534 MidiMessage MidiMessage::pitchWheel (const int channel, const int position) noexcept
535{
536 jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
537 jassert (isPositiveAndBelow (position, 0x4000));
538
539 return MidiMessage (MidiHelpers::initialByte (0xe0, channel),
540 position & 127, (position >> 7) & 127);
541}
542
543 bool MidiMessage::isController() const noexcept
544{
545 return (getRawData()[0] & 0xf0) == 0xb0;
546}
547
548 bool MidiMessage::isControllerOfType (const int controllerType) const noexcept
549{
550 auto data = getRawData();
551 return (data[0] & 0xf0) == 0xb0 && data[1] == controllerType;
552}
553
554 int MidiMessage::getControllerNumber() const noexcept
555{
556 jassert (isController());
557 return getRawData()[1];
558}
559
560 int MidiMessage::getControllerValue() const noexcept
561{
562 jassert (isController());
563 return getRawData()[2];
564}
565
566 MidiMessage MidiMessage::controllerEvent (const int channel, const int controllerType, const int value) noexcept
567{
568 // the channel must be between 1 and 16 inclusive
569 jassert (channel > 0 && channel <= 16);
570
571 return MidiMessage (MidiHelpers::initialByte (0xb0, channel),
572 controllerType & 127, value & 127);
573}
574
575 MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const uint8 velocity) noexcept
576{
577 jassert (channel > 0 && channel <= 16);
578 jassert (isPositiveAndBelow (noteNumber, 128));
579
580 return MidiMessage (MidiHelpers::initialByte (0x90, channel),
581 noteNumber & 127, MidiHelpers::validVelocity (velocity));
582}
583
584 MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const float velocity) noexcept
585{
586 return noteOn (channel, noteNumber, floatValueToMidiByte (velocity));
587}
588
589 MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept
590{
591 jassert (channel > 0 && channel <= 16);
592 jassert (isPositiveAndBelow (noteNumber, 128));
593
594 return MidiMessage (MidiHelpers::initialByte (0x80, channel),
595 noteNumber & 127, MidiHelpers::validVelocity (velocity));
596}
597
598 MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, float velocity) noexcept
599{
600 return noteOff (channel, noteNumber, floatValueToMidiByte (velocity));
601}
602
603 MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber) noexcept
604{
605 jassert (channel > 0 && channel <= 16);
606 jassert (isPositiveAndBelow (noteNumber, 128));
607
608 return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0);
609}
610
611 MidiMessage MidiMessage::allNotesOff (const int channel) noexcept
612{
613 return controllerEvent (channel, 123, 0);
614}
615
616 bool MidiMessage::isAllNotesOff() const noexcept
617{
618 auto data = getRawData();
619 return (data[0] & 0xf0) == 0xb0 && data[1] == 123;
620}
621
622 MidiMessage MidiMessage::allSoundOff (const int channel) noexcept
623{
624 return controllerEvent (channel, 120, 0);
625}
626
627 bool MidiMessage::isAllSoundOff() const noexcept
628{
629 auto data = getRawData();
630 return data[1] == 120 && (data[0] & 0xf0) == 0xb0;
631}
632
633 bool MidiMessage::isResetAllControllers() const noexcept
634{
635 auto data = getRawData();
636 return (data[0] & 0xf0) == 0xb0 && data[1] == 121;
637}
638
639 MidiMessage MidiMessage::allControllersOff (const int channel) noexcept
640{
641 return controllerEvent (channel, 121, 0);
642}
643
644 MidiMessage MidiMessage::masterVolume (const float volume)
645{
646 auto vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000));
647
648 return { 0xf0, 0x7f, 0x7f, 0x04, 0x01, vol & 0x7f, vol >> 7, 0xf7 };
649}
650
651//==============================================================================
652 bool MidiMessage::isSysEx() const noexcept
653{
654 return *getRawData() == 0xf0;
655}
656
657 MidiMessage MidiMessage::createSysExMessage (const void* sysexData, const int dataSize)
658{
659 HeapBlock<uint8> m (dataSize + 2);
660
661 m[0] = 0xf0;
662 memcpy (m + 1, sysexData, (size_t) dataSize);
663 m[dataSize + 1] = 0xf7;
664
665 return MidiMessage (m, dataSize + 2);
666}
667
668 const uint8* MidiMessage::getSysExData() const noexcept
669{
670 return isSysEx() ? getRawData() + 1 : nullptr;
671}
672
673 int MidiMessage::getSysExDataSize() const noexcept
674{
675 return isSysEx() ? size - 2 : 0;
676}
677
678//==============================================================================
679 bool MidiMessage::isMetaEvent() const noexcept { return *getRawData() == 0xff; }
680 bool MidiMessage::isActiveSense() const noexcept { return *getRawData() == 0xfe; }
681
682 int MidiMessage::getMetaEventType() const noexcept
683{
684 auto data = getRawData();
685 return *data != 0xff ? -1 : data[1];
686}
687
688 int MidiMessage::getMetaEventLength() const noexcept
689{
690 auto data = getRawData();
691
692 if (*data == 0xff)
693 {
694 int n;
695 return jmin (size - 2, readVariableLengthVal (data + 2, n));
696 }
697
698 return 0;
699}
700
701 const uint8* MidiMessage::getMetaEventData() const noexcept
702{
703 jassert (isMetaEvent());
704
705 int n;
706 auto d = getRawData() + 2;
707 readVariableLengthVal (d, n);
708 return d + n;
709}
710
711 bool MidiMessage::isTrackMetaEvent() const noexcept { return getMetaEventType() == 0; }
712 bool MidiMessage::isEndOfTrackMetaEvent() const noexcept { return getMetaEventType() == 47; }
713
714 bool MidiMessage::isTextMetaEvent() const noexcept
715{
716 auto t = getMetaEventType();
717 return t > 0 && t < 16;
718}
719
720 String MidiMessage::getTextFromTextMetaEvent() const
721{
722 auto textData = reinterpret_cast<const char*> (getMetaEventData());
723
724 return String (CharPointer_UTF8 (textData),
725 CharPointer_UTF8 (textData + getMetaEventLength()));
726}
727
728 MidiMessage MidiMessage::textMetaEvent (int type, StringRef text)
729{
730 jassert (type > 0 && type < 16);
731
732 MidiMessage result;
733
734 const size_t textSize = text.text.sizeInBytes() - 1;
735
736 uint8 header[8];
737 size_t n = sizeof (header);
738
739 header[--n] = (uint8) (textSize & 0x7f);
740
741 for (size_t i = textSize; (i >>= 7) != 0;)
742 header[--n] = (uint8) ((i & 0x7f) | 0x80);
743
744 header[--n] = (uint8) type;
745 header[--n] = 0xff;
746
747 const size_t headerLen = sizeof (header) - n;
748 const int totalSize = (int) (headerLen + textSize);
749
750 auto dest = result.allocateSpace (totalSize);
751 result.size = totalSize;
752
753 memcpy (dest, header + n, headerLen);
754 memcpy (dest + headerLen, text.text.getAddress(), textSize);
755
756 return result;
757}
758
759 bool MidiMessage::isTrackNameEvent() const noexcept { auto data = getRawData(); return (data[1] == 3) && (*data == 0xff); }
760 bool MidiMessage::isTempoMetaEvent() const noexcept { auto data = getRawData(); return (data[1] == 81) && (*data == 0xff); }
761 bool MidiMessage::isMidiChannelMetaEvent() const noexcept { auto data = getRawData(); return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); }
762
763 int MidiMessage::getMidiChannelMetaEventChannel() const noexcept
764{
765 jassert (isMidiChannelMetaEvent());
766 return getRawData()[3] + 1;
767}
768
769 double MidiMessage::getTempoSecondsPerQuarterNote() const noexcept
770{
771 if (! isTempoMetaEvent())
772 return 0.0;
773
774 auto d = getMetaEventData();
775
776 return (((unsigned int) d[0] << 16)
777 | ((unsigned int) d[1] << 8)
778 | d[2])
779 / 1000000.0;
780}
781
782 double MidiMessage::getTempoMetaEventTickLength (const short timeFormat) const noexcept
783{
784 if (timeFormat > 0)
785 {
786 if (! isTempoMetaEvent())
787 return 0.5 / timeFormat;
788
789 return getTempoSecondsPerQuarterNote() / timeFormat;
790 }
791
792 const int frameCode = (-timeFormat) >> 8;
793 double framesPerSecond;
794
795 switch (frameCode)
796 {
797 case 24: framesPerSecond = 24.0; break;
798 case 25: framesPerSecond = 25.0; break;
799 case 29: framesPerSecond = 30.0 * 1000.0 / 1001.0; break;
800 case 30: framesPerSecond = 30.0; break;
801 default: framesPerSecond = 30.0; break;
802 }
803
804 return (1.0 / framesPerSecond) / (timeFormat & 0xff);
805}
806
807 MidiMessage MidiMessage::tempoMetaEvent (int microsecondsPerQuarterNote) noexcept
808{
809 return { 0xff, 81, 3,
810 (uint8) (microsecondsPerQuarterNote >> 16),
811 (uint8) (microsecondsPerQuarterNote >> 8),
812 (uint8) microsecondsPerQuarterNote };
813}
814
815 bool MidiMessage::isTimeSignatureMetaEvent() const noexcept
816{
817 auto data = getRawData();
818 return (data[1] == 0x58) && (*data == (uint8) 0xff);
819}
820
821 void MidiMessage::getTimeSignatureInfo (int& numerator, int& denominator) const noexcept
822{
823 if (isTimeSignatureMetaEvent())
824 {
825 auto d = getMetaEventData();
826 numerator = d[0];
827 denominator = 1 << d[1];
828 }
829 else
830 {
831 numerator = 4;
832 denominator = 4;
833 }
834}
835
836 MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, const int denominator)
837{
838 int n = 1;
839 int powerOfTwo = 0;
840
841 while (n < denominator)
842 {
843 n <<= 1;
844 ++powerOfTwo;
845 }
846
847 return { 0xff, 0x58, 0x04, numerator, powerOfTwo, 1, 96 };
848}
849
850 MidiMessage MidiMessage::midiChannelMetaEvent (const int channel) noexcept
851{
852 return { 0xff, 0x20, 0x01, jlimit (0, 0xff, channel - 1) };
853}
854
855 bool MidiMessage::isKeySignatureMetaEvent() const noexcept
856{
857 return getMetaEventType() == 0x59;
858}
859
860 int MidiMessage::getKeySignatureNumberOfSharpsOrFlats() const noexcept
861{
862 return (int) (int8) getMetaEventData()[0];
863}
864
865 bool MidiMessage::isKeySignatureMajorKey() const noexcept
866{
867 return getMetaEventData()[1] == 0;
868}
869
870 MidiMessage MidiMessage::keySignatureMetaEvent (int numberOfSharpsOrFlats, bool isMinorKey)
871{
872 jassert (numberOfSharpsOrFlats >= -7 && numberOfSharpsOrFlats <= 7);
873
874 return { 0xff, 0x59, 0x02, numberOfSharpsOrFlats, isMinorKey ? 1 : 0 };
875}
876
877 MidiMessage MidiMessage::endOfTrack() noexcept
878{
879 return { 0xff, 0x2f, 0x00 };
880}
881
882//==============================================================================
883 bool MidiMessage::isSongPositionPointer() const noexcept { return *getRawData() == 0xf2; }
884 int MidiMessage::getSongPositionPointerMidiBeat() const noexcept { auto data = getRawData(); return data[1] | (data[2] << 7); }
885
886 MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeats) noexcept
887{
888 return { 0xf2,
889 positionInMidiBeats & 127,
890 (positionInMidiBeats >> 7) & 127 };
891}
892
893 bool MidiMessage::isMidiStart() const noexcept { return *getRawData() == 0xfa; }
894 MidiMessage MidiMessage::midiStart() noexcept { return MidiMessage (0xfa); }
895
896 bool MidiMessage::isMidiContinue() const noexcept { return *getRawData() == 0xfb; }
897 MidiMessage MidiMessage::midiContinue() noexcept { return MidiMessage (0xfb); }
898
899 bool MidiMessage::isMidiStop() const noexcept { return *getRawData() == 0xfc; }
900 MidiMessage MidiMessage::midiStop() noexcept { return MidiMessage (0xfc); }
901
902 bool MidiMessage::isMidiClock() const noexcept { return *getRawData() == 0xf8; }
903 MidiMessage MidiMessage::midiClock() noexcept { return MidiMessage (0xf8); }
904
905 bool MidiMessage::isQuarterFrame() const noexcept { return *getRawData() == 0xf1; }
906 int MidiMessage::getQuarterFrameSequenceNumber() const noexcept { return ((int) getRawData()[1]) >> 4; }
907 int MidiMessage::getQuarterFrameValue() const noexcept { return ((int) getRawData()[1]) & 0x0f; }
908
909 MidiMessage MidiMessage::quarterFrame (const int sequenceNumber, const int value) noexcept
910{
911 return MidiMessage (0xf1, (sequenceNumber << 4) | value);
912}
913
914 bool MidiMessage::isFullFrame() const noexcept
915{
916 auto data = getRawData();
917
918 return data[0] == 0xf0
919 && data[1] == 0x7f
920 && size >= 10
921 && data[3] == 0x01
922 && data[4] == 0x01;
923}
924
925 void MidiMessage::getFullFrameParameters (int& hours, int& minutes, int& seconds, int& frames,
926 MidiMessage::SmpteTimecodeType& timecodeType) const noexcept
927{
928 jassert (isFullFrame());
929
930 auto data = getRawData();
931 timecodeType = (SmpteTimecodeType) (data[5] >> 5);
932 hours = data[5] & 0x1f;
933 minutes = data[6];
934 seconds = data[7];
935 frames = data[8];
936}
937
938 MidiMessage MidiMessage::fullFrame (int hours, int minutes, int seconds, int frames,
939 MidiMessage::SmpteTimecodeType timecodeType)
940{
941 return { 0xf0, 0x7f, 0x7f, 0x01, 0x01,
942 (hours & 0x01f) | (timecodeType << 5),
943 minutes, seconds, frames,
944 0xf7 };
945}
946
947 bool MidiMessage::isMidiMachineControlMessage() const noexcept
948{
949 auto data = getRawData();
950
951 return data[0] == 0xf0
952 && data[1] == 0x7f
953 && data[3] == 0x06
954 && size > 5;
955}
956
957 MidiMessage::MidiMachineControlCommand MidiMessage::getMidiMachineControlCommand() const noexcept
958{
959 jassert (isMidiMachineControlMessage());
960
961 return (MidiMachineControlCommand) getRawData()[4];
962}
963
964 MidiMessage MidiMessage::midiMachineControlCommand (MidiMessage::MidiMachineControlCommand command)
965{
966 return { 0xf0, 0x7f, 0, 6, command, 0xf7 };
967}
968
969//==============================================================================
970 bool MidiMessage::isMidiMachineControlGoto (int& hours, int& minutes, int& seconds, int& frames) const noexcept
971{
972 auto data = getRawData();
973
974 if (size >= 12
975 && data[0] == 0xf0
976 && data[1] == 0x7f
977 && data[3] == 0x06
978 && data[4] == 0x44
979 && data[5] == 0x06
980 && data[6] == 0x01)
981 {
982 hours = data[7] % 24; // (that some machines send out hours > 24)
983 minutes = data[8];
984 seconds = data[9];
985 frames = data[10];
986
987 return true;
988 }
989
990 return false;
991}
992
993 MidiMessage MidiMessage::midiMachineControlGoto (int hours, int minutes, int seconds, int frames)
994{
995 return { 0xf0, 0x7f, 0, 6, 0x44, 6, 1, hours, minutes, seconds, frames, 0xf7 };
996}
997
998//==============================================================================
999 String MidiMessage::getMidiNoteName (int note, bool useSharps, bool includeOctaveNumber, int octaveNumForMiddleC)
1000{
1001 static const char* const sharpNoteNames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
1002 static const char* const flatNoteNames[] = { "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" };
1003
1004 if (isPositiveAndBelow (note, 128))
1005 {
1006 String s (useSharps ? sharpNoteNames[note % 12]
1007 : flatNoteNames [note % 12]);
1008
1009 if (includeOctaveNumber)
1010 s << (note / 12 + (octaveNumForMiddleC - 5));
1011
1012 return s;
1013 }
1014
1015 return {};
1016}
1017
1018 double MidiMessage::getMidiNoteInHertz (const int noteNumber, const double frequencyOfA) noexcept
1019{
1020 return frequencyOfA * std::pow (2.0, (noteNumber - 69) / 12.0);
1021}
1022
1023 bool MidiMessage::isMidiNoteBlack (int noteNumber) noexcept
1024{
1025 return ((1 << (noteNumber % 12)) & 0x054a) != 0;
1026}
1027
1028 const char* MidiMessage::getGMInstrumentName (const int n)
1029{
1030 static const char* names[] =
1031 {
1032 NEEDS_TRANS("Acoustic Grand Piano"), NEEDS_TRANS("Bright Acoustic Piano"), NEEDS_TRANS("Electric Grand Piano"), NEEDS_TRANS("Honky-tonk Piano"),
1033 NEEDS_TRANS("Electric Piano 1"), NEEDS_TRANS("Electric Piano 2"), NEEDS_TRANS("Harpsichord"), NEEDS_TRANS("Clavinet"),
1034 NEEDS_TRANS("Celesta"), NEEDS_TRANS("Glockenspiel"), NEEDS_TRANS("Music Box"), NEEDS_TRANS("Vibraphone"),
1035 NEEDS_TRANS("Marimba"), NEEDS_TRANS("Xylophone"), NEEDS_TRANS("Tubular Bells"), NEEDS_TRANS("Dulcimer"),
1036 NEEDS_TRANS("Drawbar Organ"), NEEDS_TRANS("Percussive Organ"), NEEDS_TRANS("Rock Organ"), NEEDS_TRANS("Church Organ"),
1037 NEEDS_TRANS("Reed Organ"), NEEDS_TRANS("Accordion"), NEEDS_TRANS("Harmonica"), NEEDS_TRANS("Tango Accordion"),
1038 NEEDS_TRANS("Acoustic Guitar (nylon)"), NEEDS_TRANS("Acoustic Guitar (steel)"), NEEDS_TRANS("Electric Guitar (jazz)"), NEEDS_TRANS("Electric Guitar (clean)"),
1039 NEEDS_TRANS("Electric Guitar (mute)"), NEEDS_TRANS("Overdriven Guitar"), NEEDS_TRANS("Distortion Guitar"), NEEDS_TRANS("Guitar Harmonics"),
1040 NEEDS_TRANS("Acoustic Bass"), NEEDS_TRANS("Electric Bass (finger)"), NEEDS_TRANS("Electric Bass (pick)"), NEEDS_TRANS("Fretless Bass"),
1041 NEEDS_TRANS("Slap Bass 1"), NEEDS_TRANS("Slap Bass 2"), NEEDS_TRANS("Synth Bass 1"), NEEDS_TRANS("Synth Bass 2"),
1042 NEEDS_TRANS("Violin"), NEEDS_TRANS("Viola"), NEEDS_TRANS("Cello"), NEEDS_TRANS("Contrabass"),
1043 NEEDS_TRANS("Tremolo Strings"), NEEDS_TRANS("Pizzicato Strings"), NEEDS_TRANS("Orchestral Harp"), NEEDS_TRANS("Timpani"),
1044 NEEDS_TRANS("String Ensemble 1"), NEEDS_TRANS("String Ensemble 2"), NEEDS_TRANS("SynthStrings 1"), NEEDS_TRANS("SynthStrings 2"),
1045 NEEDS_TRANS("Choir Aahs"), NEEDS_TRANS("Voice Oohs"), NEEDS_TRANS("Synth Voice"), NEEDS_TRANS("Orchestra Hit"),
1046 NEEDS_TRANS("Trumpet"), NEEDS_TRANS("Trombone"), NEEDS_TRANS("Tuba"), NEEDS_TRANS("Muted Trumpet"),
1047 NEEDS_TRANS("French Horn"), NEEDS_TRANS("Brass Section"), NEEDS_TRANS("SynthBrass 1"), NEEDS_TRANS("SynthBrass 2"),
1048 NEEDS_TRANS("Soprano Sax"), NEEDS_TRANS("Alto Sax"), NEEDS_TRANS("Tenor Sax"), NEEDS_TRANS("Baritone Sax"),
1049 NEEDS_TRANS("Oboe"), NEEDS_TRANS("English Horn"), NEEDS_TRANS("Bassoon"), NEEDS_TRANS("Clarinet"),
1050 NEEDS_TRANS("Piccolo"), NEEDS_TRANS("Flute"), NEEDS_TRANS("Recorder"), NEEDS_TRANS("Pan Flute"),
1051 NEEDS_TRANS("Blown Bottle"), NEEDS_TRANS("Shakuhachi"), NEEDS_TRANS("Whistle"), NEEDS_TRANS("Ocarina"),
1052 NEEDS_TRANS("Lead 1 (square)"), NEEDS_TRANS("Lead 2 (sawtooth)"), NEEDS_TRANS("Lead 3 (calliope)"), NEEDS_TRANS("Lead 4 (chiff)"),
1053 NEEDS_TRANS("Lead 5 (charang)"), NEEDS_TRANS("Lead 6 (voice)"), NEEDS_TRANS("Lead 7 (fifths)"), NEEDS_TRANS("Lead 8 (bass+lead)"),
1054 NEEDS_TRANS("Pad 1 (new age)"), NEEDS_TRANS("Pad 2 (warm)"), NEEDS_TRANS("Pad 3 (polysynth)"), NEEDS_TRANS("Pad 4 (choir)"),
1055 NEEDS_TRANS("Pad 5 (bowed)"), NEEDS_TRANS("Pad 6 (metallic)"), NEEDS_TRANS("Pad 7 (halo)"), NEEDS_TRANS("Pad 8 (sweep)"),
1056 NEEDS_TRANS("FX 1 (rain)"), NEEDS_TRANS("FX 2 (soundtrack)"), NEEDS_TRANS("FX 3 (crystal)"), NEEDS_TRANS("FX 4 (atmosphere)"),
1057 NEEDS_TRANS("FX 5 (brightness)"), NEEDS_TRANS("FX 6 (goblins)"), NEEDS_TRANS("FX 7 (echoes)"), NEEDS_TRANS("FX 8 (sci-fi)"),
1058 NEEDS_TRANS("Sitar"), NEEDS_TRANS("Banjo"), NEEDS_TRANS("Shamisen"), NEEDS_TRANS("Koto"),
1059 NEEDS_TRANS("Kalimba"), NEEDS_TRANS("Bag pipe"), NEEDS_TRANS("Fiddle"), NEEDS_TRANS("Shanai"),
1060 NEEDS_TRANS("Tinkle Bell"), NEEDS_TRANS("Agogo"), NEEDS_TRANS("Steel Drums"), NEEDS_TRANS("Woodblock"),
1061 NEEDS_TRANS("Taiko Drum"), NEEDS_TRANS("Melodic Tom"), NEEDS_TRANS("Synth Drum"), NEEDS_TRANS("Reverse Cymbal"),
1062 NEEDS_TRANS("Guitar Fret Noise"), NEEDS_TRANS("Breath Noise"), NEEDS_TRANS("Seashore"), NEEDS_TRANS("Bird Tweet"),
1063 NEEDS_TRANS("Telephone Ring"), NEEDS_TRANS("Helicopter"), NEEDS_TRANS("Applause"), NEEDS_TRANS("Gunshot")
1064 };
1065
1066 return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
1067}
1068
1069 const char* MidiMessage::getGMInstrumentBankName (const int n)
1070{
1071 static const char* names[] =
1072 {
1073 NEEDS_TRANS("Piano"), NEEDS_TRANS("Chromatic Percussion"), NEEDS_TRANS("Organ"), NEEDS_TRANS("Guitar"),
1074 NEEDS_TRANS("Bass"), NEEDS_TRANS("Strings"), NEEDS_TRANS("Ensemble"), NEEDS_TRANS("Brass"),
1075 NEEDS_TRANS("Reed"), NEEDS_TRANS("Pipe"), NEEDS_TRANS("Synth Lead"), NEEDS_TRANS("Synth Pad"),
1076 NEEDS_TRANS("Synth Effects"), NEEDS_TRANS("Ethnic"), NEEDS_TRANS("Percussive"), NEEDS_TRANS("Sound Effects")
1077 };
1078
1079 return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
1080}
1081
1082 const char* MidiMessage::getRhythmInstrumentName (const int n)
1083{
1084 static const char* names[] =
1085 {
1086 NEEDS_TRANS("Acoustic Bass Drum"), NEEDS_TRANS("Bass Drum 1"), NEEDS_TRANS("Side Stick"), NEEDS_TRANS("Acoustic Snare"),
1087 NEEDS_TRANS("Hand Clap"), NEEDS_TRANS("Electric Snare"), NEEDS_TRANS("Low Floor Tom"), NEEDS_TRANS("Closed Hi-Hat"),
1088 NEEDS_TRANS("High Floor Tom"), NEEDS_TRANS("Pedal Hi-Hat"), NEEDS_TRANS("Low Tom"), NEEDS_TRANS("Open Hi-Hat"),
1089 NEEDS_TRANS("Low-Mid Tom"), NEEDS_TRANS("Hi-Mid Tom"), NEEDS_TRANS("Crash Cymbal 1"), NEEDS_TRANS("High Tom"),
1090 NEEDS_TRANS("Ride Cymbal 1"), NEEDS_TRANS("Chinese Cymbal"), NEEDS_TRANS("Ride Bell"), NEEDS_TRANS("Tambourine"),
1091 NEEDS_TRANS("Splash Cymbal"), NEEDS_TRANS("Cowbell"), NEEDS_TRANS("Crash Cymbal 2"), NEEDS_TRANS("Vibraslap"),
1092 NEEDS_TRANS("Ride Cymbal 2"), NEEDS_TRANS("Hi Bongo"), NEEDS_TRANS("Low Bongo"), NEEDS_TRANS("Mute Hi Conga"),
1093 NEEDS_TRANS("Open Hi Conga"), NEEDS_TRANS("Low Conga"), NEEDS_TRANS("High Timbale"), NEEDS_TRANS("Low Timbale"),
1094 NEEDS_TRANS("High Agogo"), NEEDS_TRANS("Low Agogo"), NEEDS_TRANS("Cabasa"), NEEDS_TRANS("Maracas"),
1095 NEEDS_TRANS("Short Whistle"), NEEDS_TRANS("Long Whistle"), NEEDS_TRANS("Short Guiro"), NEEDS_TRANS("Long Guiro"),
1096 NEEDS_TRANS("Claves"), NEEDS_TRANS("Hi Wood Block"), NEEDS_TRANS("Low Wood Block"), NEEDS_TRANS("Mute Cuica"),
1097 NEEDS_TRANS("Open Cuica"), NEEDS_TRANS("Mute Triangle"), NEEDS_TRANS("Open Triangle")
1098 };
1099
1100 return (n >= 35 && n <= 81) ? names[n - 35] : nullptr;
1101}
1102
1103 const char* MidiMessage::getControllerName (const int n)
1104{
1105 static const char* names[] =
1106 {
1107 NEEDS_TRANS("Bank Select"), NEEDS_TRANS("Modulation Wheel (coarse)"), NEEDS_TRANS("Breath controller (coarse)"),
1108 nullptr,
1109 NEEDS_TRANS("Foot Pedal (coarse)"), NEEDS_TRANS("Portamento Time (coarse)"), NEEDS_TRANS("Data Entry (coarse)"),
1110 NEEDS_TRANS("Volume (coarse)"), NEEDS_TRANS("Balance (coarse)"),
1111 nullptr,
1112 NEEDS_TRANS("Pan position (coarse)"), NEEDS_TRANS("Expression (coarse)"), NEEDS_TRANS("Effect Control 1 (coarse)"),
1113 NEEDS_TRANS("Effect Control 2 (coarse)"),
1114 nullptr, nullptr,
1115 NEEDS_TRANS("General Purpose Slider 1"), NEEDS_TRANS("General Purpose Slider 2"),
1116 NEEDS_TRANS("General Purpose Slider 3"), NEEDS_TRANS("General Purpose Slider 4"),
1117 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
1118 NEEDS_TRANS("Bank Select (fine)"), NEEDS_TRANS("Modulation Wheel (fine)"), NEEDS_TRANS("Breath controller (fine)"),
1119 nullptr,
1120 NEEDS_TRANS("Foot Pedal (fine)"), NEEDS_TRANS("Portamento Time (fine)"), NEEDS_TRANS("Data Entry (fine)"), NEEDS_TRANS("Volume (fine)"),
1121 NEEDS_TRANS("Balance (fine)"), nullptr, NEEDS_TRANS("Pan position (fine)"), NEEDS_TRANS("Expression (fine)"),
1122 NEEDS_TRANS("Effect Control 1 (fine)"), NEEDS_TRANS("Effect Control 2 (fine)"),
1123 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
1124 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
1125 NEEDS_TRANS("Hold Pedal (on/off)"), NEEDS_TRANS("Portamento (on/off)"), NEEDS_TRANS("Sustenuto Pedal (on/off)"), NEEDS_TRANS("Soft Pedal (on/off)"),
1126 NEEDS_TRANS("Legato Pedal (on/off)"), NEEDS_TRANS("Hold 2 Pedal (on/off)"), NEEDS_TRANS("Sound Variation"), NEEDS_TRANS("Sound Timbre"),
1127 NEEDS_TRANS("Sound Release Time"), NEEDS_TRANS("Sound Attack Time"), NEEDS_TRANS("Sound Brightness"), NEEDS_TRANS("Sound Control 6"),
1128 NEEDS_TRANS("Sound Control 7"), NEEDS_TRANS("Sound Control 8"), NEEDS_TRANS("Sound Control 9"), NEEDS_TRANS("Sound Control 10"),
1129 NEEDS_TRANS("General Purpose Button 1 (on/off)"), NEEDS_TRANS("General Purpose Button 2 (on/off)"),
1130 NEEDS_TRANS("General Purpose Button 3 (on/off)"), NEEDS_TRANS("General Purpose Button 4 (on/off)"),
1131 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
1132 NEEDS_TRANS("Reverb Level"), NEEDS_TRANS("Tremolo Level"), NEEDS_TRANS("Chorus Level"), NEEDS_TRANS("Celeste Level"),
1133 NEEDS_TRANS("Phaser Level"), NEEDS_TRANS("Data Button increment"), NEEDS_TRANS("Data Button decrement"), NEEDS_TRANS("Non-registered Parameter (fine)"),
1134 NEEDS_TRANS("Non-registered Parameter (coarse)"), NEEDS_TRANS("Registered Parameter (fine)"), NEEDS_TRANS("Registered Parameter (coarse)"),
1135 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
1136 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
1137 NEEDS_TRANS("All Sound Off"), NEEDS_TRANS("All Controllers Off"), NEEDS_TRANS("Local Keyboard (on/off)"), NEEDS_TRANS("All Notes Off"),
1138 NEEDS_TRANS("Omni Mode Off"), NEEDS_TRANS("Omni Mode On"), NEEDS_TRANS("Mono Operation"), NEEDS_TRANS("Poly Operation")
1139 };
1140
1141 return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
1142}
1143
1144} // namespace juce
juce::CharPointer_UTF8
Definition: juce_CharPointer_UTF8.h:35
juce::HeapBlock
Definition: juce_HeapBlock.h:87
juce::MidiMessage
Definition: juce_MidiMessage.h:35
juce::MidiMessage::isTrackMetaEvent
bool isTrackMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:711
juce::MidiMessage::createSysExMessage
static MidiMessage createSysExMessage(const void *sysexData, int dataSize)
Definition: juce_MidiMessage.cpp:657
juce::MidiMessage::tempoMetaEvent
static MidiMessage tempoMetaEvent(int microsecondsPerQuarterNote) noexcept
Definition: juce_MidiMessage.cpp:807
juce::MidiMessage::midiStart
static MidiMessage midiStart() noexcept
Definition: juce_MidiMessage.cpp:894
juce::MidiMessage::~MidiMessage
~MidiMessage() noexcept
Definition: juce_MidiMessage.cpp:311
juce::MidiMessage::getSysExData
const uint8 * getSysExData() const noexcept
Definition: juce_MidiMessage.cpp:668
juce::MidiMessage::getDescription
String getDescription() const
Definition: juce_MidiMessage.cpp:329
juce::MidiMessage::getGMInstrumentBankName
static const char * getGMInstrumentBankName(int midiBankNumber)
Definition: juce_MidiMessage.cpp:1069
juce::MidiMessage::isAftertouch
bool isAftertouch() const noexcept
Definition: juce_MidiMessage.cpp:451
juce::MidiMessage::setNoteNumber
void setNoteNumber(int newNoteNumber) noexcept
Definition: juce_MidiMessage.cpp:417
juce::MidiMessage::isNoteOn
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Definition: juce_MidiMessage.cpp:390
juce::MidiMessage::getKeySignatureNumberOfSharpsOrFlats
int getKeySignatureNumberOfSharpsOrFlats() const noexcept
Definition: juce_MidiMessage.cpp:860
juce::MidiMessage::getSongPositionPointerMidiBeat
int getSongPositionPointerMidiBeat() const noexcept
Definition: juce_MidiMessage.cpp:884
juce::MidiMessage::multiplyVelocity
void multiplyVelocity(float scaleFactor) noexcept
Definition: juce_MidiMessage.cpp:442
juce::MidiMessage::getFullFrameParameters
void getFullFrameParameters(int &hours, int &minutes, int &seconds, int &frames, SmpteTimecodeType &timecodeType) const noexcept
Definition: juce_MidiMessage.cpp:925
juce::MidiMessage::getFloatVelocity
float getFloatVelocity() const noexcept
Definition: juce_MidiMessage.cpp:431
juce::MidiMessage::isMidiMachineControlMessage
bool isMidiMachineControlMessage() const noexcept
Definition: juce_MidiMessage.cpp:947
juce::MidiMessage::getChannel
int getChannel() const noexcept
Definition: juce_MidiMessage.cpp:359
juce::MidiMessage::isMidiNoteBlack
static bool isMidiNoteBlack(int noteNumber) noexcept
Definition: juce_MidiMessage.cpp:1023
juce::MidiMessage::aftertouchChange
static MidiMessage aftertouchChange(int channel, int noteNumber, int aftertouchAmount) noexcept
Definition: juce_MidiMessage.cpp:462
juce::MidiMessage::readVariableLengthVal
static int readVariableLengthVal(const uint8 *data, int &numBytesUsed) noexcept
Definition: juce_MidiMessage.cpp:60
juce::MidiMessage::getQuarterFrameSequenceNumber
int getQuarterFrameSequenceNumber() const noexcept
Definition: juce_MidiMessage.cpp:906
juce::MidiMessage::getSysExDataSize
int getSysExDataSize() const noexcept
Definition: juce_MidiMessage.cpp:673
juce::MidiMessage::isQuarterFrame
bool isQuarterFrame() const noexcept
Definition: juce_MidiMessage.cpp:905
juce::MidiMessage::getRawData
const uint8 * getRawData() const noexcept
Definition: juce_MidiMessage.h:133
juce::MidiMessage::isTextMetaEvent
bool isTextMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:714
juce::MidiMessage::setVelocity
void setVelocity(float newVelocity) noexcept
Definition: juce_MidiMessage.cpp:436
juce::MidiMessage::getMetaEventType
int getMetaEventType() const noexcept
Definition: juce_MidiMessage.cpp:682
juce::MidiMessage::isProgramChange
bool isProgramChange() const noexcept
Definition: juce_MidiMessage.cpp:504
juce::MidiMessage::isController
bool isController() const noexcept
Definition: juce_MidiMessage.cpp:543
juce::MidiMessage::getTimeSignatureInfo
void getTimeSignatureInfo(int &numerator, int &denominator) const noexcept
Definition: juce_MidiMessage.cpp:821
juce::MidiMessage::isAllSoundOff
bool isAllSoundOff() const noexcept
Definition: juce_MidiMessage.cpp:627
juce::MidiMessage::isSoftPedalOn
bool isSoftPedalOn() const noexcept
Definition: juce_MidiMessage.cpp:500
juce::MidiMessage::getControllerNumber
int getControllerNumber() const noexcept
Definition: juce_MidiMessage.cpp:554
juce::MidiMessage::isMidiStart
bool isMidiStart() const noexcept
Definition: juce_MidiMessage.cpp:893
juce::MidiMessage::getMidiNoteInHertz
static double getMidiNoteInHertz(int noteNumber, double frequencyOfA=440.0) noexcept
Definition: juce_MidiMessage.cpp:1018
juce::MidiMessage::getQuarterFrameValue
int getQuarterFrameValue() const noexcept
Definition: juce_MidiMessage.cpp:907
juce::MidiMessage::isTrackNameEvent
bool isTrackNameEvent() const noexcept
Definition: juce_MidiMessage.cpp:759
juce::MidiMessage::getChannelPressureValue
int getChannelPressureValue() const noexcept
Definition: juce_MidiMessage.cpp:480
juce::MidiMessage::pitchWheel
static MidiMessage pitchWheel(int channel, int position) noexcept
Definition: juce_MidiMessage.cpp:534
juce::MidiMessage::isForChannel
bool isForChannel(int channelNumber) const noexcept
Definition: juce_MidiMessage.cpp:369
juce::MidiMessage::isNoteOff
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Definition: juce_MidiMessage.cpp:398
juce::MidiMessage::getMetaEventData
const uint8 * getMetaEventData() const noexcept
Definition: juce_MidiMessage.cpp:701
juce::MidiMessage::isKeySignatureMetaEvent
bool isKeySignatureMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:855
juce::MidiMessage::noteOn
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Definition: juce_MidiMessage.cpp:584
juce::MidiMessage::quarterFrame
static MidiMessage quarterFrame(int sequenceNumber, int value) noexcept
Definition: juce_MidiMessage.cpp:909
juce::MidiMessage::isPitchWheel
bool isPitchWheel() const noexcept
Definition: juce_MidiMessage.cpp:522
juce::MidiMessage::isSustainPedalOn
bool isSustainPedalOn() const noexcept
Definition: juce_MidiMessage.cpp:494
juce::MidiMessage::isMidiContinue
bool isMidiContinue() const noexcept
Definition: juce_MidiMessage.cpp:896
juce::MidiMessage::midiStop
static MidiMessage midiStop() noexcept
Definition: juce_MidiMessage.cpp:900
juce::MidiMessage::timeSignatureMetaEvent
static MidiMessage timeSignatureMetaEvent(int numerator, int denominator)
Definition: juce_MidiMessage.cpp:836
juce::MidiMessage::isSostenutoPedalOn
bool isSostenutoPedalOn() const noexcept
Definition: juce_MidiMessage.cpp:497
juce::MidiMessage::pitchbendToPitchwheelPos
static uint16 pitchbendToPitchwheelPos(float pitchbendInSemitones, float pitchbendRangeInSemitones) noexcept
Definition: juce_MidiMessage.cpp:48
juce::MidiMessage::getNoteNumber
int getNoteNumber() const noexcept
Definition: juce_MidiMessage.cpp:412
juce::MidiMessage::midiChannelMetaEvent
static MidiMessage midiChannelMetaEvent(int channel) noexcept
Definition: juce_MidiMessage.cpp:850
juce::MidiMessage::getProgramChangeNumber
int getProgramChangeNumber() const noexcept
Definition: juce_MidiMessage.cpp:509
juce::MidiMessage::getGMInstrumentName
static const char * getGMInstrumentName(int midiInstrumentNumber)
Definition: juce_MidiMessage.cpp:1028
juce::MidiMessage::isSostenutoPedalOff
bool isSostenutoPedalOff() const noexcept
Definition: juce_MidiMessage.cpp:498
juce::MidiMessage::getMidiChannelMetaEventChannel
int getMidiChannelMetaEventChannel() const noexcept
Definition: juce_MidiMessage.cpp:763
juce::MidiMessage::MidiMachineControlCommand
MidiMachineControlCommand
Definition: juce_MidiMessage.h:800
juce::MidiMessage::isTimeSignatureMetaEvent
bool isTimeSignatureMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:815
juce::MidiMessage::allNotesOff
static MidiMessage allNotesOff(int channel) noexcept
Definition: juce_MidiMessage.cpp:611
juce::MidiMessage::controllerEvent
static MidiMessage controllerEvent(int channel, int controllerType, int value) noexcept
Definition: juce_MidiMessage.cpp:566
juce::MidiMessage::isControllerOfType
bool isControllerOfType(int controllerType) const noexcept
Definition: juce_MidiMessage.cpp:548
juce::MidiMessage::isTempoMetaEvent
bool isTempoMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:760
juce::MidiMessage::floatValueToMidiByte
static uint8 floatValueToMidiByte(float valueBetween0and1) noexcept
Definition: juce_MidiMessage.cpp:40
juce::MidiMessage::keySignatureMetaEvent
static MidiMessage keySignatureMetaEvent(int numberOfSharpsOrFlats, bool isMinorKey)
Definition: juce_MidiMessage.cpp:870
juce::MidiMessage::midiClock
static MidiMessage midiClock() noexcept
Definition: juce_MidiMessage.cpp:903
juce::MidiMessage::isResetAllControllers
bool isResetAllControllers() const noexcept
Definition: juce_MidiMessage.cpp:633
juce::MidiMessage::fullFrame
static MidiMessage fullFrame(int hours, int minutes, int seconds, int frames, SmpteTimecodeType timecodeType)
Definition: juce_MidiMessage.cpp:938
juce::MidiMessage::isSoftPedalOff
bool isSoftPedalOff() const noexcept
Definition: juce_MidiMessage.cpp:501
juce::MidiMessage::getMetaEventLength
int getMetaEventLength() const noexcept
Definition: juce_MidiMessage.cpp:688
juce::MidiMessage::isMidiStop
bool isMidiStop() const noexcept
Definition: juce_MidiMessage.cpp:899
juce::MidiMessage::operator=
MidiMessage & operator=(const MidiMessage &other)
Definition: juce_MidiMessage.cpp:267
juce::MidiMessage::isActiveSense
bool isActiveSense() const noexcept
Definition: juce_MidiMessage.cpp:680
juce::MidiMessage::getTempoSecondsPerQuarterNote
double getTempoSecondsPerQuarterNote() const noexcept
Definition: juce_MidiMessage.cpp:769
juce::MidiMessage::masterVolume
static MidiMessage masterVolume(float volume)
Definition: juce_MidiMessage.cpp:644
juce::MidiMessage::getAfterTouchValue
int getAfterTouchValue() const noexcept
Definition: juce_MidiMessage.cpp:456
juce::MidiMessage::textMetaEvent
static MidiMessage textMetaEvent(int type, StringRef text)
Definition: juce_MidiMessage.cpp:728
juce::MidiMessage::MidiMessage
MidiMessage() noexcept
Definition: juce_MidiMessage.cpp:100
juce::MidiMessage::channelPressureChange
static MidiMessage channelPressureChange(int channel, int pressure) noexcept
Definition: juce_MidiMessage.cpp:486
juce::MidiMessage::isFullFrame
bool isFullFrame() const noexcept
Definition: juce_MidiMessage.cpp:914
juce::MidiMessage::getTempoMetaEventTickLength
double getTempoMetaEventTickLength(short timeFormat) const noexcept
Definition: juce_MidiMessage.cpp:782
juce::MidiMessage::getMessageLengthFromFirstByte
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
Definition: juce_MidiMessage.cpp:79
juce::MidiMessage::isEndOfTrackMetaEvent
bool isEndOfTrackMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:712
juce::MidiMessage::isNoteOnOrOff
bool isNoteOnOrOff() const noexcept
Definition: juce_MidiMessage.cpp:406
juce::MidiMessage::midiContinue
static MidiMessage midiContinue() noexcept
Definition: juce_MidiMessage.cpp:897
juce::MidiMessage::getControllerValue
int getControllerValue() const noexcept
Definition: juce_MidiMessage.cpp:560
juce::MidiMessage::getMidiNoteName
static String getMidiNoteName(int noteNumber, bool useSharps, bool includeOctaveNumber, int octaveNumForMiddleC)
Definition: juce_MidiMessage.cpp:999
juce::MidiMessage::midiMachineControlGoto
static MidiMessage midiMachineControlGoto(int hours, int minutes, int seconds, int frames)
Definition: juce_MidiMessage.cpp:993
juce::MidiMessage::isAllNotesOff
bool isAllNotesOff() const noexcept
Definition: juce_MidiMessage.cpp:616
juce::MidiMessage::noteOff
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Definition: juce_MidiMessage.cpp:598
juce::MidiMessage::isMidiMachineControlGoto
bool isMidiMachineControlGoto(int &hours, int &minutes, int &seconds, int &frames) const noexcept
Definition: juce_MidiMessage.cpp:970
juce::MidiMessage::isKeySignatureMajorKey
bool isKeySignatureMajorKey() const noexcept
Definition: juce_MidiMessage.cpp:865
juce::MidiMessage::isMidiChannelMetaEvent
bool isMidiChannelMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:761
juce::MidiMessage::getMidiMachineControlCommand
MidiMachineControlCommand getMidiMachineControlCommand() const noexcept
Definition: juce_MidiMessage.cpp:957
juce::MidiMessage::isMetaEvent
bool isMetaEvent() const noexcept
Definition: juce_MidiMessage.cpp:679
juce::MidiMessage::getVelocity
uint8 getVelocity() const noexcept
Definition: juce_MidiMessage.cpp:423
juce::MidiMessage::getRhythmInstrumentName
static const char * getRhythmInstrumentName(int midiNoteNumber)
Definition: juce_MidiMessage.cpp:1082
juce::MidiMessage::programChange
static MidiMessage programChange(int channel, int programNumber) noexcept
Definition: juce_MidiMessage.cpp:515
juce::MidiMessage::isChannelPressure
bool isChannelPressure() const noexcept
Definition: juce_MidiMessage.cpp:475
juce::MidiMessage::isSysEx
bool isSysEx() const noexcept
Definition: juce_MidiMessage.cpp:652
juce::MidiMessage::songPositionPointer
static MidiMessage songPositionPointer(int positionInMidiBeats) noexcept
Definition: juce_MidiMessage.cpp:886
juce::MidiMessage::endOfTrack
static MidiMessage endOfTrack() noexcept
Definition: juce_MidiMessage.cpp:877
juce::MidiMessage::isMidiClock
bool isMidiClock() const noexcept
Definition: juce_MidiMessage.cpp:902
juce::MidiMessage::getTextFromTextMetaEvent
String getTextFromTextMetaEvent() const
Definition: juce_MidiMessage.cpp:720
juce::MidiMessage::SmpteTimecodeType
SmpteTimecodeType
Definition: juce_MidiMessage.h:766
juce::MidiMessage::midiMachineControlCommand
static MidiMessage midiMachineControlCommand(MidiMachineControlCommand command)
Definition: juce_MidiMessage.cpp:964
juce::MidiMessage::allSoundOff
static MidiMessage allSoundOff(int channel) noexcept
Definition: juce_MidiMessage.cpp:622
juce::MidiMessage::setChannel
void setChannel(int newChannelNumber) noexcept
Definition: juce_MidiMessage.cpp:379
juce::MidiMessage::getControllerName
static const char * getControllerName(int controllerNumber)
Definition: juce_MidiMessage.cpp:1103
juce::MidiMessage::isSongPositionPointer
bool isSongPositionPointer() const noexcept
Definition: juce_MidiMessage.cpp:883
juce::MidiMessage::isSustainPedalOff
bool isSustainPedalOff() const noexcept
Definition: juce_MidiMessage.cpp:495
juce::MidiMessage::getRawDataSize
int getRawDataSize() const noexcept
Definition: juce_MidiMessage.h:138
juce::MidiMessage::allControllersOff
static MidiMessage allControllersOff(int channel) noexcept
Definition: juce_MidiMessage.cpp:639
juce::MidiMessage::withTimeStamp
MidiMessage withTimeStamp(double newTimestamp) const
Definition: juce_MidiMessage.cpp:354
juce::MidiMessage::getPitchWheelValue
int getPitchWheelValue() const noexcept
Definition: juce_MidiMessage.cpp:527
juce::StringRef
Definition: juce_StringRef.h:62
juce::StringRef::text
String::CharPointerType text
Definition: juce_StringRef.h:130
juce::String
Definition: juce_String.h:39
juce::String::isEmpty
bool isEmpty() const noexcept
Definition: juce_String.h:296
juce::String::toHexString
static String toHexString(IntegerType number)
Definition: juce_String.h:1053