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
00001 /** 00002 * @file MIDIparser.cpp 00003 * @brief MIDI parser - converts bytes into queued MIDI messages 00004 * @author Patrick Thomas 00005 * @version 1.0 00006 * @see 00007 * 00008 * Copyright (c) 2016 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); 00011 * you may not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, 00018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 */ 00022 00023 #include "MIDIparser.h" 00024 00025 MIDIparser::MIDIparser() { 00026 00027 } 00028 00029 void MIDIparser::parse(uint8_t this_byte) { 00030 00031 // Data byte 00032 if (this_byte < 128) { 00033 00034 // We expect the output buffer to be non-empty here 00035 if (input_vector.available()) { 00036 00037 input_vector.put(this_byte); 00038 00039 // Dual condition - perform one more read after this 00040 if (!sysex && dual) dual = false; 00041 00042 // Single condition - send two bytes now 00043 else if (!sysex && !dual) { 00044 00045 output_queue.push(MIDIMessage(input_vector.head(), input_vector.size())); 00046 input_vector.clear(); 00047 } 00048 } 00049 } 00050 00051 // System realtime byte 00052 else if (this_byte > 243) { 00053 00054 switch (this_byte & 0xF) { 00055 00056 // Undefined 00057 case 4: 00058 case 5: 00059 break; 00060 00061 // Sysex end 00062 case 7: 00063 // Only output valid Sysex data 00064 if (sysex && !dual) output_queue.push(MIDIMessage(input_vector.head(), input_vector.size())); 00065 input_vector.clear(); 00066 break; 00067 00068 // Realtime 00069 default: 00070 output_queue.push(MIDIMessage(&this_byte, 1)); 00071 break; 00072 } 00073 } 00074 00075 // Status byte 00076 else { 00077 00078 // We expect the output buffer to be empty here 00079 if (!input_vector.available()) { 00080 00081 input_vector.put(this_byte); 00082 00083 // Set flags 00084 switch ((this_byte >> 4) & 7) { 00085 case 0: 00086 case 1: 00087 case 2: 00088 case 3: 00089 case 6: 00090 sysex = false; 00091 dual = true; 00092 break; 00093 00094 case 4: 00095 case 5: 00096 sysex = false; 00097 dual = false; 00098 break; 00099 00100 case 7: 00101 switch (this_byte & 7) { 00102 case 0: 00103 sysex = true; 00104 dual = false; 00105 break; 00106 00107 case 1: 00108 case 3: 00109 sysex = false; 00110 dual = false; 00111 break; 00112 00113 case 2: 00114 sysex = false; 00115 dual = true; 00116 break; 00117 00118 default: 00119 break; 00120 } 00121 break; 00122 00123 default: 00124 break; 00125 } 00126 } 00127 00128 // Invalidate the output buffer by setting flags 00129 else { 00130 sysex = true; 00131 dual = true; 00132 } 00133 } 00134 } 00135 00136 uint32_t MIDIparser::available() { return !output_queue.empty(); } 00137 00138 MIDIMessage MIDIparser::grab() { 00139 00140 MIDIMessage output; 00141 output = output_queue.front(); 00142 output_queue.pop(); 00143 return output; 00144 }
Generated on Tue Jul 12 2022 21:41:49 by 1.7.2