MidiMessage.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <vector>
  2. #include "RtMidi.h" // RtMidiError
  3. #include "MidiMessage.h"
  4. MidiMessage* MidiMessage::parseMessage(std::vector<unsigned char> &messageBytes)
  5. {
  6. // msg[0] has 8 bits
  7. // - 4 higher significant bits: message type
  8. // - 4 lower significant bits: channel (0 - 15)
  9. unsigned char messageType = messageBytes[0] >> 4;
  10. if(messageType == 0xF)
  11. {
  12. // system message
  13. throw RtMidiError("MidiMessage::parseMessage() does not support system messages yet.", RtMidiError::DEBUG_WARNING);
  14. }
  15. else
  16. {
  17. // channel message
  18. unsigned char channel = messageBytes[0] & 0xF;
  19. switch(messageType)
  20. {
  21. case NoteOnMessage::messageType:
  22. case NoteOffMessage::messageType:
  23. {
  24. unsigned char pitch = messageBytes[1];
  25. unsigned char velocity = messageBytes[2];
  26. if(messageType == NoteOffMessage::messageType || velocity == 0)
  27. {
  28. return new NoteOffMessage(channel, pitch, velocity);
  29. }
  30. else
  31. {
  32. return new NoteOnMessage(channel, pitch, velocity);
  33. }
  34. }
  35. case ControlChangeMessage::messageType:
  36. return new ControlChangeMessage(channel, messageBytes[1], messageBytes[2]);
  37. case ProgramChangeMessage::messageType:
  38. return new ProgramChangeMessage(channel, messageBytes[1]);
  39. case PitchBendChangeMessage::messageType:
  40. // messageBytes[1] are the least significant 7 bits.
  41. // messageBytes[2] are the most significant 7 bits.
  42. return new PitchBendChangeMessage(
  43. channel,
  44. (messageBytes[2] << 7) + messageBytes[1]
  45. );
  46. default:
  47. throw RtMidiError(
  48. "MidiMessage::parseMessage() does not support the given type of channel message yet.",
  49. RtMidiError::DEBUG_WARNING
  50. );
  51. }
  52. }
  53. }
  54. std::vector<unsigned char> NoteOnMessage::getBytes() const
  55. {
  56. std::vector<unsigned char> bytes(3);
  57. bytes[0] = messageType << 4 | channel;
  58. bytes[1] = pitch;
  59. bytes[2] = velocity;
  60. return bytes;
  61. }
  62. std::vector<unsigned char> NoteOffMessage::getBytes() const
  63. {
  64. std::vector<unsigned char> bytes(3);
  65. bytes[0] = messageType << 4 | channel;
  66. bytes[1] = pitch;
  67. bytes[2] = velocity;
  68. return bytes;
  69. }
  70. std::vector<unsigned char> ControlChangeMessage::getBytes() const
  71. {
  72. std::vector<unsigned char> bytes(3);
  73. bytes[0] = messageType << 4 | channel;
  74. bytes[1] = control;
  75. bytes[2] = value;
  76. return bytes;
  77. }
  78. std::vector<unsigned char> ProgramChangeMessage::getBytes() const
  79. {
  80. std::vector<unsigned char> bytes(2);
  81. bytes[0] = messageType << 4 | channel;
  82. bytes[1] = program;
  83. return bytes;
  84. }
  85. std::vector<unsigned char> PitchBendChangeMessage::getBytes() const
  86. {
  87. std::vector<unsigned char> bytes(3);
  88. bytes[0] = messageType << 4 | channel;
  89. // bytes[1] are the seven least significant bits.
  90. // bytes[2] are the seven most significant bits.
  91. bytes[1] = value & ((1 << 7) - 1);
  92. bytes[2] = value >> 7;
  93. return bytes;
  94. }
  95. std::ostream& operator<<(std::ostream& stream, const MidiMessage& message)
  96. {
  97. message.print(stream);
  98. return stream;
  99. }
  100. void NoteOnMessage::print(std::ostream& stream) const
  101. {
  102. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  103. << "note " << (unsigned short)pitch << " with velocity " << (unsigned short)velocity << " on\n";
  104. }
  105. void NoteOffMessage::print(std::ostream& stream) const
  106. {
  107. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  108. << "note " << (unsigned short)pitch << " off\n";
  109. }
  110. void ControlChangeMessage::print(std::ostream& stream) const
  111. {
  112. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  113. << "change value of control #" << (unsigned short)(control + 1)
  114. << " to " << (unsigned short)value << "\n";
  115. }
  116. void ProgramChangeMessage::print(std::ostream& stream) const
  117. {
  118. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  119. << "switch to program # " << (unsigned short)(program + 1) << "\n";
  120. }
  121. void PitchBendChangeMessage::print(std::ostream& stream) const
  122. {
  123. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  124. << "pitch bended to " << value << "\n";
  125. }