Message.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. unsigned char 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. std::vector<unsigned char> NoteOnMessage::getBytes() const
  53. {
  54. std::vector<unsigned char> bytes(3);
  55. bytes[0] = messageType << 4 | channel;
  56. bytes[1] = pitch;
  57. bytes[2] = velocity;
  58. return bytes;
  59. }
  60. std::vector<unsigned char> NoteOffMessage::getBytes() const
  61. {
  62. std::vector<unsigned char> bytes(3);
  63. bytes[0] = messageType << 4 | channel;
  64. bytes[1] = pitch;
  65. bytes[2] = velocity;
  66. return bytes;
  67. }
  68. std::vector<unsigned char> ControlChangeMessage::getBytes() const
  69. {
  70. std::vector<unsigned char> bytes(3);
  71. bytes[0] = messageType << 4 | channel;
  72. bytes[1] = control;
  73. bytes[2] = value;
  74. return bytes;
  75. }
  76. std::vector<unsigned char> ProgramChangeMessage::getBytes() const
  77. {
  78. std::vector<unsigned char> bytes(2);
  79. bytes[0] = messageType << 4 | channel;
  80. bytes[1] = program;
  81. return bytes;
  82. }
  83. std::vector<unsigned char> PitchBendChangeMessage::getBytes() const
  84. {
  85. std::vector<unsigned char> bytes(3);
  86. bytes[0] = messageType << 4 | channel;
  87. // bytes[1] are the seven least significant bits.
  88. // bytes[2] are the seven most significant bits.
  89. bytes[1] = value & ((1 << 7) - 1);
  90. bytes[2] = value >> 7;
  91. return bytes;
  92. }
  93. std::ostream& operator<<(std::ostream& stream, const Message& message)
  94. {
  95. message.print(stream);
  96. return stream;
  97. }
  98. void NoteOnMessage::print(std::ostream& stream) const
  99. {
  100. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  101. << "note " << (unsigned short)pitch << " with velocity " << (unsigned short)velocity << " on\n";
  102. }
  103. void NoteOffMessage::print(std::ostream& stream) const
  104. {
  105. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  106. << "note " << (unsigned short)pitch << " off\n";
  107. }
  108. void ControlChangeMessage::print(std::ostream& stream) const
  109. {
  110. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  111. << "change value of control #" << (unsigned short)(control + 1)
  112. << " to " << (unsigned short)value << "\n";
  113. }
  114. void ProgramChangeMessage::print(std::ostream& stream) const
  115. {
  116. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  117. << "switch to program # " << (unsigned short)(program + 1) << "\n";
  118. }
  119. void PitchBendChangeMessage::print(std::ostream& stream) const
  120. {
  121. stream << "channel #" << (unsigned short)(channel + 1) << ": "
  122. << "pitch bended to " << value << "\n";
  123. }
  124. } // namespace