A class that converts byte streams into MIDI messages, and stores them in a FIFO. This is useful if you wish to read MIDI messages via polling instead of interrupts. The class supports every type of MIDI message, and System Realtime messages can be interleaved with regular ones.
MIDIparser.cpp@1:1c3f0c6ea0fb, 2016-08-04 (annotated)
- Committer:
- Padman
- Date:
- Thu Aug 04 12:02:12 2016 +0000
- Revision:
- 1:1c3f0c6ea0fb
- Parent:
- 0:69cbdcd5d770
Added API documentation
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Padman | 0:69cbdcd5d770 | 1 | /** |
Padman | 0:69cbdcd5d770 | 2 | * @file MIDIparser.cpp |
Padman | 0:69cbdcd5d770 | 3 | * @brief MIDI parser - converts bytes into queued MIDI messages |
Padman | 0:69cbdcd5d770 | 4 | * @author Patrick Thomas |
Padman | 0:69cbdcd5d770 | 5 | * @version 1.0 |
Padman | 0:69cbdcd5d770 | 6 | * @see |
Padman | 0:69cbdcd5d770 | 7 | * |
Padman | 0:69cbdcd5d770 | 8 | * Copyright (c) 2016 |
Padman | 0:69cbdcd5d770 | 9 | * |
Padman | 0:69cbdcd5d770 | 10 | * Licensed under the Apache License, Version 2.0 (the "License"); |
Padman | 0:69cbdcd5d770 | 11 | * you may not use this file except in compliance with the License. |
Padman | 0:69cbdcd5d770 | 12 | * You may obtain a copy of the License at |
Padman | 0:69cbdcd5d770 | 13 | * |
Padman | 0:69cbdcd5d770 | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
Padman | 0:69cbdcd5d770 | 15 | * |
Padman | 0:69cbdcd5d770 | 16 | * Unless required by applicable law or agreed to in writing, software |
Padman | 0:69cbdcd5d770 | 17 | * distributed under the License is distributed on an "AS IS" BASIS, |
Padman | 0:69cbdcd5d770 | 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Padman | 0:69cbdcd5d770 | 19 | * See the License for the specific language governing permissions and |
Padman | 0:69cbdcd5d770 | 20 | * limitations under the License. |
Padman | 0:69cbdcd5d770 | 21 | */ |
Padman | 0:69cbdcd5d770 | 22 | |
Padman | 0:69cbdcd5d770 | 23 | #include "MIDIparser.h" |
Padman | 0:69cbdcd5d770 | 24 | |
Padman | 0:69cbdcd5d770 | 25 | MIDIparser::MIDIparser() { |
Padman | 0:69cbdcd5d770 | 26 | |
Padman | 0:69cbdcd5d770 | 27 | } |
Padman | 0:69cbdcd5d770 | 28 | |
Padman | 0:69cbdcd5d770 | 29 | void MIDIparser::parse(uint8_t this_byte) { |
Padman | 0:69cbdcd5d770 | 30 | |
Padman | 0:69cbdcd5d770 | 31 | // Data byte |
Padman | 0:69cbdcd5d770 | 32 | if (this_byte < 128) { |
Padman | 0:69cbdcd5d770 | 33 | |
Padman | 0:69cbdcd5d770 | 34 | // We expect the output buffer to be non-empty here |
Padman | 0:69cbdcd5d770 | 35 | if (input_vector.available()) { |
Padman | 0:69cbdcd5d770 | 36 | |
Padman | 0:69cbdcd5d770 | 37 | input_vector.put(this_byte); |
Padman | 0:69cbdcd5d770 | 38 | |
Padman | 0:69cbdcd5d770 | 39 | // Dual condition - perform one more read after this |
Padman | 0:69cbdcd5d770 | 40 | if (!sysex && dual) dual = false; |
Padman | 0:69cbdcd5d770 | 41 | |
Padman | 0:69cbdcd5d770 | 42 | // Single condition - send two bytes now |
Padman | 0:69cbdcd5d770 | 43 | else if (!sysex && !dual) { |
Padman | 0:69cbdcd5d770 | 44 | |
Padman | 0:69cbdcd5d770 | 45 | output_queue.push(MIDIMessage(input_vector.head(), input_vector.size())); |
Padman | 0:69cbdcd5d770 | 46 | input_vector.clear(); |
Padman | 0:69cbdcd5d770 | 47 | } |
Padman | 0:69cbdcd5d770 | 48 | } |
Padman | 0:69cbdcd5d770 | 49 | } |
Padman | 0:69cbdcd5d770 | 50 | |
Padman | 0:69cbdcd5d770 | 51 | // System realtime byte |
Padman | 0:69cbdcd5d770 | 52 | else if (this_byte > 243) { |
Padman | 0:69cbdcd5d770 | 53 | |
Padman | 0:69cbdcd5d770 | 54 | switch (this_byte & 0xF) { |
Padman | 0:69cbdcd5d770 | 55 | |
Padman | 0:69cbdcd5d770 | 56 | // Undefined |
Padman | 0:69cbdcd5d770 | 57 | case 4: |
Padman | 0:69cbdcd5d770 | 58 | case 5: |
Padman | 0:69cbdcd5d770 | 59 | break; |
Padman | 0:69cbdcd5d770 | 60 | |
Padman | 0:69cbdcd5d770 | 61 | // Sysex end |
Padman | 0:69cbdcd5d770 | 62 | case 7: |
Padman | 0:69cbdcd5d770 | 63 | // Only output valid Sysex data |
Padman | 0:69cbdcd5d770 | 64 | if (sysex && !dual) output_queue.push(MIDIMessage(input_vector.head(), input_vector.size())); |
Padman | 0:69cbdcd5d770 | 65 | input_vector.clear(); |
Padman | 0:69cbdcd5d770 | 66 | break; |
Padman | 0:69cbdcd5d770 | 67 | |
Padman | 0:69cbdcd5d770 | 68 | // Realtime |
Padman | 0:69cbdcd5d770 | 69 | default: |
Padman | 0:69cbdcd5d770 | 70 | output_queue.push(MIDIMessage(&this_byte, 1)); |
Padman | 0:69cbdcd5d770 | 71 | break; |
Padman | 0:69cbdcd5d770 | 72 | } |
Padman | 0:69cbdcd5d770 | 73 | } |
Padman | 0:69cbdcd5d770 | 74 | |
Padman | 0:69cbdcd5d770 | 75 | // Status byte |
Padman | 0:69cbdcd5d770 | 76 | else { |
Padman | 0:69cbdcd5d770 | 77 | |
Padman | 0:69cbdcd5d770 | 78 | // We expect the output buffer to be empty here |
Padman | 0:69cbdcd5d770 | 79 | if (!input_vector.available()) { |
Padman | 0:69cbdcd5d770 | 80 | |
Padman | 0:69cbdcd5d770 | 81 | input_vector.put(this_byte); |
Padman | 0:69cbdcd5d770 | 82 | |
Padman | 0:69cbdcd5d770 | 83 | // Set flags |
Padman | 0:69cbdcd5d770 | 84 | switch ((this_byte >> 4) & 7) { |
Padman | 0:69cbdcd5d770 | 85 | case 0: |
Padman | 0:69cbdcd5d770 | 86 | case 1: |
Padman | 0:69cbdcd5d770 | 87 | case 2: |
Padman | 0:69cbdcd5d770 | 88 | case 3: |
Padman | 0:69cbdcd5d770 | 89 | case 6: |
Padman | 0:69cbdcd5d770 | 90 | sysex = false; |
Padman | 0:69cbdcd5d770 | 91 | dual = true; |
Padman | 0:69cbdcd5d770 | 92 | break; |
Padman | 0:69cbdcd5d770 | 93 | |
Padman | 0:69cbdcd5d770 | 94 | case 4: |
Padman | 0:69cbdcd5d770 | 95 | case 5: |
Padman | 0:69cbdcd5d770 | 96 | sysex = false; |
Padman | 0:69cbdcd5d770 | 97 | dual = false; |
Padman | 0:69cbdcd5d770 | 98 | break; |
Padman | 0:69cbdcd5d770 | 99 | |
Padman | 0:69cbdcd5d770 | 100 | case 7: |
Padman | 0:69cbdcd5d770 | 101 | switch (this_byte & 7) { |
Padman | 0:69cbdcd5d770 | 102 | case 0: |
Padman | 0:69cbdcd5d770 | 103 | sysex = true; |
Padman | 0:69cbdcd5d770 | 104 | dual = false; |
Padman | 0:69cbdcd5d770 | 105 | break; |
Padman | 0:69cbdcd5d770 | 106 | |
Padman | 0:69cbdcd5d770 | 107 | case 1: |
Padman | 0:69cbdcd5d770 | 108 | case 3: |
Padman | 0:69cbdcd5d770 | 109 | sysex = false; |
Padman | 0:69cbdcd5d770 | 110 | dual = false; |
Padman | 0:69cbdcd5d770 | 111 | break; |
Padman | 0:69cbdcd5d770 | 112 | |
Padman | 0:69cbdcd5d770 | 113 | case 2: |
Padman | 0:69cbdcd5d770 | 114 | sysex = false; |
Padman | 0:69cbdcd5d770 | 115 | dual = true; |
Padman | 0:69cbdcd5d770 | 116 | break; |
Padman | 0:69cbdcd5d770 | 117 | |
Padman | 0:69cbdcd5d770 | 118 | default: |
Padman | 0:69cbdcd5d770 | 119 | break; |
Padman | 0:69cbdcd5d770 | 120 | } |
Padman | 0:69cbdcd5d770 | 121 | break; |
Padman | 0:69cbdcd5d770 | 122 | |
Padman | 0:69cbdcd5d770 | 123 | default: |
Padman | 0:69cbdcd5d770 | 124 | break; |
Padman | 0:69cbdcd5d770 | 125 | } |
Padman | 0:69cbdcd5d770 | 126 | } |
Padman | 0:69cbdcd5d770 | 127 | |
Padman | 0:69cbdcd5d770 | 128 | // Invalidate the output buffer by setting flags |
Padman | 0:69cbdcd5d770 | 129 | else { |
Padman | 0:69cbdcd5d770 | 130 | sysex = true; |
Padman | 0:69cbdcd5d770 | 131 | dual = true; |
Padman | 0:69cbdcd5d770 | 132 | } |
Padman | 0:69cbdcd5d770 | 133 | } |
Padman | 0:69cbdcd5d770 | 134 | } |
Padman | 0:69cbdcd5d770 | 135 | |
Padman | 1:1c3f0c6ea0fb | 136 | uint32_t MIDIparser::available() { return !output_queue.empty(); } |
Padman | 0:69cbdcd5d770 | 137 | |
Padman | 0:69cbdcd5d770 | 138 | MIDIMessage MIDIparser::grab() { |
Padman | 0:69cbdcd5d770 | 139 | |
Padman | 0:69cbdcd5d770 | 140 | MIDIMessage output; |
Padman | 0:69cbdcd5d770 | 141 | output = output_queue.front(); |
Padman | 0:69cbdcd5d770 | 142 | output_queue.pop(); |
Padman | 0:69cbdcd5d770 | 143 | return output; |
Padman | 0:69cbdcd5d770 | 144 | } |