MIDI interpreter using mbed
Dependencies: MIDI TextLCD mbed
parser.cpp
00001 #include "mbed.h" 00002 00003 #include "define.h" 00004 #include "RingBuffer.h" 00005 #include "events.h" 00006 #include "parser.h" 00007 00008 extern BusOut obLeds; 00009 #ifdef USE_PC_SERIAL 00010 extern Serial pc; 00011 #endif 00012 00013 char const sysExGmSystemOn[6] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 }; 00014 char const sysExGsReset[11] = { 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7 }; 00015 char const sysExXgSystemOn[9] = { 0xf0, 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00, 0xf7 }; 00016 00017 00018 void parseMessage(RingBuffer<char>& buffer) { 00019 static char lastStatusByte; 00020 char c; 00021 char dataBytes[2]; 00022 char sysExBuffer[SYSEX_BUFFER_LENGTH]; 00023 bool runningStatus = false; 00024 00025 c = *buffer.peek(); 00026 00027 // Running status 00028 if (!(c & 0x80)) { 00029 runningStatus = true; 00030 // Restore previous status byte 00031 c = lastStatusByte; 00032 } 00033 00034 switch (c & 0xf0) { 00035 case 0x80: /* Note off */ 00036 if (buffer.items() >= 3 - runningStatus) { 00037 if (!runningStatus) buffer.read(); 00038 for (uint8_t i = 0; i < 2; i++) { 00039 dataBytes[i] = *buffer.read(); 00040 } 00041 #ifdef USE_PC_SERIAL 00042 pc.printf("%-19s %c%02X %02X %02Xh\r\n", 00043 "Note off", runningStatus ? '*' : ' ', 00044 c, dataBytes[0], dataBytes[1]); 00045 #endif 00046 00047 dispatchNoteOff(c, dataBytes[0]); 00048 lastStatusByte = c; 00049 } 00050 break; 00051 case 0x90: /* Note on */ 00052 if (buffer.items() >= 3 - runningStatus) { 00053 if (!runningStatus) buffer.read(); 00054 for (uint8_t i = 0; i < 2; i++) { 00055 dataBytes[i] = *buffer.read(); 00056 } 00057 #ifdef USE_PC_SERIAL 00058 pc.printf("%-19s %c%02X %02X %02Xh\r\n", 00059 "Note on", runningStatus ? '*' : ' ', 00060 c, dataBytes[0], dataBytes[1]); 00061 #endif 00062 00063 if (dataBytes[1] == 0x00) { 00064 dispatchNoteOff(c, dataBytes[0]); 00065 } else { 00066 dispatchNoteOn(c, dataBytes[0], dataBytes[1]); 00067 } 00068 lastStatusByte = c; 00069 } 00070 break; 00071 case 0xa0: /* Polyphonic pressure */ 00072 // Not supported 00073 if (buffer.items() >= 3 - runningStatus) { 00074 if (!runningStatus) buffer.read(); 00075 for (uint8_t i = 0; i < 2; i++) { 00076 dataBytes[i] = *buffer.read(); 00077 } 00078 #ifdef USE_PC_SERIAL 00079 pc.printf("%-19s %c%02X %02X %02Xh\r\n", 00080 "Poly pressure", runningStatus ? '*' : ' ', 00081 c, dataBytes[0], dataBytes[1]); 00082 #endif 00083 lastStatusByte = c; 00084 } 00085 break; 00086 case 0xb0: /* Control change */ 00087 if (buffer.items() >= 3 - runningStatus) { 00088 if (!runningStatus) buffer.read(); 00089 for (uint8_t i = 0; i < 2; i++) { 00090 dataBytes[i] = *buffer.read(); 00091 } 00092 #ifdef USE_PC_SERIAL 00093 pc.printf("%-19s %c%02X %02X %02Xh\r\n", 00094 "Control change", runningStatus ? '*' : ' ', 00095 c, dataBytes[0], dataBytes[1]); 00096 #endif 00097 setControlChange(c, dataBytes[0], dataBytes[1]); 00098 lastStatusByte = c; 00099 } 00100 break; 00101 case 0xc0: /* Program change */ 00102 if (buffer.items() >= 3 - runningStatus) { 00103 if (!runningStatus) buffer.read(); 00104 for (uint8_t i = 0; i < 2; i++) { 00105 dataBytes[i] = *buffer.read(); 00106 } 00107 #ifdef USE_PC_SERIAL 00108 pc.printf("%-19s %c%02X %02X __h\r\n", 00109 "Program change", runningStatus ? '*' : ' ', 00110 c, dataBytes[0]); 00111 #endif 00112 setProgramChange(c, dataBytes[0]); 00113 lastStatusByte = c; 00114 } 00115 break; 00116 case 0xd0: /* Channel pressure */ 00117 // Not supported 00118 if (buffer.items() >= 3 - runningStatus) { 00119 if (!runningStatus) buffer.read(); 00120 for (uint8_t i = 0; i < 2; i++) { 00121 dataBytes[i] = *buffer.read(); 00122 } 00123 #ifdef USE_PC_SERIAL 00124 pc.printf("%-19s %c%02X %02X __h\r\n", 00125 "Ch pressure", runningStatus ? '*' : ' ', 00126 c, dataBytes[0]); 00127 #endif 00128 lastStatusByte = c; 00129 } 00130 break; 00131 case 0xe0: /* Pitch bend */ 00132 if (buffer.items() >= 3 - runningStatus) { 00133 if (!runningStatus) buffer.read(); 00134 for (uint8_t i = 0; i < 2; i++) { 00135 dataBytes[i] = *buffer.read(); 00136 } 00137 #ifdef USE_PC_SERIAL 00138 pc.printf("%-19s %c%02X %02X %02Xh\r\n", 00139 "Pitch bend", runningStatus ? '*' : ' ', 00140 c, dataBytes[0], dataBytes[1]); 00141 #endif 00142 setPitchBend(c, dataBytes[1] << 7 | dataBytes[0]); 00143 lastStatusByte = c; 00144 } 00145 break; 00146 case 0xf0: 00147 switch (c) { 00148 case 0xf0: /* SysEx message */ 00149 if (buffer.find(0xf7) == -1) { 00150 break; 00151 } 00152 00153 extractSysExMessage(buffer, sysExBuffer); 00154 if (strncmp(sysExBuffer, sysExGmSystemOn, 6) == 0) { 00155 // Matches "GM System On" SysEx message 00156 #ifdef USE_PC_SERIAL 00157 pc.printf("SysEx message: GM System On\r\n"); 00158 #endif 00159 obLeds = 0x1; 00160 } else if (strncmp(sysExBuffer, sysExGsReset, 11) == 0) { 00161 // Matches "GS Reset" SysEx message 00162 #ifdef USE_PC_SERIAL 00163 pc.printf("SysEx message: GS Reset\r\n"); 00164 #endif 00165 obLeds = 0x2; 00166 } else if (strncmp(sysExBuffer, sysExXgSystemOn, 9) == 0) { 00167 // Matches "XG System On" SysEx message 00168 #ifdef USE_PC_SERIAL 00169 pc.printf("SysEx message: XG System On\r\n"); 00170 #endif 00171 obLeds = 0x2; 00172 } else { 00173 #ifdef USE_PC_SERIAL 00174 pc.printf("Unsupported SysEx message\r\n"); 00175 #endif 00176 } 00177 break; 00178 case 0xf1: /* MTC quarter frame */ 00179 case 0xf3: /* Song select */ 00180 // Not supported 00181 buffer.read(); 00182 buffer.read(); 00183 obLeds = 0x0; 00184 break; 00185 case 0xf2: /* Song position */ 00186 // Not supported 00187 buffer.read(); 00188 buffer.read(); 00189 buffer.read(); 00190 obLeds = 0x0; 00191 break; 00192 case 0xf4: case 0xf5: case 0xf9: case 0xfd: /* Undefined */ 00193 case 0xf6: /* Tune request */ 00194 case 0xfa: /* Start */ 00195 case 0xfb: /* Continue */ 00196 case 0xfc: /* Stop */ 00197 buffer.read(); 00198 obLeds = 0x0; 00199 break; 00200 case 0xfe: /* Active sensing */ 00201 break; 00202 case 0xff: /* System reset */ 00203 // Discard message (@todo) 00204 buffer.read(); 00205 obLeds = 0x0; 00206 } 00207 } 00208 } 00209 00210 uint32_t extractSysExMessage(RingBuffer<char>& buffer, char* msg) { 00211 uint32_t extractedLength; 00212 char* c = NULL; 00213 00214 // Check if the first byte matches SysEx start byte (0xf0) 00215 c = buffer.read(); 00216 if (!c) return 0; 00217 if (*c != 0xf0) { 00218 return 0; 00219 } else { 00220 msg[0] = *c; 00221 } 00222 00223 // Read buffer until reaching SysEx end byte (0xf7) 00224 extractedLength = 1; 00225 while (extractedLength < SYSEX_BUFFER_LENGTH) { 00226 c = buffer.read(); 00227 if (!c) break; 00228 00229 msg[extractedLength++] = *c; 00230 if (*c == 0xf7) return extractedLength; 00231 } 00232 return 0; 00233 }
Generated on Tue Jul 12 2022 22:18:32 by 1.7.2