|
@@ -0,0 +1,92 @@
|
|
|
+#include <vector>
|
|
|
+#include "RtMidi.h" // RtMidiError
|
|
|
+#include "MidiMessage.h"
|
|
|
+
|
|
|
+MidiMessage* MidiMessage::parseMessage(std::vector<unsigned char> &messageBytes)
|
|
|
+{
|
|
|
+ // msg[0] has 8 bits
|
|
|
+ // - 4 higher significant bits: message type
|
|
|
+ // - 4 lower significant bits: channel (0 - 15)
|
|
|
+ unsigned char messageType = messageBytes[0] >> 4;
|
|
|
+ if(messageType == 0xF)
|
|
|
+ {
|
|
|
+ // system message
|
|
|
+ throw RtMidiError("MidiMessage::parseMessage() does not support system messages yet.", RtMidiError::DEBUG_WARNING);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // channel message
|
|
|
+ unsigned char channel = messageBytes[0] & 0xF;
|
|
|
+
|
|
|
+ switch(messageType)
|
|
|
+ {
|
|
|
+ case 0x8:
|
|
|
+ case 0x9:
|
|
|
+ {
|
|
|
+ unsigned char pitch = messageBytes[1];
|
|
|
+ unsigned char velocity = messageBytes[2];
|
|
|
+ if(messageType == 0x8 || velocity == 0)
|
|
|
+ {
|
|
|
+ return new NoteOffMessage(channel, pitch, velocity);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return new NoteOnMessage(channel, pitch, velocity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 0xB:
|
|
|
+ return new ControlChangeMessage(channel, messageBytes[1], messageBytes[2]);
|
|
|
+ case 0xC:
|
|
|
+ return new ProgramChangeMessage(channel, messageBytes[1]);
|
|
|
+ case 0xE:
|
|
|
+ // messageBytes[1] are the least significant 7 bits.
|
|
|
+ // messageBytes[2] are the most significant 7 bits.
|
|
|
+ return new PitchBendChangeMessage(
|
|
|
+ channel,
|
|
|
+ (messageBytes[2] << 7) + messageBytes[1]
|
|
|
+ );
|
|
|
+ default:
|
|
|
+ throw RtMidiError(
|
|
|
+ "MidiMessage::parseMessage() does not support the given type of channel message yet.",
|
|
|
+ RtMidiError::DEBUG_WARNING
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+std::ostream& operator<<(std::ostream& stream, const MidiMessage& message)
|
|
|
+{
|
|
|
+ message.print(stream);
|
|
|
+ return stream;
|
|
|
+}
|
|
|
+
|
|
|
+void NoteOnMessage::print(std::ostream& stream) const
|
|
|
+{
|
|
|
+ stream << "channel #" << (unsigned short)(channel + 1) << ": "
|
|
|
+ << "note " << (unsigned short)pitch << " with velocity " << (unsigned short)velocity << " on\n";
|
|
|
+}
|
|
|
+
|
|
|
+void NoteOffMessage::print(std::ostream& stream) const
|
|
|
+{
|
|
|
+ stream << "channel #" << (unsigned short)(channel + 1) << ": "
|
|
|
+ << "note " << (unsigned short)pitch << " off\n";
|
|
|
+}
|
|
|
+
|
|
|
+void ControlChangeMessage::print(std::ostream& stream) const
|
|
|
+{
|
|
|
+ stream << "channel #" << (unsigned short)(channel + 1) << ": "
|
|
|
+ << "change value of control #" << (unsigned short)(control + 1)
|
|
|
+ << " to " << (unsigned short)value << "\n";
|
|
|
+}
|
|
|
+
|
|
|
+void ProgramChangeMessage::print(std::ostream& stream) const
|
|
|
+{
|
|
|
+ stream << "channel #" << (unsigned short)(channel + 1) << ": "
|
|
|
+ << "switch to program # " << (unsigned short)(program + 1) << "\n";
|
|
|
+}
|
|
|
+
|
|
|
+void PitchBendChangeMessage::print(std::ostream& stream) const
|
|
|
+{
|
|
|
+ stream << "channel #" << (unsigned short)(channel + 1) << ": "
|
|
|
+ << "pitch bended to " << value << "\n";
|
|
|
+}
|