diff --git a/modules/juce_audio_basics/midi/juce_MidiMessage.cpp b/modules/juce_audio_basics/midi/juce_MidiMessage.cpp index e406bc985e..1cffde6e11 100644 --- a/modules/juce_audio_basics/midi/juce_MidiMessage.cpp +++ b/modules/juce_audio_basics/midi/juce_MidiMessage.cpp @@ -103,7 +103,7 @@ int MidiMessage::getMessageLengthFromFirstByte (const uint8 firstByte) noexcept //============================================================================== MidiMessage::MidiMessage() noexcept - : timeStamp (0), size (2) + : size (2) { packedData.asBytes[0] = 0xf0; packedData.asBytes[1] = 0xf7; @@ -171,12 +171,12 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const double t, bool sysexHasEmbeddedLength) : timeStamp (t) { - const uint8* src = static_cast (srcData); - unsigned int byte = (unsigned int) *src; + auto src = static_cast (srcData); + auto byte = (unsigned int) *src; if (byte < 0x80) { - byte = (unsigned int) (uint8) lastStatusByte; + byte = (unsigned int) lastStatusByte; numBytesUsed = -1; } else @@ -190,7 +190,7 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const { if (byte == 0xf0) { - const uint8* d = src; + auto d = src; bool haveReadAllLengthBytes = ! sysexHasEmbeddedLength; int numVariableLengthSysexBytes = 0; @@ -221,7 +221,7 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const src += numVariableLengthSysexBytes; size = 1 + (int) (d - src); - uint8* dest = allocateSpace (size); + auto dest = allocateSpace (size); *dest = (uint8) byte; memcpy (dest + 1, src, (size_t) (size - 1)); @@ -233,7 +233,7 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const const int bytesLeft = readVariableLengthVal (src + 1, n); size = jmin (sz + 1, n + 2 + bytesLeft); - uint8* dest = allocateSpace (size); + auto dest = allocateSpace (size); *dest = (uint8) byte; memcpy (dest + 1, src, (size_t) size - 1); @@ -316,7 +316,7 @@ uint8* MidiMessage::allocateSpace (int bytes) { if (bytes > (int) sizeof (packedData)) { - uint8* d = static_cast (std::malloc ((size_t) bytes)); + auto d = static_cast (std::malloc ((size_t) bytes)); packedData.allocatedData = d; return d; } @@ -351,7 +351,7 @@ String MidiMessage::getDescription() const int MidiMessage::getChannel() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); if ((data[0] & 0xf0) != 0xf0) return (data[0] & 0xf) + 1; @@ -363,7 +363,7 @@ bool MidiMessage::isForChannel (const int channel) const noexcept { jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - const uint8* const data = getRawData(); + auto data = getRawData(); return ((data[0] & 0xf) == channel - 1) && ((data[0] & 0xf0) != 0xf0); @@ -373,7 +373,7 @@ void MidiMessage::setChannel (const int channel) noexcept { jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - uint8* const data = getData(); + auto data = getData(); if ((data[0] & 0xf0) != (uint8) 0xf0) data[0] = (uint8) ((data[0] & (uint8) 0xf0) @@ -382,7 +382,7 @@ void MidiMessage::setChannel (const int channel) noexcept bool MidiMessage::isNoteOn (const bool returnTrueForVelocity0) const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return ((data[0] & 0xf0) == 0x90) && (returnTrueForVelocity0 || data[2] != 0); @@ -390,7 +390,7 @@ bool MidiMessage::isNoteOn (const bool returnTrueForVelocity0) const noexcept bool MidiMessage::isNoteOff (const bool returnTrueForNoteOnVelocity0) const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return ((data[0] & 0xf0) == 0x80) || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90)); @@ -398,9 +398,7 @@ bool MidiMessage::isNoteOff (const bool returnTrueForNoteOnVelocity0) const noex bool MidiMessage::isNoteOnOrOff() const noexcept { - const uint8* const data = getRawData(); - - const int d = data[0] & 0xf0; + auto d = getRawData()[0] & 0xf0; return (d == 0x90) || (d == 0x80); } @@ -438,7 +436,7 @@ void MidiMessage::multiplyVelocity (const float scaleFactor) noexcept { if (isNoteOnOrOff()) { - uint8* const data = getData(); + auto data = getData(); data[2] = MidiHelpers::validVelocity (roundToInt (scaleFactor * data[2])); } } @@ -522,7 +520,7 @@ bool MidiMessage::isPitchWheel() const noexcept int MidiMessage::getPitchWheelValue() const noexcept { jassert (isPitchWheel()); - const uint8* const data = getRawData(); + auto data = getRawData(); return data[1] | (data[2] << 7); } @@ -542,7 +540,7 @@ bool MidiMessage::isController() const noexcept bool MidiMessage::isControllerOfType (const int controllerType) const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return (data[0] & 0xf0) == 0xb0 && data[1] == controllerType; } @@ -610,7 +608,7 @@ MidiMessage MidiMessage::allNotesOff (const int channel) noexcept bool MidiMessage::isAllNotesOff() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return (data[0] & 0xf0) == 0xb0 && data[1] == 123; } @@ -621,8 +619,8 @@ MidiMessage MidiMessage::allSoundOff (const int channel) noexcept bool MidiMessage::isAllSoundOff() const noexcept { - const uint8* const data = getRawData(); - return (data[0] & 0xf0) == 0xb0 && data[1] == 120; + auto data = getRawData(); + return data[1] == 120 && (data[0] & 0xf0) == 0xb0; } MidiMessage MidiMessage::allControllersOff (const int channel) noexcept @@ -632,14 +630,9 @@ MidiMessage MidiMessage::allControllersOff (const int channel) noexcept MidiMessage MidiMessage::masterVolume (const float volume) { - const int vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000)); - - const uint8 buf[] = { 0xf0, 0x7f, 0x7f, 0x04, 0x01, - (uint8) (vol & 0x7f), - (uint8) (vol >> 7), - 0xf7 }; + auto vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000)); - return MidiMessage (buf, 8); + return { 0xf0, 0x7f, 0x7f, 0x04, 0x01, vol & 0x7f, vol >> 7, 0xf7 }; } //============================================================================== @@ -675,13 +668,14 @@ bool MidiMessage::isActiveSense() const noexcept { return *getRawData() == 0x int MidiMessage::getMetaEventType() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return *data != 0xff ? -1 : data[1]; } int MidiMessage::getMetaEventLength() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); + if (*data == 0xff) { int n; @@ -696,7 +690,7 @@ const uint8* MidiMessage::getMetaEventData() const noexcept jassert (isMetaEvent()); int n; - const uint8* d = getRawData() + 2; + auto d = getRawData() + 2; readVariableLengthVal (d, n); return d + n; } @@ -706,13 +700,14 @@ bool MidiMessage::isEndOfTrackMetaEvent() const noexcept { return getMetaEven bool MidiMessage::isTextMetaEvent() const noexcept { - const int t = getMetaEventType(); + auto t = getMetaEventType(); return t > 0 && t < 16; } String MidiMessage::getTextFromTextMetaEvent() const { - const char* const textData = reinterpret_cast (getMetaEventData()); + auto textData = reinterpret_cast (getMetaEventData()); + return String (CharPointer_UTF8 (textData), CharPointer_UTF8 (textData + getMetaEventLength())); } @@ -739,7 +734,7 @@ MidiMessage MidiMessage::textMetaEvent (int type, StringRef text) const size_t headerLen = sizeof (header) - n; const int totalSize = (int) (headerLen + textSize); - uint8* const dest = result.allocateSpace (totalSize); + auto dest = result.allocateSpace (totalSize); result.size = totalSize; memcpy (dest, header + n, headerLen); @@ -748,9 +743,9 @@ MidiMessage MidiMessage::textMetaEvent (int type, StringRef text) return result; } -bool MidiMessage::isTrackNameEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 3) && (*data == 0xff); } -bool MidiMessage::isTempoMetaEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 81) && (*data == 0xff); } -bool MidiMessage::isMidiChannelMetaEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); } +bool MidiMessage::isTrackNameEvent() const noexcept { auto data = getRawData(); return (data[1] == 3) && (*data == 0xff); } +bool MidiMessage::isTempoMetaEvent() const noexcept { auto data = getRawData(); return (data[1] == 81) && (*data == 0xff); } +bool MidiMessage::isMidiChannelMetaEvent() const noexcept { auto data = getRawData(); return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); } int MidiMessage::getMidiChannelMetaEventChannel() const noexcept { @@ -763,7 +758,7 @@ double MidiMessage::getTempoSecondsPerQuarterNote() const noexcept if (! isTempoMetaEvent()) return 0.0; - const uint8* const d = getMetaEventData(); + auto d = getMetaEventData(); return (((unsigned int) d[0] << 16) | ((unsigned int) d[1] << 8) @@ -780,37 +775,33 @@ double MidiMessage::getTempoMetaEventTickLength (const short timeFormat) const n return getTempoSecondsPerQuarterNote() / timeFormat; } - else - { - const int frameCode = (-timeFormat) >> 8; - double framesPerSecond; - switch (frameCode) - { - case 24: framesPerSecond = 24.0; break; - case 25: framesPerSecond = 25.0; break; - case 29: framesPerSecond = 30.0 * 1000.0 / 1001.0; break; - case 30: framesPerSecond = 30.0; break; - default: framesPerSecond = 30.0; break; - } + const int frameCode = (-timeFormat) >> 8; + double framesPerSecond; - return (1.0 / framesPerSecond) / (timeFormat & 0xff); + switch (frameCode) + { + case 24: framesPerSecond = 24.0; break; + case 25: framesPerSecond = 25.0; break; + case 29: framesPerSecond = 30.0 * 1000.0 / 1001.0; break; + case 30: framesPerSecond = 30.0; break; + default: framesPerSecond = 30.0; break; } + + return (1.0 / framesPerSecond) / (timeFormat & 0xff); } MidiMessage MidiMessage::tempoMetaEvent (int microsecondsPerQuarterNote) noexcept { - const uint8 d[] = { 0xff, 81, 3, - (uint8) (microsecondsPerQuarterNote >> 16), - (uint8) (microsecondsPerQuarterNote >> 8), - (uint8) microsecondsPerQuarterNote }; - - return MidiMessage (d, 6, 0.0); + return { 0xff, 81, 3, + (uint8) (microsecondsPerQuarterNote >> 16), + (uint8) (microsecondsPerQuarterNote >> 8), + (uint8) microsecondsPerQuarterNote }; } bool MidiMessage::isTimeSignatureMetaEvent() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return (data[1] == 0x58) && (*data == (uint8) 0xff); } @@ -818,7 +809,7 @@ void MidiMessage::getTimeSignatureInfo (int& numerator, int& denominator) const { if (isTimeSignatureMetaEvent()) { - const uint8* const d = getMetaEventData(); + auto d = getMetaEventData(); numerator = d[0]; denominator = 1 << d[1]; } @@ -840,14 +831,12 @@ MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, const int ++powerOfTwo; } - const uint8 d[] = { 0xff, 0x58, 0x04, (uint8) numerator, (uint8) powerOfTwo, 1, 96 }; - return MidiMessage (d, 7, 0.0); + return { 0xff, 0x58, 0x04, numerator, powerOfTwo, 1, 96 }; } MidiMessage MidiMessage::midiChannelMetaEvent (const int channel) noexcept { - const uint8 d[] = { 0xff, 0x20, 0x01, (uint8) jlimit (0, 0xff, channel - 1) }; - return MidiMessage (d, 4, 0.0); + return { 0xff, 0x20, 0x01, jlimit (0, 0xff, channel - 1) }; } bool MidiMessage::isKeySignatureMetaEvent() const noexcept @@ -869,37 +858,36 @@ MidiMessage MidiMessage::keySignatureMetaEvent (int numberOfSharpsOrFlats, bool { jassert (numberOfSharpsOrFlats >= -7 && numberOfSharpsOrFlats <= 7); - const uint8 d[] = { 0xff, 0x59, 0x02, (uint8) numberOfSharpsOrFlats, isMinorKey ? (uint8) 1 : (uint8) 0 }; - return MidiMessage (d, 5, 0.0); + return { 0xff, 0x59, 0x02, numberOfSharpsOrFlats, isMinorKey ? 1 : 0 }; } MidiMessage MidiMessage::endOfTrack() noexcept { - return MidiMessage (0xff, 0x2f, 0, 0.0); + return { 0xff, 0x2f }; } //============================================================================== bool MidiMessage::isSongPositionPointer() const noexcept { return *getRawData() == 0xf2; } -int MidiMessage::getSongPositionPointerMidiBeat() const noexcept { const uint8* data = getRawData(); return data[1] | (data[2] << 7); } +int MidiMessage::getSongPositionPointerMidiBeat() const noexcept { auto data = getRawData(); return data[1] | (data[2] << 7); } MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeats) noexcept { - return MidiMessage (0xf2, - positionInMidiBeats & 127, - (positionInMidiBeats >> 7) & 127); + return { 0xf2, + positionInMidiBeats & 127, + (positionInMidiBeats >> 7) & 127 }; } -bool MidiMessage::isMidiStart() const noexcept { return *getRawData() == 0xfa; } -MidiMessage MidiMessage::midiStart() noexcept { return MidiMessage (0xfa); } +bool MidiMessage::isMidiStart() const noexcept { return *getRawData() == 0xfa; } +MidiMessage MidiMessage::midiStart() noexcept { return MidiMessage (0xfa); } -bool MidiMessage::isMidiContinue() const noexcept { return *getRawData() == 0xfb; } -MidiMessage MidiMessage::midiContinue() noexcept { return MidiMessage (0xfb); } +bool MidiMessage::isMidiContinue() const noexcept { return *getRawData() == 0xfb; } +MidiMessage MidiMessage::midiContinue() noexcept { return MidiMessage (0xfb); } -bool MidiMessage::isMidiStop() const noexcept { return *getRawData() == 0xfc; } -MidiMessage MidiMessage::midiStop() noexcept { return MidiMessage (0xfc); } +bool MidiMessage::isMidiStop() const noexcept { return *getRawData() == 0xfc; } +MidiMessage MidiMessage::midiStop() noexcept { return MidiMessage (0xfc); } -bool MidiMessage::isMidiClock() const noexcept { return *getRawData() == 0xf8; } -MidiMessage MidiMessage::midiClock() noexcept { return MidiMessage (0xf8); } +bool MidiMessage::isMidiClock() const noexcept { return *getRawData() == 0xf8; } +MidiMessage MidiMessage::midiClock() noexcept { return MidiMessage (0xf8); } bool MidiMessage::isQuarterFrame() const noexcept { return *getRawData() == 0xf1; } int MidiMessage::getQuarterFrameSequenceNumber() const noexcept { return ((int) getRawData()[1]) >> 4; } @@ -912,7 +900,7 @@ MidiMessage MidiMessage::quarterFrame (const int sequenceNumber, const int value bool MidiMessage::isFullFrame() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); return data[0] == 0xf0 && data[1] == 0x7f @@ -926,7 +914,7 @@ void MidiMessage::getFullFrameParameters (int& hours, int& minutes, int& seconds { jassert (isFullFrame()); - const uint8* const data = getRawData(); + auto data = getRawData(); timecodeType = (SmpteTimecodeType) (data[5] >> 5); hours = data[5] & 0x1f; minutes = data[6]; @@ -934,23 +922,19 @@ void MidiMessage::getFullFrameParameters (int& hours, int& minutes, int& seconds frames = data[8]; } -MidiMessage MidiMessage::fullFrame (const int hours, const int minutes, - const int seconds, const int frames, +MidiMessage MidiMessage::fullFrame (int hours, int minutes, int seconds, int frames, MidiMessage::SmpteTimecodeType timecodeType) { - const uint8 d[] = { 0xf0, 0x7f, 0x7f, 0x01, 0x01, - (uint8) ((hours & 0x01f) | (timecodeType << 5)), - (uint8) minutes, - (uint8) seconds, - (uint8) frames, - 0xf7 }; - - return MidiMessage (d, 10, 0.0); + return { 0xf0, 0x7f, 0x7f, 0x01, 0x01, + (hours & 0x01f) | (timecodeType << 5), + minutes, seconds, frames, + 0xf7 }; } bool MidiMessage::isMidiMachineControlMessage() const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); + return data[0] == 0xf0 && data[1] == 0x7f && data[3] == 0x06 @@ -966,15 +950,14 @@ MidiMessage::MidiMachineControlCommand MidiMessage::getMidiMachineControlCommand MidiMessage MidiMessage::midiMachineControlCommand (MidiMessage::MidiMachineControlCommand command) { - const uint8 d[] = { 0xf0, 0x7f, 0, 6, (uint8) command, 0xf7 }; - - return MidiMessage (d, 6, 0.0); + return { 0xf0, 0x7f, 0, 6, command, 0xf7 }; } //============================================================================== bool MidiMessage::isMidiMachineControlGoto (int& hours, int& minutes, int& seconds, int& frames) const noexcept { - const uint8* const data = getRawData(); + auto data = getRawData(); + if (size >= 12 && data[0] == 0xf0 && data[1] == 0x7f @@ -996,14 +979,7 @@ bool MidiMessage::isMidiMachineControlGoto (int& hours, int& minutes, int& secon MidiMessage MidiMessage::midiMachineControlGoto (int hours, int minutes, int seconds, int frames) { - const uint8 d[] = { 0xf0, 0x7f, 0, 6, 0x44, 6, 1, - (uint8) hours, - (uint8) minutes, - (uint8) seconds, - (uint8) frames, - 0xf7 }; - - return MidiMessage (d, 12, 0.0); + return { 0xf0, 0x7f, 0, 6, 0x44, 6, 1, hours, minutes, seconds, frames, 0xf7 }; } //============================================================================== diff --git a/modules/juce_audio_basics/midi/juce_MidiMessage.h b/modules/juce_audio_basics/midi/juce_MidiMessage.h index e9c08ae1ee..cf78fbe719 100644 --- a/modules/juce_audio_basics/midi/juce_MidiMessage.h +++ b/modules/juce_audio_basics/midi/juce_MidiMessage.h @@ -68,6 +68,18 @@ public: */ MidiMessage (int byte1, double timeStamp = 0) noexcept; + /** Creates a midi message from a list of bytes. */ + template + MidiMessage (int byte1, int byte2, int byte3, Data... otherBytes) : size (3 + sizeof... (otherBytes)) + { + // this checks that the length matches the data.. + jassert (size > 3 || byte1 >= 0xf0 || getMessageLengthFromFirstByte (byte1) == size); + + const uint8 data[] = { (uint8) byte1, (uint8) byte2, (uint8) byte3, static_cast (otherBytes)... }; + memcpy (allocateSpace (size), data, (size_t) size); + } + + /** Creates a midi message from a block of data. */ MidiMessage (const void* data, int numBytes, double timeStamp = 0); @@ -473,7 +485,6 @@ public: bool isControllerOfType (int controllerType) const noexcept; /** Creates a controller message. - @param channel the midi channel, in the range 1 to 16 @param controllerType the type of controller @param value the controller value @@ -494,21 +505,18 @@ public: bool isAllSoundOff() const noexcept; /** Creates an all-notes-off message. - @param channel the midi channel, in the range 1 to 16 @see isAllNotesOff */ static MidiMessage allNotesOff (int channel) noexcept; /** Creates an all-sound-off message. - @param channel the midi channel, in the range 1 to 16 @see isAllSoundOff */ static MidiMessage allSoundOff (int channel) noexcept; /** Creates an all-controllers-off message. - @param channel the midi channel, in the range 1 to 16 */ static MidiMessage allControllersOff (int channel) noexcept; @@ -928,7 +936,7 @@ private: }; PackedData packedData; - double timeStamp; + double timeStamp = 0; int size; #endif