This program enables a RedBearlab nRF51822 to be used as a "bridge device" with full bi-directional communication between MIDI through standard MIDI cables and BLE-MIDI. MIDI cables are connected to the UART. This allows for example to send MIDI data to synthesizers directly from a computer or a tablet via BLE-MIDI and vice-versa, "wires-free" . The Midi Manufacturers Association BLE-MIDI Specification is used. This project is inspired by Matthias Frick's "blidino" project which implements a USB-MIDI to BLE-MIDI bridge with the nRF51822 and is available at https://github.com/sieren/blidino. I owe to him all the BLE-MIDI to MIDI parsing part.

Dependencies:   BLE_API BufferedSerial mbed nRF51822

/media/uploads/popcornell/wp_20160713_22_30_15_rich.jpg

Video

Committer:
popcornell
Date:
Tue Aug 09 12:57:23 2016 +0000
Revision:
0:244f1d0a3810
first

Who changed what in which revision?

UserRevisionLine numberNew contents of line
popcornell 0:244f1d0a3810 1 /*
popcornell 0:244f1d0a3810 2 * Copyright (c) 2014 Matthias Frick
popcornell 0:244f1d0a3810 3 *
popcornell 0:244f1d0a3810 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
popcornell 0:244f1d0a3810 5 * of this software and associated documentation files (the "Software"), to deal
popcornell 0:244f1d0a3810 6 * in the Software without restriction, including without limitation the rights
popcornell 0:244f1d0a3810 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
popcornell 0:244f1d0a3810 8 * copies of the Software, and to permit persons to whom the Software is
popcornell 0:244f1d0a3810 9 * furnished to do so, subject to the following conditions:
popcornell 0:244f1d0a3810 10 *
popcornell 0:244f1d0a3810 11 * The above copyright notice and this permission notice shall be included in all
popcornell 0:244f1d0a3810 12 * copies or substantial portions of the Software.
popcornell 0:244f1d0a3810 13 *
popcornell 0:244f1d0a3810 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
popcornell 0:244f1d0a3810 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
popcornell 0:244f1d0a3810 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
popcornell 0:244f1d0a3810 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
popcornell 0:244f1d0a3810 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
popcornell 0:244f1d0a3810 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
popcornell 0:244f1d0a3810 20 * SOFTWARE.
popcornell 0:244f1d0a3810 21 *
popcornell 0:244f1d0a3810 22 */
popcornell 0:244f1d0a3810 23
popcornell 0:244f1d0a3810 24 #ifndef ____BLE_MIDI_Parser__
popcornell 0:244f1d0a3810 25 #define ____BLE_MIDI_Parser__
popcornell 0:244f1d0a3810 26 #include <stdio.h>
popcornell 0:244f1d0a3810 27 #include <stdbool.h>
popcornell 0:244f1d0a3810 28 #include <string.h>
popcornell 0:244f1d0a3810 29
popcornell 0:244f1d0a3810 30
popcornell 0:244f1d0a3810 31
popcornell 0:244f1d0a3810 32
popcornell 0:244f1d0a3810 33
popcornell 0:244f1d0a3810 34 const int kMaxBufferSize=256; // max lenght for sysex buffer size
popcornell 0:244f1d0a3810 35
popcornell 0:244f1d0a3810 36 uint8_t midiBuffer[3];
popcornell 0:244f1d0a3810 37 uint8_t sysExBuffer[kMaxBufferSize];
popcornell 0:244f1d0a3810 38 uint8_t alterSysExBuffer[kMaxBufferSize];
popcornell 0:244f1d0a3810 39 int midiBufferPtr ; // int midiBufferPtr = 0;
popcornell 0:244f1d0a3810 40 int sysExRecBufferPtr ; // int sysExRecBufferPtr = 0;
popcornell 0:244f1d0a3810 41 int sysExBufferPtr ; // int sysExBufferPtr = 0;
popcornell 0:244f1d0a3810 42
popcornell 0:244f1d0a3810 43
popcornell 0:244f1d0a3810 44 // MIDI event messages, state & stamps
popcornell 0:244f1d0a3810 45 int midiEventKind;
popcornell 0:244f1d0a3810 46 int midiEventNote;
popcornell 0:244f1d0a3810 47 int midiEventVelocity;
popcornell 0:244f1d0a3810 48 int midiState; //int midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 49 int timestamp;
popcornell 0:244f1d0a3810 50
popcornell 0:244f1d0a3810 51
popcornell 0:244f1d0a3810 52 bool useTimestamp ; // bool useTimestamp = true;
popcornell 0:244f1d0a3810 53
popcornell 0:244f1d0a3810 54 int lastTimestamp;
popcornell 0:244f1d0a3810 55 long lastTimestampRecorded ; // long lastTimestampRecorded = 0;
popcornell 0:244f1d0a3810 56 int zeroTimestampCount; // int zeroTimestampCount = 0;
popcornell 0:244f1d0a3810 57 //Receiver *midiRecv;
popcornell 0:244f1d0a3810 58
popcornell 0:244f1d0a3810 59
popcornell 0:244f1d0a3810 60
popcornell 0:244f1d0a3810 61
popcornell 0:244f1d0a3810 62 ////////////////////////////////////
popcornell 0:244f1d0a3810 63
popcornell 0:244f1d0a3810 64
popcornell 0:244f1d0a3810 65 static int MIDI_STATE_TIMESTAMP = 0;
popcornell 0:244f1d0a3810 66 static int MIDI_STATE_WAIT = 1;
popcornell 0:244f1d0a3810 67 static int MIDI_STATE_SIGNAL_2BYTES_2 = 21;
popcornell 0:244f1d0a3810 68 static int MIDI_STATE_SIGNAL_3BYTES_2 = 31;
popcornell 0:244f1d0a3810 69 static int MIDI_STATE_SIGNAL_3BYTES_3 = 32;
popcornell 0:244f1d0a3810 70 static int MIDI_STATE_SIGNAL_SYSEX = 41;
popcornell 0:244f1d0a3810 71
popcornell 0:244f1d0a3810 72 // for Timestamp
popcornell 0:244f1d0a3810 73 static int MAX_TIMESTAMP = 8192;
popcornell 0:244f1d0a3810 74 static int BUFFER_LENGTH_MILLIS = 10;
popcornell 0:244f1d0a3810 75
popcornell 0:244f1d0a3810 76
popcornell 0:244f1d0a3810 77 // for RPN/NRPN messages
popcornell 0:244f1d0a3810 78 static int PARAMETER_MODE_NONE = 0;
popcornell 0:244f1d0a3810 79 static int PARAMETER_MODE_RPN = 1;
popcornell 0:244f1d0a3810 80 static int PARAMETER_MODE_NRPN = 2;
popcornell 0:244f1d0a3810 81 int parameterMode = 0;
popcornell 0:244f1d0a3810 82 int parameterNumber = 0x3fff;
popcornell 0:244f1d0a3810 83 int parameterValue = 0x3fff;
popcornell 0:244f1d0a3810 84
popcornell 0:244f1d0a3810 85 void addByteToMidiBuffer(uint8_t midiEvent)
popcornell 0:244f1d0a3810 86 {
popcornell 0:244f1d0a3810 87 midiBuffer[midiBufferPtr] = midiEvent;
popcornell 0:244f1d0a3810 88 midiBufferPtr++;
popcornell 0:244f1d0a3810 89 }
popcornell 0:244f1d0a3810 90
popcornell 0:244f1d0a3810 91 void addByteToSysExBuffer(uint8_t midiEvent)
popcornell 0:244f1d0a3810 92 {
popcornell 0:244f1d0a3810 93 sysExBuffer[sysExBufferPtr] = midiEvent;
popcornell 0:244f1d0a3810 94 sysExBufferPtr++;
popcornell 0:244f1d0a3810 95 }
popcornell 0:244f1d0a3810 96
popcornell 0:244f1d0a3810 97 uint8_t replaceLastByteInSysExBuffer(uint8_t midiEvent)
popcornell 0:244f1d0a3810 98 {
popcornell 0:244f1d0a3810 99 sysExBufferPtr--;
popcornell 0:244f1d0a3810 100 uint8_t lastEvt = sysExBuffer[sysExBufferPtr];
popcornell 0:244f1d0a3810 101 sysExBuffer[sysExBufferPtr] = midiEvent;
popcornell 0:244f1d0a3810 102 sysExBufferPtr++;
popcornell 0:244f1d0a3810 103 return lastEvt;
popcornell 0:244f1d0a3810 104 }
popcornell 0:244f1d0a3810 105
popcornell 0:244f1d0a3810 106 void sendSysex()
popcornell 0:244f1d0a3810 107 {
popcornell 0:244f1d0a3810 108
popcornell 0:244f1d0a3810 109 for(int i = 0 ; i<=sysExBufferPtr; i++ ) { // send sysex message on the UART
popcornell 0:244f1d0a3810 110 UART.putc(sysExBuffer[i]) ;
popcornell 0:244f1d0a3810 111 }
popcornell 0:244f1d0a3810 112 //midiRecv->SendSysEx(sysExBuffer, sysExBufferPtr, 0);
popcornell 0:244f1d0a3810 113 }
popcornell 0:244f1d0a3810 114
popcornell 0:244f1d0a3810 115 void createSysExRecovery()
popcornell 0:244f1d0a3810 116 {
popcornell 0:244f1d0a3810 117 sysExRecBufferPtr = sysExBufferPtr;
popcornell 0:244f1d0a3810 118 memcpy(alterSysExBuffer, sysExBuffer, sysExBufferPtr);
popcornell 0:244f1d0a3810 119 }
popcornell 0:244f1d0a3810 120
popcornell 0:244f1d0a3810 121 void sendSysexRecovery()
popcornell 0:244f1d0a3810 122 {
popcornell 0:244f1d0a3810 123
popcornell 0:244f1d0a3810 124 for(int i = 0 ; i<=sysExRecBufferPtr; i++ ) {
popcornell 0:244f1d0a3810 125 UART.putc(alterSysExBuffer[i]) ;
popcornell 0:244f1d0a3810 126 }
popcornell 0:244f1d0a3810 127 // midiRecv->SendSysEx(alterSysExBuffer, sysExRecBufferPtr, 0);
popcornell 0:244f1d0a3810 128 }
popcornell 0:244f1d0a3810 129
popcornell 0:244f1d0a3810 130 uint8_t replaceLastByteInRecoveryBuffer(uint8_t midiEvent)
popcornell 0:244f1d0a3810 131 {
popcornell 0:244f1d0a3810 132 sysExRecBufferPtr--;
popcornell 0:244f1d0a3810 133 uint8_t lastEvt = alterSysExBuffer[sysExRecBufferPtr];
popcornell 0:244f1d0a3810 134 alterSysExBuffer[sysExRecBufferPtr] = midiEvent;
popcornell 0:244f1d0a3810 135 sysExRecBufferPtr++;
popcornell 0:244f1d0a3810 136 return lastEvt;
popcornell 0:244f1d0a3810 137 }
popcornell 0:244f1d0a3810 138
popcornell 0:244f1d0a3810 139 void addByteToRecoveryBuffer(uint8_t midiEvent)
popcornell 0:244f1d0a3810 140 {
popcornell 0:244f1d0a3810 141 alterSysExBuffer[sysExRecBufferPtr] = midiEvent;
popcornell 0:244f1d0a3810 142 sysExRecBufferPtr++;
popcornell 0:244f1d0a3810 143 }
popcornell 0:244f1d0a3810 144
popcornell 0:244f1d0a3810 145 void resetMidiBuffer()
popcornell 0:244f1d0a3810 146 {
popcornell 0:244f1d0a3810 147 memset(&midiBuffer[0], 0, sizeof(midiBuffer));
popcornell 0:244f1d0a3810 148 midiBufferPtr = 0;
popcornell 0:244f1d0a3810 149 }
popcornell 0:244f1d0a3810 150
popcornell 0:244f1d0a3810 151 void resetSysExBuffer()
popcornell 0:244f1d0a3810 152 {
popcornell 0:244f1d0a3810 153 memset(&sysExBuffer[0], 0, kMaxBufferSize);
popcornell 0:244f1d0a3810 154 sysExBufferPtr = 0;
popcornell 0:244f1d0a3810 155 }
popcornell 0:244f1d0a3810 156
popcornell 0:244f1d0a3810 157 void resetRecoveryBuffer()
popcornell 0:244f1d0a3810 158 {
popcornell 0:244f1d0a3810 159 memset(&alterSysExBuffer[0], 0, sizeof(alterSysExBuffer));
popcornell 0:244f1d0a3810 160 sysExRecBufferPtr = 0;
popcornell 0:244f1d0a3810 161 }
popcornell 0:244f1d0a3810 162
popcornell 0:244f1d0a3810 163 void sendMidi(uint8_t size) // send MIDI Message on the UART
popcornell 0:244f1d0a3810 164 {
popcornell 0:244f1d0a3810 165 for(int i = 0 ; i<=size ; i++ ) {
popcornell 0:244f1d0a3810 166 UART.putc(midiBuffer[i]) ;
popcornell 0:244f1d0a3810 167 }
popcornell 0:244f1d0a3810 168
popcornell 0:244f1d0a3810 169 }
popcornell 0:244f1d0a3810 170
popcornell 0:244f1d0a3810 171
popcornell 0:244f1d0a3810 172
popcornell 0:244f1d0a3810 173 void parseMidiEvent(uint8_t header, const uint8_t event)
popcornell 0:244f1d0a3810 174 {
popcornell 0:244f1d0a3810 175 uint8_t midiEvent = event & 0xff;
popcornell 0:244f1d0a3810 176
popcornell 0:244f1d0a3810 177 // printf((char*)midiEvent);
popcornell 0:244f1d0a3810 178 if (midiState == MIDI_STATE_TIMESTAMP)
popcornell 0:244f1d0a3810 179 {
popcornell 0:244f1d0a3810 180 // printf("Timestamp");
popcornell 0:244f1d0a3810 181 if ((midiEvent & 0x80) == 0)
popcornell 0:244f1d0a3810 182 {
popcornell 0:244f1d0a3810 183 // running status
popcornell 0:244f1d0a3810 184 midiState = MIDI_STATE_WAIT;
popcornell 0:244f1d0a3810 185 }
popcornell 0:244f1d0a3810 186
popcornell 0:244f1d0a3810 187 if (midiEvent == 0xf7)
popcornell 0:244f1d0a3810 188 {
popcornell 0:244f1d0a3810 189 // make sure this is the end of sysex
popcornell 0:244f1d0a3810 190 // and send alternative recovery stream
popcornell 0:244f1d0a3810 191 if (sysExRecBufferPtr > 0)
popcornell 0:244f1d0a3810 192 {
popcornell 0:244f1d0a3810 193 uint8_t removed = replaceLastByteInRecoveryBuffer(midiEvent);
popcornell 0:244f1d0a3810 194 sendSysexRecovery();
popcornell 0:244f1d0a3810 195 resetRecoveryBuffer();
popcornell 0:244f1d0a3810 196 }
popcornell 0:244f1d0a3810 197 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 198 return;
popcornell 0:244f1d0a3810 199 }
popcornell 0:244f1d0a3810 200 else
popcornell 0:244f1d0a3810 201 {
popcornell 0:244f1d0a3810 202 // reset alternative sysex stream
popcornell 0:244f1d0a3810 203 resetRecoveryBuffer();
popcornell 0:244f1d0a3810 204 }
popcornell 0:244f1d0a3810 205 } // end of timestamp
popcornell 0:244f1d0a3810 206
popcornell 0:244f1d0a3810 207 if (midiState == MIDI_STATE_TIMESTAMP)
popcornell 0:244f1d0a3810 208 {
popcornell 0:244f1d0a3810 209 timestamp = ((header & 0x3f) << 7) | (midiEvent & 0x7f);
popcornell 0:244f1d0a3810 210 midiState = MIDI_STATE_WAIT;
popcornell 0:244f1d0a3810 211 }
popcornell 0:244f1d0a3810 212 else if (midiState == MIDI_STATE_WAIT)
popcornell 0:244f1d0a3810 213 {
popcornell 0:244f1d0a3810 214 switch (midiEvent & 0xf0) {
popcornell 0:244f1d0a3810 215 case 0xf0: {
popcornell 0:244f1d0a3810 216 switch (midiEvent) {
popcornell 0:244f1d0a3810 217 case 0xf0:
popcornell 0:244f1d0a3810 218 resetRecoveryBuffer();
popcornell 0:244f1d0a3810 219 resetSysExBuffer();
popcornell 0:244f1d0a3810 220 addByteToSysExBuffer(midiEvent);
popcornell 0:244f1d0a3810 221 midiState = MIDI_STATE_SIGNAL_SYSEX;
popcornell 0:244f1d0a3810 222 break;
popcornell 0:244f1d0a3810 223 case 0xf1:
popcornell 0:244f1d0a3810 224 case 0xf3:
popcornell 0:244f1d0a3810 225 // 0xf1 MIDI Time Code Quarter Frame. : 2bytes
popcornell 0:244f1d0a3810 226 // 0xf3 Song Select. : 2bytes
popcornell 0:244f1d0a3810 227 midiEventKind = midiEvent;
popcornell 0:244f1d0a3810 228 addByteToMidiBuffer(midiEvent);
popcornell 0:244f1d0a3810 229 midiState = MIDI_STATE_SIGNAL_2BYTES_2;
popcornell 0:244f1d0a3810 230 break;
popcornell 0:244f1d0a3810 231 case 0xf2:
popcornell 0:244f1d0a3810 232 // 0xf2 Song Position Pointer. : 3bytes
popcornell 0:244f1d0a3810 233 midiEventKind = midiEvent;
popcornell 0:244f1d0a3810 234 addByteToMidiBuffer(midiEvent);
popcornell 0:244f1d0a3810 235 midiState = MIDI_STATE_SIGNAL_3BYTES_2;
popcornell 0:244f1d0a3810 236 break;
popcornell 0:244f1d0a3810 237 case 0xf6:
popcornell 0:244f1d0a3810 238 // 0xf6 Tune Request : 1byte
popcornell 0:244f1d0a3810 239 addByteToMidiBuffer(midiEvent);
popcornell 0:244f1d0a3810 240 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 241 break;
popcornell 0:244f1d0a3810 242 case 0xf8:
popcornell 0:244f1d0a3810 243 // 0xf8 Timing Clock : 1byte
popcornell 0:244f1d0a3810 244 //#pragma mark send timeclock // no on mbed OS
popcornell 0:244f1d0a3810 245 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 246 break;
popcornell 0:244f1d0a3810 247 case 0xfa:
popcornell 0:244f1d0a3810 248 // 0xfa Start : 1byte
popcornell 0:244f1d0a3810 249 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 250 break;
popcornell 0:244f1d0a3810 251 case 0xfb:
popcornell 0:244f1d0a3810 252 // 0xfb Continue : 1byte
popcornell 0:244f1d0a3810 253 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 254 break;
popcornell 0:244f1d0a3810 255 case 0xfc:
popcornell 0:244f1d0a3810 256 // 0xfc Stop : 1byte
popcornell 0:244f1d0a3810 257 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 258 break;
popcornell 0:244f1d0a3810 259 case 0xfe:
popcornell 0:244f1d0a3810 260 // 0xfe Active Sensing : 1byte
popcornell 0:244f1d0a3810 261 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 262 break;
popcornell 0:244f1d0a3810 263 case 0xff:
popcornell 0:244f1d0a3810 264 // 0xff Reset : 1byte
popcornell 0:244f1d0a3810 265 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 266 break;
popcornell 0:244f1d0a3810 267
popcornell 0:244f1d0a3810 268 default:
popcornell 0:244f1d0a3810 269 break;
popcornell 0:244f1d0a3810 270 }
popcornell 0:244f1d0a3810 271 }
popcornell 0:244f1d0a3810 272 break;
popcornell 0:244f1d0a3810 273 case 0x80:
popcornell 0:244f1d0a3810 274 case 0x90:
popcornell 0:244f1d0a3810 275 case 0xa0:
popcornell 0:244f1d0a3810 276 case 0xb0:
popcornell 0:244f1d0a3810 277 case 0xe0:
popcornell 0:244f1d0a3810 278 // 3bytes pattern
popcornell 0:244f1d0a3810 279 midiEventKind = midiEvent;
popcornell 0:244f1d0a3810 280 midiState = MIDI_STATE_SIGNAL_3BYTES_2;
popcornell 0:244f1d0a3810 281 break;
popcornell 0:244f1d0a3810 282 case 0xc0: // program change
popcornell 0:244f1d0a3810 283 case 0xd0: // channel after-touch
popcornell 0:244f1d0a3810 284 // 2bytes pattern
popcornell 0:244f1d0a3810 285 midiEventKind = midiEvent;
popcornell 0:244f1d0a3810 286 midiState = MIDI_STATE_SIGNAL_2BYTES_2;
popcornell 0:244f1d0a3810 287 break;
popcornell 0:244f1d0a3810 288 default:
popcornell 0:244f1d0a3810 289 // 0x00 - 0x70: running status
popcornell 0:244f1d0a3810 290 if ((midiEventKind & 0xf0) != 0xf0) {
popcornell 0:244f1d0a3810 291 // previous event kind is multi-bytes pattern
popcornell 0:244f1d0a3810 292 midiEventNote = midiEvent;
popcornell 0:244f1d0a3810 293 midiState = MIDI_STATE_SIGNAL_3BYTES_3;
popcornell 0:244f1d0a3810 294 }
popcornell 0:244f1d0a3810 295 break;
popcornell 0:244f1d0a3810 296 }
popcornell 0:244f1d0a3810 297 }
popcornell 0:244f1d0a3810 298 else if (midiState == MIDI_STATE_SIGNAL_2BYTES_2)
popcornell 0:244f1d0a3810 299 {
popcornell 0:244f1d0a3810 300 switch (midiEventKind & 0xf0)
popcornell 0:244f1d0a3810 301 {
popcornell 0:244f1d0a3810 302 // 2bytes pattern
popcornell 0:244f1d0a3810 303 case 0xc0: // program change
popcornell 0:244f1d0a3810 304 midiEventNote = midiEvent;
popcornell 0:244f1d0a3810 305 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 306 break;
popcornell 0:244f1d0a3810 307 case 0xd0: // channel after-touch
popcornell 0:244f1d0a3810 308 midiEventNote = midiEvent;
popcornell 0:244f1d0a3810 309 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 310 break;
popcornell 0:244f1d0a3810 311 case 0xf0:
popcornell 0:244f1d0a3810 312 {
popcornell 0:244f1d0a3810 313 switch (midiEventKind)
popcornell 0:244f1d0a3810 314 {
popcornell 0:244f1d0a3810 315 case 0xf1:
popcornell 0:244f1d0a3810 316 // 0xf1 MIDI Time Code Quarter Frame. : 2bytes
popcornell 0:244f1d0a3810 317 midiEventNote = midiEvent;
popcornell 0:244f1d0a3810 318 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 319 sendMidi(2);
popcornell 0:244f1d0a3810 320 resetMidiBuffer();
popcornell 0:244f1d0a3810 321 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 322 break;
popcornell 0:244f1d0a3810 323 case 0xf3:
popcornell 0:244f1d0a3810 324 // 0xf3 Song Select. : 2bytes
popcornell 0:244f1d0a3810 325 midiEventNote = midiEvent;
popcornell 0:244f1d0a3810 326 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 327 sendMidi(2);
popcornell 0:244f1d0a3810 328 resetMidiBuffer();
popcornell 0:244f1d0a3810 329 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 330 break;
popcornell 0:244f1d0a3810 331 default:
popcornell 0:244f1d0a3810 332 // illegal state
popcornell 0:244f1d0a3810 333 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 334 break;
popcornell 0:244f1d0a3810 335 }
popcornell 0:244f1d0a3810 336 }
popcornell 0:244f1d0a3810 337 break;
popcornell 0:244f1d0a3810 338 default:
popcornell 0:244f1d0a3810 339 // illegal state
popcornell 0:244f1d0a3810 340 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 341 break;
popcornell 0:244f1d0a3810 342 }
popcornell 0:244f1d0a3810 343 }
popcornell 0:244f1d0a3810 344 else if (midiState == MIDI_STATE_SIGNAL_3BYTES_2)
popcornell 0:244f1d0a3810 345 {
popcornell 0:244f1d0a3810 346 switch (midiEventKind & 0xf0)
popcornell 0:244f1d0a3810 347 {
popcornell 0:244f1d0a3810 348 case 0x80:
popcornell 0:244f1d0a3810 349 case 0x90:
popcornell 0:244f1d0a3810 350 case 0xa0:
popcornell 0:244f1d0a3810 351 case 0xb0:
popcornell 0:244f1d0a3810 352 case 0xe0:
popcornell 0:244f1d0a3810 353 case 0xf0:
popcornell 0:244f1d0a3810 354 // 3bytes pattern
popcornell 0:244f1d0a3810 355 midiEventNote = midiEvent;
popcornell 0:244f1d0a3810 356 midiState = MIDI_STATE_SIGNAL_3BYTES_3;
popcornell 0:244f1d0a3810 357 break;
popcornell 0:244f1d0a3810 358 default:
popcornell 0:244f1d0a3810 359 // illegal state
popcornell 0:244f1d0a3810 360 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 361 break;
popcornell 0:244f1d0a3810 362 }
popcornell 0:244f1d0a3810 363 }
popcornell 0:244f1d0a3810 364 else if (midiState == MIDI_STATE_SIGNAL_3BYTES_3)
popcornell 0:244f1d0a3810 365 {
popcornell 0:244f1d0a3810 366 switch (midiEventKind & 0xf0)
popcornell 0:244f1d0a3810 367 {
popcornell 0:244f1d0a3810 368 // 3bytes pattern
popcornell 0:244f1d0a3810 369 case 0x80: // note off
popcornell 0:244f1d0a3810 370
popcornell 0:244f1d0a3810 371 midiEventVelocity = midiEvent;
popcornell 0:244f1d0a3810 372 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 373 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 374 addByteToMidiBuffer(midiEventVelocity);
popcornell 0:244f1d0a3810 375 sendMidi(3);
popcornell 0:244f1d0a3810 376 resetMidiBuffer();
popcornell 0:244f1d0a3810 377 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 378 break;
popcornell 0:244f1d0a3810 379 case 0x90: // note on
popcornell 0:244f1d0a3810 380 midiEventVelocity = midiEvent;
popcornell 0:244f1d0a3810 381 //timeToWait = calculateTimeToWait(timestamp);
popcornell 0:244f1d0a3810 382
popcornell 0:244f1d0a3810 383 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 384 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 385 addByteToMidiBuffer(midiEventVelocity);
popcornell 0:244f1d0a3810 386 sendMidi(3);
popcornell 0:244f1d0a3810 387 resetMidiBuffer();
popcornell 0:244f1d0a3810 388 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 389 break;
popcornell 0:244f1d0a3810 390 case 0xa0: // control polyphonic key pressure
popcornell 0:244f1d0a3810 391 midiEventVelocity = midiEvent;
popcornell 0:244f1d0a3810 392 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 393 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 394 addByteToMidiBuffer(midiEventVelocity);
popcornell 0:244f1d0a3810 395 sendMidi(3);
popcornell 0:244f1d0a3810 396 resetMidiBuffer();
popcornell 0:244f1d0a3810 397 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 398 break;
popcornell 0:244f1d0a3810 399 case 0xb0: // control change
popcornell 0:244f1d0a3810 400 midiEventVelocity = midiEvent;
popcornell 0:244f1d0a3810 401 switch (midiEventNote & 0x7f)
popcornell 0:244f1d0a3810 402 {
popcornell 0:244f1d0a3810 403 case 98:
popcornell 0:244f1d0a3810 404 // NRPN LSB
popcornell 0:244f1d0a3810 405 parameterNumber &= 0x3f80;
popcornell 0:244f1d0a3810 406 parameterNumber |= midiEventVelocity & 0x7f;
popcornell 0:244f1d0a3810 407 parameterMode = PARAMETER_MODE_NRPN;
popcornell 0:244f1d0a3810 408 break;
popcornell 0:244f1d0a3810 409 case 99:
popcornell 0:244f1d0a3810 410 // NRPN MSB
popcornell 0:244f1d0a3810 411 parameterNumber &= 0x007f;
popcornell 0:244f1d0a3810 412 parameterNumber |= (midiEventVelocity & 0x7f) << 7;
popcornell 0:244f1d0a3810 413 parameterMode = PARAMETER_MODE_NRPN;
popcornell 0:244f1d0a3810 414 break;
popcornell 0:244f1d0a3810 415 case 100:
popcornell 0:244f1d0a3810 416 // RPN LSB
popcornell 0:244f1d0a3810 417 parameterNumber &= 0x3f80;
popcornell 0:244f1d0a3810 418 parameterNumber |= midiEventVelocity & 0x7f;
popcornell 0:244f1d0a3810 419 parameterMode = PARAMETER_MODE_RPN;
popcornell 0:244f1d0a3810 420 break;
popcornell 0:244f1d0a3810 421 case 101:
popcornell 0:244f1d0a3810 422 // RPN MSB
popcornell 0:244f1d0a3810 423 parameterNumber &= 0x007f;
popcornell 0:244f1d0a3810 424 parameterNumber |= (midiEventVelocity & 0x7f) << 7;
popcornell 0:244f1d0a3810 425 parameterMode = PARAMETER_MODE_RPN;
popcornell 0:244f1d0a3810 426 break;
popcornell 0:244f1d0a3810 427 case 38:
popcornell 0:244f1d0a3810 428 // data LSB
popcornell 0:244f1d0a3810 429 parameterValue &= 0x3f80;
popcornell 0:244f1d0a3810 430 parameterValue |= midiEventVelocity & 0x7f;
popcornell 0:244f1d0a3810 431
popcornell 0:244f1d0a3810 432 if (parameterNumber != 0x3fff) {
popcornell 0:244f1d0a3810 433 if (parameterMode == PARAMETER_MODE_RPN)
popcornell 0:244f1d0a3810 434 {
popcornell 0:244f1d0a3810 435 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 436 addByteToMidiBuffer(parameterNumber);
popcornell 0:244f1d0a3810 437 addByteToMidiBuffer(parameterValue);
popcornell 0:244f1d0a3810 438 sendMidi(3);
popcornell 0:244f1d0a3810 439 resetMidiBuffer();
popcornell 0:244f1d0a3810 440 }
popcornell 0:244f1d0a3810 441 else if (parameterMode == PARAMETER_MODE_NRPN)
popcornell 0:244f1d0a3810 442 {
popcornell 0:244f1d0a3810 443 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 444 addByteToMidiBuffer(parameterNumber);
popcornell 0:244f1d0a3810 445 addByteToMidiBuffer(parameterValue);
popcornell 0:244f1d0a3810 446 sendMidi(3);
popcornell 0:244f1d0a3810 447 resetMidiBuffer();
popcornell 0:244f1d0a3810 448 }
popcornell 0:244f1d0a3810 449 }
popcornell 0:244f1d0a3810 450 break;
popcornell 0:244f1d0a3810 451 case 6:
popcornell 0:244f1d0a3810 452 // data MSB
popcornell 0:244f1d0a3810 453 parameterValue &= 0x007f;
popcornell 0:244f1d0a3810 454 parameterValue |= (midiEventVelocity & 0x7f) << 7;
popcornell 0:244f1d0a3810 455
popcornell 0:244f1d0a3810 456 if (parameterNumber != 0x3fff)
popcornell 0:244f1d0a3810 457 {
popcornell 0:244f1d0a3810 458 if (parameterMode == PARAMETER_MODE_RPN)
popcornell 0:244f1d0a3810 459 {
popcornell 0:244f1d0a3810 460 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 461 addByteToMidiBuffer(parameterNumber);
popcornell 0:244f1d0a3810 462 addByteToMidiBuffer(parameterValue);
popcornell 0:244f1d0a3810 463 sendMidi(3);
popcornell 0:244f1d0a3810 464 resetMidiBuffer();
popcornell 0:244f1d0a3810 465 }
popcornell 0:244f1d0a3810 466 else if (parameterMode == PARAMETER_MODE_NRPN)
popcornell 0:244f1d0a3810 467 {
popcornell 0:244f1d0a3810 468 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 469 addByteToMidiBuffer(parameterNumber);
popcornell 0:244f1d0a3810 470 addByteToMidiBuffer(parameterValue);
popcornell 0:244f1d0a3810 471 sendMidi(3);
popcornell 0:244f1d0a3810 472 resetMidiBuffer();
popcornell 0:244f1d0a3810 473 }
popcornell 0:244f1d0a3810 474 }
popcornell 0:244f1d0a3810 475 break;
popcornell 0:244f1d0a3810 476 default:
popcornell 0:244f1d0a3810 477 // do nothing
popcornell 0:244f1d0a3810 478 break;
popcornell 0:244f1d0a3810 479 }
popcornell 0:244f1d0a3810 480 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 481 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 482 addByteToMidiBuffer(midiEventVelocity);
popcornell 0:244f1d0a3810 483 sendMidi(3);
popcornell 0:244f1d0a3810 484 resetMidiBuffer();
popcornell 0:244f1d0a3810 485 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 486 break;
popcornell 0:244f1d0a3810 487 case 0xe0: // pitch bend
popcornell 0:244f1d0a3810 488 midiEventVelocity = midiEvent;
popcornell 0:244f1d0a3810 489 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 490 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 491 addByteToMidiBuffer(midiEventVelocity);
popcornell 0:244f1d0a3810 492 sendMidi(3);
popcornell 0:244f1d0a3810 493 resetMidiBuffer();
popcornell 0:244f1d0a3810 494 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 495 break;
popcornell 0:244f1d0a3810 496 case 0xf0: // Song Position Pointer.
popcornell 0:244f1d0a3810 497 midiEventVelocity = midiEvent;
popcornell 0:244f1d0a3810 498 addByteToMidiBuffer(midiEventKind);
popcornell 0:244f1d0a3810 499 addByteToMidiBuffer(midiEventNote);
popcornell 0:244f1d0a3810 500 addByteToMidiBuffer(midiEventVelocity);
popcornell 0:244f1d0a3810 501 sendMidi(3);
popcornell 0:244f1d0a3810 502 resetMidiBuffer();
popcornell 0:244f1d0a3810 503 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 504 break;
popcornell 0:244f1d0a3810 505 default:
popcornell 0:244f1d0a3810 506 // illegal state
popcornell 0:244f1d0a3810 507 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 508 break;
popcornell 0:244f1d0a3810 509 }
popcornell 0:244f1d0a3810 510 }
popcornell 0:244f1d0a3810 511 else if (midiState == MIDI_STATE_SIGNAL_SYSEX)
popcornell 0:244f1d0a3810 512 {
popcornell 0:244f1d0a3810 513 if (midiEvent == 0xf7)
popcornell 0:244f1d0a3810 514 {
popcornell 0:244f1d0a3810 515 uint8_t repEvt = replaceLastByteInSysExBuffer(midiEvent);
popcornell 0:244f1d0a3810 516
popcornell 0:244f1d0a3810 517 resetRecoveryBuffer();
popcornell 0:244f1d0a3810 518 createSysExRecovery();
popcornell 0:244f1d0a3810 519 replaceLastByteInRecoveryBuffer(repEvt);
popcornell 0:244f1d0a3810 520 addByteToRecoveryBuffer(midiEvent);
popcornell 0:244f1d0a3810 521 sendSysex();
popcornell 0:244f1d0a3810 522 resetSysExBuffer();
popcornell 0:244f1d0a3810 523 midiState = MIDI_STATE_TIMESTAMP;
popcornell 0:244f1d0a3810 524 }
popcornell 0:244f1d0a3810 525 else
popcornell 0:244f1d0a3810 526 {
popcornell 0:244f1d0a3810 527 addByteToSysExBuffer(midiEvent);
popcornell 0:244f1d0a3810 528 }
popcornell 0:244f1d0a3810 529
popcornell 0:244f1d0a3810 530 }
popcornell 0:244f1d0a3810 531 }
popcornell 0:244f1d0a3810 532
popcornell 0:244f1d0a3810 533
popcornell 0:244f1d0a3810 534 #endif /* defined(____BLEParser__) */