parser.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include <stdlib.h>
  2. #include "parser.h"
  3. typedef enum {
  4. ParserEmpty,
  5. ParserHasStatus,
  6. ParserHasData0,
  7. ParserSysEx,
  8. } ParserState;
  9. const uint8_t kStatusByteMask = 0x80;
  10. const uint8_t kMessageMask = 0x70;
  11. const uint8_t kDataByteMask = 0x7F;
  12. const uint8_t kSystemCommonMask = 0xF0;
  13. const uint8_t kChannelMask = 0x0F;
  14. const uint8_t kRealTimeMask = 0xF8;
  15. const uint8_t kSystemRealTimeMask = 0x07;
  16. struct MidiParser {
  17. MidiMessageType status;
  18. ParserState state;
  19. MidiEvent incoming_message;
  20. };
  21. MidiParser* midi_parser_alloc(void) {
  22. MidiParser* parser = malloc(sizeof(MidiParser));
  23. parser->incoming_message.type = MessageLast;
  24. parser->state = ParserEmpty;
  25. return parser;
  26. }
  27. void midi_parser_free(MidiParser* parser) {
  28. free(parser);
  29. }
  30. bool midi_parser_parse(MidiParser* parser, uint8_t byte) {
  31. bool parsed = false;
  32. MidiEvent* event = &parser->incoming_message;
  33. switch(parser->state) {
  34. case ParserEmpty:
  35. // check byte for valid Status Byte
  36. if(byte & kStatusByteMask) {
  37. // Get MessageType, and Channel
  38. event->channel = byte & kChannelMask;
  39. event->type = (MidiMessageType)((byte & kMessageMask) >> 4);
  40. // Validate, and move on.
  41. if(event->type < MessageLast) {
  42. parser->state = ParserHasStatus;
  43. // Mark this status byte as running_status
  44. parser->status = event->type;
  45. if(parser->status == SystemCommon) {
  46. event->channel = 0;
  47. //system real time = 1111 1xxx
  48. if(byte & 0x08) {
  49. event->type = SystemRealTime;
  50. parser->status = SystemRealTime;
  51. event->srt_type = (SystemRealTimeType)(byte & kSystemRealTimeMask);
  52. //short circuit to start
  53. parser->state = ParserEmpty;
  54. //queue_.push(incoming_message_);
  55. parsed = true;
  56. }
  57. //system common
  58. else {
  59. event->sc_type = (SystemCommonType)(byte & 0x07);
  60. //sysex
  61. if(event->sc_type == SystemExclusive) {
  62. parser->state = ParserSysEx;
  63. event->sysex_message_len = 0;
  64. }
  65. //short circuit
  66. else if(event->sc_type > SongSelect) {
  67. parser->state = ParserEmpty;
  68. //queue_.push(incoming_message_);
  69. parsed = true;
  70. }
  71. }
  72. }
  73. }
  74. // Else we'll keep waiting for a valid incoming status byte
  75. } else {
  76. // Handle as running status
  77. event->type = parser->status;
  78. event->data[0] = byte & kDataByteMask;
  79. parser->state = ParserHasData0;
  80. }
  81. break;
  82. case ParserHasStatus:
  83. if((byte & kStatusByteMask) == 0) {
  84. event->data[0] = byte & kDataByteMask;
  85. if(parser->status == ChannelPressure || parser->status == ProgramChange ||
  86. event->sc_type == MTCQuarterFrame || event->sc_type == SongSelect) {
  87. //these are just one data byte, so we short circuit back to start
  88. parser->state = ParserEmpty;
  89. //queue_.push(incoming_message_);
  90. parsed = true;
  91. } else {
  92. parser->state = ParserHasData0;
  93. }
  94. //ChannelModeMessages (reserved Control Changes)
  95. if(parser->status == ControlChange && event->data[0] > 119) {
  96. event->type = ChannelMode;
  97. parser->status = ChannelMode;
  98. event->cm_type = (ChannelModeType)(event->data[0] - 120);
  99. }
  100. } else {
  101. // invalid message go back to start ;p
  102. parser->state = ParserEmpty;
  103. }
  104. break;
  105. case ParserHasData0:
  106. if((byte & kStatusByteMask) == 0) {
  107. event->data[1] = byte & kDataByteMask;
  108. // At this point the message is valid, and we can add this MidiEvent to the queue
  109. //queue_.push(incoming_message_);
  110. parsed = true;
  111. }
  112. // Regardless, of whether the data was valid or not we go back to empty
  113. // because either the message is queued for handling or its not.
  114. parser->state = ParserEmpty;
  115. break;
  116. case ParserSysEx:
  117. // end of sysex
  118. if(byte == 0xf7) {
  119. parser->state = ParserEmpty;
  120. //queue_.push(incoming_message_);
  121. parsed = true;
  122. } else {
  123. if(event->sysex_message_len < SYSEX_BUFFER_LEN) {
  124. event->sysex_data[event->sysex_message_len] = byte;
  125. event->sysex_message_len++;
  126. }
  127. }
  128. break;
  129. default:
  130. break;
  131. }
  132. return parsed;
  133. }
  134. MidiEvent* midi_parser_get_message(MidiParser* parser) {
  135. return &parser->incoming_message;
  136. }