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
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));
67 const auto limit =
jmin (maxBytesToUse, 4);
69 for (
int numBytesUsed = 0; numBytesUsed < limit; ++numBytesUsed)
71 const auto i = data[numBytesUsed];
72 v = (v << 7) + (i & 0x7f);
75 return { (
int) v, numBytesUsed + 1 };
85int MidiMessage::readVariableLengthVal (
const uint8* data,
int& numBytesUsed)
noexcept
94 if (++numBytesUsed > 6)
97 v = (v << 7) + (i & 0x7f);
107 jassert (firstByte >= 0x80 && firstByte != 0xf0 && firstByte != 0xf7);
109 static const char messageLengths[] =
111 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
112 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
113 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
114 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
115 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
116 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
117 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
118 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
121 return messageLengths[firstByte & 0x7f];
128 packedData.asBytes[0] = 0xf0;
129 packedData.asBytes[1] = 0xf7;
133 : timeStamp (t), size (dataSize)
139 memcpy (allocateSpace (dataSize), d, (
size_t) dataSize);
143 : timeStamp (t), size (1)
145 packedData.asBytes[0] = (
uint8) byte1;
148 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((
uint8) byte1) == 1);
152 : timeStamp (t), size (2)
154 packedData.asBytes[0] = (
uint8) byte1;
155 packedData.asBytes[1] = (
uint8) byte2;
158 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((
uint8) byte1) == 2);
162 : timeStamp (t), size (3)
164 packedData.asBytes[0] = (
uint8) byte1;
165 packedData.asBytes[1] = (
uint8) byte2;
166 packedData.asBytes[2] = (
uint8) byte3;
169 jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((
uint8) byte1) == 3);
173 : timeStamp (other.timeStamp), size (other.size)
175 if (isHeapAllocated())
176 memcpy (allocateSpace (size), other.getData(), (
size_t) size);
178 packedData.allocatedData = other.packedData.allocatedData;
182 : timeStamp (newTimeStamp), size (other.size)
184 if (isHeapAllocated())
185 memcpy (allocateSpace (size), other.getData(), (
size_t) size);
187 packedData.allocatedData = other.packedData.allocatedData;
191 double t,
bool sysexHasEmbeddedLength)
194 auto src =
static_cast<const uint8*
> (srcData);
195 auto byte = (
unsigned int) *src;
199 byte = (
unsigned int) lastStatusByte;
214 bool haveReadAllLengthBytes = ! sysexHasEmbeddedLength;
215 int numVariableLengthSysexBytes = 0;
227 if (haveReadAllLengthBytes)
230 ++numVariableLengthSysexBytes;
232 else if (! haveReadAllLengthBytes)
234 haveReadAllLengthBytes =
true;
235 ++numVariableLengthSysexBytes;
241 src += numVariableLengthSysexBytes;
242 size = 1 + (
int) (d - src);
244 auto dest = allocateSpace (size);
245 *dest = (
uint8)
byte;
246 memcpy (dest + 1, src, (
size_t) (size - 1));
248 numBytesUsed += (numVariableLengthSysexBytes + size);
250 else if (
byte == 0xff)
253 size =
jmin (sz + 1, bytesLeft.bytesUsed + 2 + bytesLeft.value);
255 auto dest = allocateSpace (size);
256 *dest = (
uint8)
byte;
257 memcpy (dest + 1, src, (
size_t) size - 1);
259 numBytesUsed += size;
264 packedData.asBytes[0] = (
uint8)
byte;
268 packedData.asBytes[1] = (sz > 0 ? src[0] : 0);
271 packedData.asBytes[2] = (sz > 1 ? src[1] : 0);
274 numBytesUsed +=
jmin (size, sz + 1);
279 packedData.allocatedData =
nullptr;
288 if (other.isHeapAllocated())
290 auto* newStorage =
static_cast<uint8*
> (isHeapAllocated()
291 ?
std::realloc (packedData.allocatedData, (
size_t) other.size)
294 if (newStorage ==
nullptr)
297 packedData.allocatedData = newStorage;
298 memcpy (packedData.allocatedData, other.packedData.allocatedData, (
size_t) other.size);
302 if (isHeapAllocated())
305 packedData.allocatedData = other.packedData.allocatedData;
308 timeStamp = other.timeStamp;
316 : timeStamp (other.timeStamp), size (other.size)
318 packedData.allocatedData = other.packedData.allocatedData;
324 packedData.allocatedData = other.packedData.allocatedData;
325 timeStamp = other.timeStamp;
333 if (isHeapAllocated())
337uint8* MidiMessage::allocateSpace (
int bytes)
339 if (bytes > (
int)
sizeof (packedData))
342 packedData.allocatedData = d;
346 return packedData.asBytes;
376 return { *
this, newTimestamp };
383 if ((data[0] & 0xf0) != 0xf0)
384 return (data[0] & 0xf) + 1;
391 jassert (channel > 0 && channel <= 16);
393 auto data = getRawData();
395 return ((data[0] & 0xf) == channel - 1)
396 && ((data[0] & 0xf0) != 0xf0);
401 jassert (channel > 0 && channel <= 16);
403 auto data = getData();
405 if ((data[0] & 0xf0) != (
uint8) 0xf0)
407 | (
uint8) (channel - 1));
412 auto data = getRawData();
414 return ((data[0] & 0xf0) == 0x90)
415 && (returnTrueForVelocity0 || data[2] != 0);
420 auto data = getRawData();
422 return ((data[0] & 0xf0) == 0x80)
423 || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90));
429 return (d == 0x90) || (d == 0x80);
439 if (isNoteOnOrOff() || isAftertouch())
440 getData()[1] = (
uint8) (newNoteNumber & 127);
459 getData()[2] = floatValueToMidiByte (newVelocity);
466 auto data = getData();
467 data[2] = MidiHelpers::validVelocity (
roundToInt (scaleFactor * data[2]));
484 const int aftertouchValue)
noexcept
486 jassert (channel > 0 && channel <= 16);
490 return MidiMessage (MidiHelpers::initialByte (0xa0, channel),
492 aftertouchValue & 0x7f);
508 jassert (channel > 0 && channel <= 16);
511 return MidiMessage (MidiHelpers::initialByte (0xd0, channel), pressure & 0x7f);
537 jassert (channel > 0 && channel <= 16);
539 return MidiMessage (MidiHelpers::initialByte (0xc0, channel), programNumber & 0x7f);
551 return data[1] | (data[2] << 7);
556 jassert (channel > 0 && channel <= 16);
559 return MidiMessage (MidiHelpers::initialByte (0xe0, channel),
560 position & 127, (position >> 7) & 127);
570 auto data = getRawData();
571 return (data[0] & 0xf0) == 0xb0 && data[1] == controllerType;
589 jassert (channel > 0 && channel <= 16);
591 return MidiMessage (MidiHelpers::initialByte (0xb0, channel),
592 controllerType & 127, value & 127);
597 jassert (channel > 0 && channel <= 16);
600 return MidiMessage (MidiHelpers::initialByte (0x90, channel),
601 noteNumber & 127, MidiHelpers::validVelocity (velocity));
606 return noteOn (channel, noteNumber, floatValueToMidiByte (velocity));
611 jassert (channel > 0 && channel <= 16);
614 return MidiMessage (MidiHelpers::initialByte (0x80, channel),
615 noteNumber & 127, MidiHelpers::validVelocity (velocity));
620 return noteOff (channel, noteNumber, floatValueToMidiByte (velocity));
625 jassert (channel > 0 && channel <= 16);
628 return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0);
633 return controllerEvent (channel, 123, 0);
639 return (data[0] & 0xf0) == 0xb0 && data[1] == 123;
644 return controllerEvent (channel, 120, 0);
650 return data[1] == 120 && (data[0] & 0xf0) == 0xb0;
656 return (data[0] & 0xf0) == 0xb0 && data[1] == 121;
661 return controllerEvent (channel, 121, 0);
668 return { 0xf0, 0x7f, 0x7f, 0x04, 0x01, vol & 0x7f, vol >> 7, 0xf7 };
682 memcpy (m + 1, sysexData, (
size_t) dataSize);
683 m[dataSize + 1] = 0xf7;
700 return isSysEx() ? size - 2 : 0;
710 return (size < 2 || *data != 0xff) ? -1 : data[1];
732 return d +
var.bytesUsed;
741 return t > 0 && t < 16;
754 jassert (type > 0 && type < 16);
761 size_t n =
sizeof (header);
763 header[--n] = (
uint8) (textSize & 0x7f);
765 for (
size_t i = textSize; (i >>= 7) != 0;)
766 header[--n] = (
uint8) ((i & 0x7f) | 0x80);
768 header[--n] = (
uint8) type;
771 const size_t headerLen =
sizeof (header) - n;
772 const int totalSize = (
int) (headerLen + textSize);
774 auto dest = result.allocateSpace (totalSize);
775 result.size = totalSize;
777 memcpy (dest, header + n, headerLen);
800 return (((
unsigned int) d[0] << 16)
801 | ((
unsigned int) d[1] << 8)
810 if (! isTempoMetaEvent())
811 return 0.5 / timeFormat;
813 return getTempoSecondsPerQuarterNote() / timeFormat;
816 const int frameCode = (-timeFormat) >> 8;
817 double framesPerSecond;
821 case 24: framesPerSecond = 24.0;
break;
822 case 25: framesPerSecond = 25.0;
break;
823 case 29: framesPerSecond = 30.0 * 1000.0 / 1001.0;
break;
824 case 30: framesPerSecond = 30.0;
break;
825 default: framesPerSecond = 30.0;
break;
828 return (1.0 / framesPerSecond) / (timeFormat & 0xff);
833 return { 0xff, 81, 3,
834 (
uint8) (microsecondsPerQuarterNote >> 16),
835 (
uint8) (microsecondsPerQuarterNote >> 8),
836 (
uint8) microsecondsPerQuarterNote };
842 return (data[1] == 0x58) && (*data == (
uint8) 0xff);
847 if (isTimeSignatureMetaEvent())
849 auto d = getMetaEventData();
851 denominator = 1 << d[1];
865 while (n < denominator)
871 return { 0xff, 0x58, 0x04, numerator, powerOfTwo, 1, 96 };
876 return { 0xff, 0x20, 0x01,
jlimit (0, 0xff, channel - 1) };
896 jassert (numberOfSharpsOrFlats >= -7 && numberOfSharpsOrFlats <= 7);
898 return { 0xff, 0x59, 0x02, numberOfSharpsOrFlats, isMinorKey ? 1 : 0 };
903 return { 0xff, 0x2f, 0x00 };
913 positionInMidiBeats & 127,
914 (positionInMidiBeats >> 7) & 127 };
935 return MidiMessage (0xf1, (sequenceNumber << 4) | value);
942 return data[0] == 0xf0
954 auto data = getRawData();
956 hours = data[5] & 0x1f;
965 return { 0xf0, 0x7f, 0x7f, 0x01, 0x01,
966 (hours & 0x01f) | (timecodeType << 5),
967 minutes, seconds, frames,
975 return data[0] == 0xf0
990 return { 0xf0, 0x7f, 0, 6, command, 0xf7 };
996 auto data = getRawData();
1006 hours = data[7] % 24;
1019 return { 0xf0, 0x7f, 0, 6, 0x44, 6, 1, hours, minutes, seconds, frames, 0xf7 };
1025 static const char*
const sharpNoteNames[] = {
"C",
"C#",
"D",
"D#",
"E",
"F",
"F#",
"G",
"G#",
"A",
"A#",
"B" };
1026 static const char*
const flatNoteNames[] = {
"C",
"Db",
"D",
"Eb",
"E",
"F",
"Gb",
"G",
"Ab",
"A",
"Bb",
"B" };
1030 String s (useSharps ? sharpNoteNames[note % 12]
1031 : flatNoteNames [note % 12]);
1033 if (includeOctaveNumber)
1034 s << (note / 12 + (octaveNumForMiddleC - 5));
1044 return frequencyOfA *
std::pow (2.0, (noteNumber - 69) / 12.0);
1049 return ((1 << (noteNumber % 12)) & 0x054a) != 0;
1054 static const char* names[] =
1095 static const char* names[] =
1108 static const char* names[] =
1124 return (n >= 35 && n <= 81) ? names[n - 35] :
nullptr;
1129 static const char* names[] =
1141 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
1147 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
1148 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
1155 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
1159 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
1160 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
1172struct MidiMessageTest final :
public UnitTest
1175 :
UnitTest (
"MidiMessage", UnitTestCategories::midi)
1178 void runTest()
override
1183 beginTest (
"ReadVariableLengthValue should return valid, backward-compatible results");
1193 { 0x81, 0x80, 0x00 },
1194 { 0xc0, 0x80, 0x00 },
1195 { 0xff, 0xff, 0x7f },
1196 { 0x81, 0x80, 0x80, 0x00 },
1197 { 0xc0, 0x80, 0x80, 0x00 },
1198 { 0xff, 0xff, 0xff, 0x7f }
1222 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
1223 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
1225 for (const auto& input : inputs)
1229 while (
copy.size() < 16)
1232 const auto result = MidiMessage::readVariableLengthValue (
copy.data(),
1235 expect (result.isValid());
1236 expectEquals (result.value, outputs[index]);
1237 expectEquals (result.bytesUsed, (
int) inputs[index].size());
1239 int legacyNumUsed = 0;
1240 const auto legacyResult = MidiMessage::readVariableLengthVal (
copy.data(),
1243 expectEquals (result.value, legacyResult);
1244 expectEquals (result.bytesUsed, legacyNumUsed);
1249 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
1250 JUCE_END_IGNORE_WARNINGS_MSVC
1253 beginTest (
"ReadVariableLengthVal should return 0 if input is truncated");
1255 for (
size_t i = 0; i != 16; ++i)
1260 const auto result = MidiMessage::readVariableLengthValue (input.
data(),
1261 (
int) input.
size());
1263 expect (! result.isValid());
1264 expectEquals (result.value, 0);
1265 expectEquals (result.bytesUsed, 0);
1273 { 0xff, 0x00, 0x02, 0x00, 0x00 },
1274 { 0xff, 0x01, 0x00 },
1275 { 0xff, 0x02, 0x00 },
1276 { 0xff, 0x03, 0x00 },
1277 { 0xff, 0x04, 0x00 },
1278 { 0xff, 0x05, 0x00 },
1279 { 0xff, 0x06, 0x00 },
1280 { 0xff, 0x07, 0x00 },
1281 { 0xff, 0x20, 0x01, 0x00 },
1282 { 0xff, 0x2f, 0x00 },
1283 { 0xff, 0x51, 0x03, 0x01, 0x02, 0x03 },
1284 { 0xff, 0x54, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05 },
1285 { 0xff, 0x58, 0x04, 0x01, 0x02, 0x03, 0x04 },
1286 { 0xff, 0x59, 0x02, 0x01, 0x02 },
1287 { 0xff, 0x7f, 0x00 },
1290 beginTest (
"MidiMessage data constructor works for well-formed meta-events");
1292 const auto status = (uint8) 0x90;
1294 for (
const auto& input : metaEvents)
1297 const MidiMessage msg (input.data(), (
int) input.size(), bytesUsed, status);
1299 expect (msg.isMetaEvent());
1300 expectEquals (msg.getMetaEventLength(), (
int) input.size() - 3);
1301 expectEquals (msg.getMetaEventType(), (
int) input[1]);
1305 beginTest (
"MidiMessage data constructor works for malformed meta-events");
1307 const auto status = (uint8) 0x90;
1312 const MidiMessage msg (input.data(), (
int) input.size(), bytesUsed, status);
1314 expect (msg.isMetaEvent());
1315 expectEquals (msg.getMetaEventLength(),
jmax (0, (
int) input.size() - 3));
1316 expectEquals (msg.getMetaEventType(), input.size() >= 2 ? input[1] : -1);
1321 for (
const auto& input : metaEvents)
1332static MidiMessageTest midiMessageTests;
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.
Very simple container class to hold a pointer to some data on the heap.
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.
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 empty sysex 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.
static VariableLengthValue readVariableLengthValue(const uint8 *data, int maxBytesToUse) noexcept
Reads a midi variable-length integer, with protection against buffer overflow.
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 non-owning view over contiguous objects stored in an Array or vector or other similar container.
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.
This is a base class for classes that perform a unit test.
A variant class, that can be used to hold a range of primitive values.
#define NEEDS_TRANS(stringLiteral)
A dummy version of the TRANS macro, used to indicate a string literal that should be added to the tra...
@ copy
The command ID that should be used to send a "Copy to clipboard" command.
unsigned short uint16
A platform-independent 16-bit unsigned integer type.
constexpr Type jmap(Type value0To1, Type targetRangeMin, Type targetRangeMax)
Remaps a normalised value (between 0 and 1) to a target range.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
signed char int8
A platform-independent 8-bit signed integer type.
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
unsigned char uint8
A platform-independent 8-bit unsigned integer type.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
constexpr int numElementsInArray(Type(&)[N]) noexcept
Handy function for getting the number of elements in a simple const C array.
Holds information about a variable-length value which was parsed from a stream of bytes.