Merge pull request #32 from RobertoHE/patch-1

Added runningStatus continuation in receive()
This commit is contained in:
lathoub 2021-08-04 17:18:57 +02:00 committed by GitHub
commit 2f48b0f25b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 130 additions and 40 deletions

View File

@ -29,6 +29,9 @@ void receive(byte* buffer, size_t length)
// lastStatus used to capture runningStatus // lastStatus used to capture runningStatus
byte lastStatus; byte lastStatus;
// previousStatus used to continue a runningStatus interrupted by a timeStamp or a System Message.
byte previousStatus = 0x00;
byte headerByte = buffer[lPtr++]; byte headerByte = buffer[lPtr++];
// auto signatureIs1 = CHECK_BIT(headerByte, 7 - 1); // auto signatureIs1 = CHECK_BIT(headerByte, 7 - 1);
@ -39,6 +42,8 @@ void receive(byte* buffer, size_t length)
uint16_t timestamp = 0; uint16_t timestamp = 0;
bool sysExContinuation = false; bool sysExContinuation = false;
bool runningStatusContinuation = false;
if (timestampByte >= 80) { if (timestampByte >= 80) {
auto timestampLow = 0x7f & timestampByte; auto timestampLow = 0x7f & timestampByte;
@ -54,30 +59,38 @@ void receive(byte* buffer, size_t length)
{ {
lastStatus = buffer[lPtr]; lastStatus = buffer[lPtr];
if ((buffer[lPtr] < 0x80) && !sysExContinuation) if(previousStatus==0x00){
return; // Status message not present, bail if ((lastStatus < 0x80) && !sysExContinuation)
return; // Status message not present and it is not a runningStatus continuation, bail
}else if(lastStatus < 0x80)
{
lastStatus = previousStatus;
runningStatusContinuation = true;
}
// Point to next non-data byte // Point to next non-data byte
rPtr = lPtr; rPtr = lPtr;
while ((buffer[rPtr + 1] < 0x80) && (rPtr < (length - 1))) while ((buffer[rPtr + 1] < 0x80) && (rPtr < (length - 1)))
rPtr++; rPtr++;
if(!runningStatusContinuation){
// look at l and r pointers and decode by size. // look at l and r pointers and decode by size.
if (rPtr - lPtr < 1) { if (rPtr - lPtr < 1) {
// Time code or system // Time code or system or "2 bytes" running Message
transmitMIDIonDIN(lastStatus, 0, 0); transmitMIDIonDIN(buffer[lPtr], 0, 0);
} }
else if (rPtr - lPtr < 2) { else if (rPtr - lPtr < 2) {
transmitMIDIonDIN(lastStatus, buffer[lPtr + 1], 0); transmitMIDIonDIN(buffer[lPtr], buffer[lPtr + 1], 0);
} }
else if (rPtr - lPtr < 3) { else if (rPtr - lPtr < 3) {
transmitMIDIonDIN(lastStatus, buffer[lPtr + 1], buffer[lPtr + 2]); transmitMIDIonDIN(buffer[lPtr], buffer[lPtr + 1], buffer[lPtr + 2]);
} }
else { else {
// Too much data // Too much data
// If not System Common or System Real-Time, send it as running status // If not System Common or System Real-Time, send it as running status
auto midiType = buffer[lPtr] & 0xF0; auto midiType = lastStatus & 0xF0;
if (sysExContinuation) if (sysExContinuation)
midiType = 0xF0; midiType = 0xF0;
@ -111,10 +124,48 @@ void receive(byte* buffer, size_t length)
break; break;
} }
} }
}else
{
auto midiType = lastStatus & 0xF0;
if (sysExContinuation)
midiType = 0xF0;
switch (midiType)
{
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
//3 bytes full Midi -> 2 bytes runningStatus
for (auto i = lPtr; i <= rPtr; i = i + 2)
{
transmitMIDIonDIN(lastStatus, buffer[i], buffer[i + 1]);
}
break;
case 0xC0:
case 0xD0:
//2 bytes full Midi -> 1 byte runningStatus
for (auto i = lPtr; i <= rPtr; i = i + 1)
{
transmitMIDIonDIN(lastStatus, buffer[i], 0);
}
break;
default:
break;
}
runningStatusContinuation = false;
}
if (++rPtr >= length) if (++rPtr >= length)
return; // end of packet return; // end of packet
if(lastStatus < 0xf0) //exclude System Message. They must not be RunningStatus
{
previousStatus = lastStatus;
}
timestampByte = buffer[rPtr++]; timestampByte = buffer[rPtr++];
if (timestampByte >= 80) // is bit 7 set? if (timestampByte >= 80) // is bit 7 set?
{ {
@ -203,16 +254,55 @@ int main()
receive(blePacketWithThreeMIDIMessage, sizeof(blePacketWithThreeMIDIMessage)); receive(blePacketWithThreeMIDIMessage, sizeof(blePacketWithThreeMIDIMessage));
// std::cout << std::endl << "2 MIDI messages with running status" << std::endl; std::cout << std::endl << "2 MIDI messages with multiple running status" << std::endl;
// TODO byte twoMIDIMessageWithRunningStatus[] = { 0xA9, 0xAD,
0xD1, 0x74, //Full Midi 2 bytes(afterTouch)
0x73, //running
0xAE, //timeStamp
0x72, //running after timeStamp
0xAF, //timeStamp
0x71, //running after timeStamp
0x70,
0x69,
0x68,
0xB2, //
0x92, 0x36, 0x70, //Full Midi 3 bytes (noteOn)
0xB3, //
0x93, 0x37, 0x71,
0x38, 0x72,
0x39, 0x73,
0xB4, //
0x40, 0x74
};
receive(twoMIDIMessageWithRunningStatus, sizeof(twoMIDIMessageWithRunningStatus));
// byte twoMIDIMessageWithRunningStatus[] = { 0xA9, 0xAE, 0xD1, 0x74, 0xAF, 0xD2, 0x74, 0xB1 };
// receive(twoMIDIMessageWithRunningStatus, sizeof(twoMIDIMessageWithRunningStatus));
// std::cout << std::endl << "2 MIDI messages with running status" << std::endl; std::cout << std::endl << "2 MIDI messages with multiple running status and a System message in middle" << std::endl;
//
// byte multipleMIDIMessagesMixedType[] = { 0x00 };
// receive(multipleMIDIMessagesMixedType, sizeof(multipleMIDIMessagesMixedType));
byte twoMIDIMessageWithRunningStatusPlusSys[] = { 0xA9, 0xAD,
0xD1, 0x74, //Full Midi 2 bytes(afterTouch)
0x73, //running
0xAE, //timeStamp
0x72, //running after timeStamp
0xAF, //timeStamp
0x71, //running after timeStamp
0x70,
0x69,
0x68,
0xB2, //
0xFA, // <- Sys START
0xB2,
0x92, 0x36, 0x70, //Full Midi 3 bytes (noteOn)
0xB3, //
0x93, 0x37, 0x71,
0x38, 0x72,
0xB3, //
0xFC, // <- Sys STOP
0xB3,
0x39, 0x73,
0xB4, //
0x40, 0x74
};
receive(twoMIDIMessageWithRunningStatusPlusSys, sizeof(twoMIDIMessageWithRunningStatusPlusSys));
} }