Message.cpp 3.8 KB

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