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.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MIDIparser.cpp Source File

MIDIparser.cpp

Go to the documentation of this file.
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 }