28 inline uint8 initialByte (
const int type,
const int channel)
noexcept
30 return (uint8) (type | jlimit (0, 15, channel - 1));
33 inline uint8 validVelocity (
const int v)
noexcept
35 return (uint8) jlimit (0, 127, v);
42 jassert (v >= 0 && v <= 1.0f);
45 return MidiHelpers::validVelocity (roundToInt (v * 127.0f));
49 const float pitchbendRange)
noexcept
52 jassert (std::abs (pitchbend) <= pitchbendRange);
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));
69 if (++numBytesUsed > 6)
72 v = (v << 7) + (i & 0x7f);
82 jassert (firstByte >= 0x80 && firstByte != 0xf0 && firstByte != 0xf7);
84 static const char messageLengths[] =
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
96 return messageLengths[firstByte & 0x7f];
103 packedData.asBytes[0] = 0xf0;
104 packedData.asBytes[1] = 0xf7;
108 : timeStamp (t), size (dataSize)
110 jassert (dataSize > 0);
114 memcpy (allocateSpace (dataSize), d, (
size_t) dataSize);
118 : timeStamp (t), size (1)
120 packedData.asBytes[0] = (uint8) byte1;
123 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 1);
127 : timeStamp (t), size (2)
129 packedData.asBytes[0] = (uint8) byte1;
130 packedData.asBytes[1] = (uint8) byte2;
133 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 2);
137 : timeStamp (t), size (3)
139 packedData.asBytes[0] = (uint8) byte1;
140 packedData.asBytes[1] = (uint8) byte2;
141 packedData.asBytes[2] = (uint8) byte3;
144 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 3);
148 : timeStamp (other.timeStamp), size (other.size)
150 if (isHeapAllocated())
151 memcpy (allocateSpace (size), other.getData(), (
size_t) size);
153 packedData.allocatedData = other.packedData.allocatedData;
157 : timeStamp (newTimeStamp), size (other.size)
159 if (isHeapAllocated())
160 memcpy (allocateSpace (size), other.getData(), (
size_t) size);
162 packedData.allocatedData = other.packedData.allocatedData;
166 double t,
bool sysexHasEmbeddedLength)
169 auto src =
static_cast<const uint8*
> (srcData);
170 auto byte = (
unsigned int) *src;
174 byte = (
unsigned int) lastStatusByte;
189 bool haveReadAllLengthBytes = ! sysexHasEmbeddedLength;
190 int numVariableLengthSysexBytes = 0;
202 if (haveReadAllLengthBytes)
205 ++numVariableLengthSysexBytes;
207 else if (! haveReadAllLengthBytes)
209 haveReadAllLengthBytes =
true;
210 ++numVariableLengthSysexBytes;
216 src += numVariableLengthSysexBytes;
217 size = 1 + (int) (d - src);
219 auto dest = allocateSpace (size);
220 *dest = (uint8)
byte;
221 memcpy (dest + 1, src, (
size_t) (size - 1));
223 numBytesUsed += (numVariableLengthSysexBytes + size);
225 else if (
byte == 0xff)
235 size = jmin (sz + 1, n + 2 + bytesLeft);
238 auto dest = allocateSpace (size);
239 *dest = (uint8)
byte;
240 memcpy (dest + 1, src, (
size_t) size - 1);
242 numBytesUsed += size;
247 packedData.asBytes[0] = (uint8)
byte;
251 packedData.asBytes[1] = (sz > 0 ? src[0] : 0);
254 packedData.asBytes[2] = (sz > 1 ? src[1] : 0);
257 numBytesUsed += jmin (size, sz + 1);
262 packedData.allocatedData =
nullptr;
271 if (other.isHeapAllocated())
273 if (isHeapAllocated())
274 packedData.allocatedData =
static_cast<uint8*
> (std::realloc (packedData.allocatedData, (
size_t) other.size));
276 packedData.allocatedData =
static_cast<uint8*
> (std::malloc ((
size_t) other.size));
278 memcpy (packedData.allocatedData, other.packedData.allocatedData, (
size_t) other.size);
282 if (isHeapAllocated())
283 std::free (packedData.allocatedData);
285 packedData.allocatedData = other.packedData.allocatedData;
288 timeStamp = other.timeStamp;
296 : timeStamp (other.timeStamp), size (other.size)
298 packedData.allocatedData = other.packedData.allocatedData;
304 packedData.allocatedData = other.packedData.allocatedData;
305 timeStamp = other.timeStamp;
313 if (isHeapAllocated())
314 std::free (packedData.allocatedData);
317uint8* MidiMessage::allocateSpace (
int bytes)
319 if (bytes > (
int)
sizeof (packedData))
321 auto d =
static_cast<uint8*
> (std::malloc ((
size_t) bytes));
322 packedData.allocatedData = d;
326 return packedData.asBytes;
356 return { *
this, newTimestamp };
363 if ((data[0] & 0xf0) != 0xf0)
364 return (data[0] & 0xf) + 1;
371 jassert (channel > 0 && channel <= 16);
373 auto data = getRawData();
375 return ((data[0] & 0xf) == channel - 1)
376 && ((data[0] & 0xf0) != 0xf0);
381 jassert (channel > 0 && channel <= 16);
383 auto data = getData();
385 if ((data[0] & 0xf0) != (uint8) 0xf0)
386 data[0] = (uint8) ((data[0] & (uint8) 0xf0)
387 | (uint8)(channel - 1));
392 auto data = getRawData();
394 return ((data[0] & 0xf0) == 0x90)
395 && (returnTrueForVelocity0 || data[2] != 0);
400 auto data = getRawData();
402 return ((data[0] & 0xf0) == 0x80)
403 || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90));
409 return (d == 0x90) || (d == 0x80);
419 if (isNoteOnOrOff() || isAftertouch())
420 getData()[1] = (uint8) (newNoteNumber & 127);
439 getData()[2] = floatValueToMidiByte (newVelocity);
446 auto data = getData();
447 data[2] = MidiHelpers::validVelocity (roundToInt (scaleFactor * data[2]));
464 const int aftertouchValue)
noexcept
466 jassert (channel > 0 && channel <= 16);
467 jassert (isPositiveAndBelow (noteNum, 128));
468 jassert (isPositiveAndBelow (aftertouchValue, 128));
470 return MidiMessage (MidiHelpers::initialByte (0xa0, channel),
472 aftertouchValue & 0x7f);
488 jassert (channel > 0 && channel <= 16);
489 jassert (isPositiveAndBelow (pressure, 128));
491 return MidiMessage (MidiHelpers::initialByte (0xd0, channel), pressure & 0x7f);
517 jassert (channel > 0 && channel <= 16);
519 return MidiMessage (MidiHelpers::initialByte (0xc0, channel), programNumber & 0x7f);
531 return data[1] | (data[2] << 7);
536 jassert (channel > 0 && channel <= 16);
537 jassert (isPositiveAndBelow (position, 0x4000));
539 return MidiMessage (MidiHelpers::initialByte (0xe0, channel),
540 position & 127, (position >> 7) & 127);
550 auto data = getRawData();
551 return (data[0] & 0xf0) == 0xb0 && data[1] == controllerType;
569 jassert (channel > 0 && channel <= 16);
571 return MidiMessage (MidiHelpers::initialByte (0xb0, channel),
572 controllerType & 127, value & 127);
577 jassert (channel > 0 && channel <= 16);
578 jassert (isPositiveAndBelow (noteNumber, 128));
580 return MidiMessage (MidiHelpers::initialByte (0x90, channel),
581 noteNumber & 127, MidiHelpers::validVelocity (velocity));
586 return noteOn (channel, noteNumber, floatValueToMidiByte (velocity));
591 jassert (channel > 0 && channel <= 16);
592 jassert (isPositiveAndBelow (noteNumber, 128));
594 return MidiMessage (MidiHelpers::initialByte (0x80, channel),
595 noteNumber & 127, MidiHelpers::validVelocity (velocity));
600 return noteOff (channel, noteNumber, floatValueToMidiByte (velocity));
605 jassert (channel > 0 && channel <= 16);
606 jassert (isPositiveAndBelow (noteNumber, 128));
608 return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0);
613 return controllerEvent (channel, 123, 0);
619 return (data[0] & 0xf0) == 0xb0 && data[1] == 123;
624 return controllerEvent (channel, 120, 0);
630 return data[1] == 120 && (data[0] & 0xf0) == 0xb0;
636 return (data[0] & 0xf0) == 0xb0 && data[1] == 121;
641 return controllerEvent (channel, 121, 0);
646 auto vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000));
648 return { 0xf0, 0x7f, 0x7f, 0x04, 0x01, vol & 0x7f, vol >> 7, 0xf7 };
662 memcpy (m + 1, sysexData, (
size_t) dataSize);
663 m[dataSize + 1] = 0xf7;
675 return isSysEx() ? size - 2 : 0;
685 return *data != 0xff ? -1 : data[1];
717 return t > 0 && t < 16;
730 jassert (type > 0 && type < 16);
737 size_t n =
sizeof (header);
739 header[--n] = (uint8) (textSize & 0x7f);
741 for (
size_t i = textSize; (i >>= 7) != 0;)
742 header[--n] = (uint8) ((i & 0x7f) | 0x80);
744 header[--n] = (uint8) type;
747 const size_t headerLen =
sizeof (header) - n;
748 const int totalSize = (int) (headerLen + textSize);
750 auto dest = result.allocateSpace (totalSize);
751 result.size = totalSize;
753 memcpy (dest, header + n, headerLen);
776 return (((
unsigned int) d[0] << 16)
777 | ((
unsigned int) d[1] << 8)
786 if (! isTempoMetaEvent())
787 return 0.5 / timeFormat;
789 return getTempoSecondsPerQuarterNote() / timeFormat;
792 const int frameCode = (-timeFormat) >> 8;
793 double framesPerSecond;
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;
804 return (1.0 / framesPerSecond) / (timeFormat & 0xff);
809 return { 0xff, 81, 3,
810 (uint8) (microsecondsPerQuarterNote >> 16),
811 (uint8) (microsecondsPerQuarterNote >> 8),
812 (uint8) microsecondsPerQuarterNote };
818 return (data[1] == 0x58) && (*data == (uint8) 0xff);
823 if (isTimeSignatureMetaEvent())
825 auto d = getMetaEventData();
827 denominator = 1 << d[1];
841 while (n < denominator)
847 return { 0xff, 0x58, 0x04, numerator, powerOfTwo, 1, 96 };
852 return { 0xff, 0x20, 0x01, jlimit (0, 0xff, channel - 1) };
872 jassert (numberOfSharpsOrFlats >= -7 && numberOfSharpsOrFlats <= 7);
874 return { 0xff, 0x59, 0x02, numberOfSharpsOrFlats, isMinorKey ? 1 : 0 };
879 return { 0xff, 0x2f, 0x00 };
889 positionInMidiBeats & 127,
890 (positionInMidiBeats >> 7) & 127 };
911 return MidiMessage (0xf1, (sequenceNumber << 4) | value);
918 return data[0] == 0xf0
928 jassert (isFullFrame());
930 auto data = getRawData();
932 hours = data[5] & 0x1f;
941 return { 0xf0, 0x7f, 0x7f, 0x01, 0x01,
942 (hours & 0x01f) | (timecodeType << 5),
943 minutes, seconds, frames,
951 return data[0] == 0xf0
966 return { 0xf0, 0x7f, 0, 6, command, 0xf7 };
972 auto data = getRawData();
982 hours = data[7] % 24;
995 return { 0xf0, 0x7f, 0, 6, 0x44, 6, 1, hours, minutes, seconds, frames, 0xf7 };
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" };
1004 if (isPositiveAndBelow (note, 128))
1006 String s (useSharps ? sharpNoteNames[note % 12]
1007 : flatNoteNames [note % 12]);
1009 if (includeOctaveNumber)
1010 s << (note / 12 + (octaveNumForMiddleC - 5));
1020 return frequencyOfA * std::pow (2.0, (noteNumber - 69) / 12.0);
1025 return ((1 << (noteNumber % 12)) & 0x054a) != 0;
1030 static const char* names[] =
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")
1066 return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] :
nullptr;
1071 static const char* names[] =
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")
1079 return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] :
nullptr;
1084 static const char* names[] =
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")
1100 return (n >= 35 && n <= 81) ? names[n - 35] :
nullptr;
1105 static const char* names[] =
1107 NEEDS_TRANS(
"Bank Select"), NEEDS_TRANS(
"Modulation Wheel (coarse)"), NEEDS_TRANS(
"Breath controller (coarse)"),
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)"),
1112 NEEDS_TRANS(
"Pan position (coarse)"), NEEDS_TRANS(
"Expression (coarse)"), NEEDS_TRANS(
"Effect Control 1 (coarse)"),
1113 NEEDS_TRANS(
"Effect Control 2 (coarse)"),
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)"),
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")
1141 return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] :
nullptr;
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
size_t sizeInBytes() const noexcept
Returns the number of bytes that are used to represent this string.
CharType * getAddress() const noexcept
Returns the address that this pointer is pointing to.
Encapsulates a MIDI message.
bool isTrackMetaEvent() const noexcept
Returns true if this is a 'track' meta-event.
static MidiMessage createSysExMessage(const void *sysexData, int dataSize)
Creates a system-exclusive message.
static MidiMessage tempoMetaEvent(int microsecondsPerQuarterNote) noexcept
Creates a tempo meta-event.
static MidiMessage midiStart() noexcept
Creates a midi start event.
~MidiMessage() noexcept
Destructor.
const uint8 * getSysExData() const noexcept
Returns a pointer to the sysex data inside the message.
String getDescription() const
Returns a human-readable description of the midi message as a string, for example "Note On C#3 Veloci...
static const char * getGMInstrumentBankName(int midiBankNumber)
Returns the name of a bank of GM instruments, or nullptr if unknown for this bank number.
bool isAftertouch() const noexcept
Returns true if the message is an aftertouch event.
void setNoteNumber(int newNoteNumber) noexcept
Changes the midi note number of a note-on or note-off message.
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Returns true if this message is a 'key-down' event.
int getKeySignatureNumberOfSharpsOrFlats() const noexcept
Returns the key from a key-signature meta-event.
int getSongPositionPointerMidiBeat() const noexcept
Returns the midi beat-number of a song-position-pointer message.
void multiplyVelocity(float scaleFactor) noexcept
Multiplies the velocity of a note-on or note-off message by a given amount.
void getFullFrameParameters(int &hours, int &minutes, int &seconds, int &frames, SmpteTimecodeType &timecodeType) const noexcept
Extracts the timecode information from a full-frame midi timecode message.
float getFloatVelocity() const noexcept
Returns the velocity of a note-on or note-off message.
bool isMidiMachineControlMessage() const noexcept
Checks whether this is an MMC message.
int getChannel() const noexcept
Returns the midi channel associated with the message.
static bool isMidiNoteBlack(int noteNumber) noexcept
Returns true if the given midi note number is a black key.
static MidiMessage aftertouchChange(int channel, int noteNumber, int aftertouchAmount) noexcept
Creates an aftertouch message.
static int readVariableLengthVal(const uint8 *data, int &numBytesUsed) noexcept
Reads a midi variable-length integer.
int getQuarterFrameSequenceNumber() const noexcept
Returns the sequence number of a quarter-frame midi timecode message.
int getSysExDataSize() const noexcept
Returns the size of the sysex data.
bool isQuarterFrame() const noexcept
Returns true if this is a quarter-frame midi timecode message.
const uint8 * getRawData() const noexcept
Returns a pointer to the raw midi data.
bool isTextMetaEvent() const noexcept
Returns true if this is a 'text' meta-event.
void setVelocity(float newVelocity) noexcept
Changes the velocity of a note-on or note-off message.
int getMetaEventType() const noexcept
Returns a meta-event's type number.
bool isProgramChange() const noexcept
Returns true if the message is a program (patch) change message.
bool isController() const noexcept
Returns true if this is a midi controller message.
void getTimeSignatureInfo(int &numerator, int &denominator) const noexcept
Returns the time-signature values from a time-signature meta-event.
bool isAllSoundOff() const noexcept
Checks whether this message is an all-sound-off message.
bool isSoftPedalOn() const noexcept
Returns true if this message is a 'soft pedal down' controller message.
int getControllerNumber() const noexcept
Returns the controller number of a controller message.
bool isMidiStart() const noexcept
Returns true if this is a midi start event.
static double getMidiNoteInHertz(int noteNumber, double frequencyOfA=440.0) noexcept
Returns the frequency of a midi note number.
int getQuarterFrameValue() const noexcept
Returns the value from a quarter-frame message.
bool isTrackNameEvent() const noexcept
Returns true if this is an 'track name' meta-event.
int getChannelPressureValue() const noexcept
Returns the pressure from a channel pressure change message.
static MidiMessage pitchWheel(int channel, int position) noexcept
Creates a pitch-wheel move message.
bool isForChannel(int channelNumber) const noexcept
Returns true if the message applies to the given midi channel.
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Returns true if this message is a 'key-up' event.
const uint8 * getMetaEventData() const noexcept
Returns a pointer to the data in a meta-event.
bool isKeySignatureMetaEvent() const noexcept
Returns true if this is a 'key-signature' meta-event.
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Creates a key-down message (using a floating-point velocity).
static MidiMessage quarterFrame(int sequenceNumber, int value) noexcept
Creates a quarter-frame MTC message.
bool isPitchWheel() const noexcept
Returns true if the message is a pitch-wheel move.
bool isSustainPedalOn() const noexcept
Returns true if this message is a 'sustain pedal down' controller message.
bool isMidiContinue() const noexcept
Returns true if this is a midi continue event.
static MidiMessage midiStop() noexcept
Creates a midi stop event.
static MidiMessage timeSignatureMetaEvent(int numerator, int denominator)
Creates a time-signature meta-event.
bool isSostenutoPedalOn() const noexcept
Returns true if this message is a 'sostenuto pedal down' controller message.
static uint16 pitchbendToPitchwheelPos(float pitchbendInSemitones, float pitchbendRangeInSemitones) noexcept
Converts a pitchbend value in semitones to a MIDI 14-bit pitchwheel position value.
int getNoteNumber() const noexcept
Returns the midi note number for note-on and note-off messages.
static MidiMessage midiChannelMetaEvent(int channel) noexcept
Creates a midi channel meta-event.
int getProgramChangeNumber() const noexcept
Returns the new program number of a program change message.
static const char * getGMInstrumentName(int midiInstrumentNumber)
Returns the standard name of a GM instrument, or nullptr if unknown for this index.
bool isSostenutoPedalOff() const noexcept
Returns true if this message is a 'sostenuto pedal up' controller message.
int getMidiChannelMetaEventChannel() const noexcept
Returns the channel number from a channel meta-event.
MidiMachineControlCommand
Types of MMC command.
bool isTimeSignatureMetaEvent() const noexcept
Returns true if this is a 'time-signature' meta-event.
static MidiMessage allNotesOff(int channel) noexcept
Creates an all-notes-off message.
static MidiMessage controllerEvent(int channel, int controllerType, int value) noexcept
Creates a controller message.
bool isControllerOfType(int controllerType) const noexcept
Returns true if this message is a controller message and if it has the specified controller type.
bool isTempoMetaEvent() const noexcept
Returns true if this is a 'tempo' meta-event.
static uint8 floatValueToMidiByte(float valueBetween0and1) noexcept
Converts a floating-point value between 0 and 1 to a MIDI 7-bit value between 0 and 127.
static MidiMessage keySignatureMetaEvent(int numberOfSharpsOrFlats, bool isMinorKey)
Creates a key-signature meta-event.
static MidiMessage midiClock() noexcept
Creates a midi clock event.
bool isResetAllControllers() const noexcept
Checks whether this message is a reset all controllers message.
static MidiMessage fullFrame(int hours, int minutes, int seconds, int frames, SmpteTimecodeType timecodeType)
Creates a full-frame MTC message.
bool isSoftPedalOff() const noexcept
Returns true if this message is a 'soft pedal up' controller message.
int getMetaEventLength() const noexcept
Returns the length of the data for a meta-event.
bool isMidiStop() const noexcept
Returns true if this is a midi stop event.
MidiMessage & operator=(const MidiMessage &other)
Copies this message from another one.
bool isActiveSense() const noexcept
Returns true if this is an active-sense message.
double getTempoSecondsPerQuarterNote() const noexcept
Calculates the seconds-per-quarter-note from a tempo meta-event.
static MidiMessage masterVolume(float volume)
Creates a master-volume change message.
int getAfterTouchValue() const noexcept
Returns the amount of aftertouch from an aftertouch messages.
static MidiMessage textMetaEvent(int type, StringRef text)
Creates a text meta-event.
MidiMessage() noexcept
Creates an active-sense message.
static MidiMessage channelPressureChange(int channel, int pressure) noexcept
Creates a channel-pressure change event.
bool isFullFrame() const noexcept
Returns true if this is a full-frame midi timecode message.
double getTempoMetaEventTickLength(short timeFormat) const noexcept
Returns the tick length from a tempo meta-event.
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
Based on the first byte of a short midi message, this uses a lookup table to return the message lengt...
bool isEndOfTrackMetaEvent() const noexcept
Returns true if this is an 'end-of-track' meta-event.
bool isNoteOnOrOff() const noexcept
Returns true if this message is a 'key-down' or 'key-up' event.
static MidiMessage midiContinue() noexcept
Creates a midi continue event.
int getControllerValue() const noexcept
Returns the controller value from a controller message.
static String getMidiNoteName(int noteNumber, bool useSharps, bool includeOctaveNumber, int octaveNumForMiddleC)
Returns the name of a midi note number.
static MidiMessage midiMachineControlGoto(int hours, int minutes, int seconds, int frames)
Creates an MMC "goto" message.
bool isAllNotesOff() const noexcept
Checks whether this message is an all-notes-off message.
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Creates a key-up message.
bool isMidiMachineControlGoto(int &hours, int &minutes, int &seconds, int &frames) const noexcept
Checks whether this is an MMC "goto" message.
bool isKeySignatureMajorKey() const noexcept
Returns true if this key-signature event is major, or false if it's minor.
bool isMidiChannelMetaEvent() const noexcept
Returns true if this is a 'channel' meta-event.
MidiMachineControlCommand getMidiMachineControlCommand() const noexcept
For an MMC message, this returns its type.
bool isMetaEvent() const noexcept
Returns true if this event is a meta-event.
uint8 getVelocity() const noexcept
Returns the velocity of a note-on or note-off message.
static const char * getRhythmInstrumentName(int midiNoteNumber)
Returns the standard name of a channel 10 percussion sound, or nullptr if unknown for this note numbe...
static MidiMessage programChange(int channel, int programNumber) noexcept
Creates a program-change message.
bool isChannelPressure() const noexcept
Returns true if the message is a channel-pressure change event.
bool isSysEx() const noexcept
Returns true if this is a system-exclusive message.
static MidiMessage songPositionPointer(int positionInMidiBeats) noexcept
Creates a song-position-pointer message.
static MidiMessage endOfTrack() noexcept
Creates an end-of-track meta-event.
bool isMidiClock() const noexcept
Returns true if this is a midi clock event.
String getTextFromTextMetaEvent() const
Returns the text from a text meta-event.
SmpteTimecodeType
SMPTE timecode types.
static MidiMessage midiMachineControlCommand(MidiMachineControlCommand command)
Creates an MMC message.
static MidiMessage allSoundOff(int channel) noexcept
Creates an all-sound-off message.
void setChannel(int newChannelNumber) noexcept
Changes the message's midi channel.
static const char * getControllerName(int controllerNumber)
Returns the name of a controller type number, or nullptr if unknown for this controller number.
bool isSongPositionPointer() const noexcept
Returns true if this is a song-position-pointer message.
bool isSustainPedalOff() const noexcept
Returns true if this message is a 'sustain pedal up' controller message.
int getRawDataSize() const noexcept
Returns the number of bytes of data in the message.
static MidiMessage allControllersOff(int channel) noexcept
Creates an all-controllers-off message.
MidiMessage withTimeStamp(double newTimestamp) const
Return a copy of this message with a new timestamp.
int getPitchWheelValue() const noexcept
Returns the pitch wheel position from a pitch-wheel move message.
A simple class for holding temporary references to a string literal or String.
String::CharPointerType text
The text that is referenced.
bool isEmpty() const noexcept
Returns true if the string contains no characters.
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.