You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
6.2KB

  1. // Copyright 2013 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // Decoding of MIDI messages.
  28. #ifndef STMLIB_MIDI_H_
  29. #define STMLIB_MIDI_H_
  30. namespace stmlib_midi {
  31. const uint8_t kCCModulationWheelMsb = 0x01;
  32. const uint8_t kCCBreathController = 0x02;
  33. const uint8_t kCCFootPedalMsb = 0x04;
  34. const uint8_t kCCPortamentoTimeMsb = 0x05;
  35. const uint8_t kCCDataEntryMsb = 0x06;
  36. const uint8_t kCCVolume = 0x07;
  37. const uint8_t kCCBankLsb = 0x20;
  38. const uint8_t kCCDataEntryLsb = 0x26;
  39. const uint8_t kCCHoldPedal = 0x40;
  40. const uint8_t kCCHarmonicIntensity = 0x47;
  41. const uint8_t kCCRelease = 0x48;
  42. const uint8_t kCCAttack = 0x49;
  43. const uint8_t kCCBrightness = 0x4a;
  44. const uint8_t kCCDataIncrement = 0x60;
  45. const uint8_t kCCDataDecrement = 0x61;
  46. const uint8_t kCCNrpnLsb = 0x62;
  47. const uint8_t kCCNrpnMsb = 0x63;
  48. const uint8_t kCCOmniModeOff = 0x7c;
  49. const uint8_t kCCOmniModeOn = 0x7d;
  50. const uint8_t kCCMonoModeOn = 0x7e;
  51. const uint8_t kCCPolyModeOn = 0x7f;
  52. template<typename Handler>
  53. class MidiStreamParser {
  54. public:
  55. MidiStreamParser() {
  56. running_status_ = 0;
  57. data_size_ = 0;
  58. expected_data_size_ = 0;
  59. }
  60. void PushByte(uint8_t byte) {
  61. // Active sensing messages are filtered at the source, the hard way...
  62. if (byte == 0xfe) {
  63. return;
  64. }
  65. Handler::RawByte(byte);
  66. // Realtime messages are immediately passed-through, and do not modify the
  67. // state of the parser.
  68. if (byte >= 0xf8) {
  69. MessageReceived(byte);
  70. } else {
  71. if (byte >= 0x80) {
  72. uint8_t hi = byte & 0xf0;
  73. uint8_t lo = byte & 0x0f;
  74. data_size_ = 0;
  75. expected_data_size_ = 1;
  76. switch (hi) {
  77. case 0x80:
  78. case 0x90:
  79. case 0xa0:
  80. case 0xb0:
  81. expected_data_size_ = 2;
  82. break;
  83. case 0xc0:
  84. case 0xd0:
  85. break; // default data size of 1.
  86. case 0xe0:
  87. expected_data_size_ = 2;
  88. break;
  89. case 0xf0:
  90. if (lo > 0 && lo < 3) {
  91. expected_data_size_ = 2;
  92. } else if (lo >= 4) {
  93. expected_data_size_ = 0;
  94. }
  95. break;
  96. }
  97. if (byte == 0xf7) {
  98. if (running_status_ == 0xf0) {
  99. Handler::SysExEnd();
  100. }
  101. running_status_ = 0;
  102. } else if (byte == 0xf0) {
  103. running_status_ = 0xf0;
  104. Handler::SysExStart();
  105. } else {
  106. running_status_ = byte;
  107. }
  108. } else {
  109. data_[data_size_++] = byte;
  110. }
  111. if (data_size_ >= expected_data_size_) {
  112. MessageReceived(running_status_);
  113. data_size_ = 0;
  114. if (running_status_ > 0xf0) {
  115. expected_data_size_ = 0;
  116. running_status_ = 0;
  117. }
  118. }
  119. }
  120. }
  121. private:
  122. void MessageReceived(uint8_t status) {
  123. if (!status) {
  124. Handler::BozoByte(data_[0]);
  125. }
  126. uint8_t hi = status & 0xf0;
  127. uint8_t lo = status & 0x0f;
  128. // If this is a channel-specific message, check first that the receiver is
  129. // tuned to this channel.
  130. if (hi != 0xf0 && !Handler::CheckChannel(lo)) {
  131. Handler::RawMidiData(status, data_, data_size_, 0);
  132. return;
  133. }
  134. if (status != 0xf0 && status != 0xf7) {
  135. Handler::RawMidiData(status, data_, data_size_, 1);
  136. }
  137. switch (hi) {
  138. case 0x80:
  139. Handler::NoteOff(lo, data_[0], data_[1]);
  140. break;
  141. case 0x90:
  142. if (data_[1]) {
  143. Handler::NoteOn(lo, data_[0], data_[1]);
  144. } else {
  145. Handler::NoteOff(lo, data_[0], 0);
  146. }
  147. break;
  148. case 0xa0:
  149. Handler::Aftertouch(lo, data_[0], data_[1]);
  150. break;
  151. case 0xb0:
  152. Handler::ControlChange(lo, data_[0], data_[1]);
  153. break;
  154. case 0xc0:
  155. Handler::ProgramChange(lo, data_[0]);
  156. break;
  157. case 0xd0:
  158. Handler::Aftertouch(lo, data_[0]);
  159. break;
  160. case 0xe0:
  161. Handler::PitchBend(lo, (static_cast<uint16_t>(data_[1]) << 7) + data_[0]);
  162. break;
  163. case 0xf0:
  164. switch(lo) {
  165. case 0x0:
  166. Handler::SysExByte(data_[0]);
  167. break;
  168. case 0x1:
  169. case 0x2:
  170. case 0x3:
  171. case 0x4:
  172. case 0x5:
  173. case 0x6:
  174. // TODO(pichenettes): implement this if it makes sense.
  175. break;
  176. case 0x8:
  177. Handler::Clock();
  178. break;
  179. case 0x9:
  180. break;
  181. case 0xa:
  182. Handler::Start();
  183. break;
  184. case 0xb:
  185. Handler::Continue();
  186. break;
  187. case 0xc:
  188. Handler::Stop();
  189. break;
  190. case 0xf:
  191. Handler::Reset();
  192. break;
  193. }
  194. break;
  195. }
  196. }
  197. uint8_t running_status_;
  198. uint8_t data_[3];
  199. uint8_t data_size_; // Number of non-status byte received.
  200. uint8_t expected_data_size_; // Expected number of non-status bytes.
  201. DISALLOW_COPY_AND_ASSIGN(MidiStreamParser);
  202. };
  203. } // namespace stmlib_midi
  204. #endif // STMLIB_MIDI_H_