added support for running Status
This commit is contained in:
parent
42cd91d79b
commit
f80e225080
142
src/BLE-MIDI.h
142
src/BLE-MIDI.h
|
|
@ -106,148 +106,6 @@ public:
|
||||||
public:
|
public:
|
||||||
QueueHandle_t mRxQueue;
|
QueueHandle_t mRxQueue;
|
||||||
|
|
||||||
/*
|
|
||||||
The general form of a MIDI message follows:
|
|
||||||
n-byte MIDI Message
|
|
||||||
Byte 0 MIDI message Status byte, Bit 7 is Set to 1.
|
|
||||||
Bytes 1 to n-1 MIDI message Data bytes, if n > 1. Bit 7 is Set to 0
|
|
||||||
There are two types of MIDI messages that can appear in a single packet: full MIDI messages and
|
|
||||||
Running Status MIDI messages. Each is encoded differently.
|
|
||||||
A full MIDI message is simply the MIDI message with the Status byte included.
|
|
||||||
A Running Status MIDI message is a MIDI message with the Status byte omitted. Running Status
|
|
||||||
MIDI messages may only be placed in the data stream if the following criteria are met:
|
|
||||||
1. The original MIDI message is 2 bytes or greater and is not a System Common or System
|
|
||||||
Real-Time message.
|
|
||||||
2. The omitted Status byte matches the most recently preceding full MIDI message’s Status
|
|
||||||
byte within the same BLE packet.
|
|
||||||
In addition, the following rules apply with respect to Running Status:
|
|
||||||
1. A Running Status MIDI message is allowed within the packet after at least one full MIDI
|
|
||||||
message.
|
|
||||||
2. Every MIDI Status byte must be preceded by a timestamp byte. Running Status MIDI
|
|
||||||
messages may be preceded by a timestamp byte. If a Running Status MIDI message is not
|
|
||||||
preceded by a timestamp byte, the timestamp byte of the most recently preceding message
|
|
||||||
in the same packet is used.
|
|
||||||
3. System Common and System Real-Time messages do not cancel Running Status if
|
|
||||||
interspersed between Running Status MIDI messages. However, a timestamp byte must
|
|
||||||
precede the Running Status MIDI message that follows.
|
|
||||||
4. The end of a BLE packet does cancel Running Status.
|
|
||||||
In the MIDI 1.0 protocol, System Real-Time messages can be sent at any time and may be
|
|
||||||
inserted anywhere in a MIDI data stream, including between Status and Data bytes of any other
|
|
||||||
MIDI messages. In the MIDI BLE protocol, the System Real-Time messages must be deinterleaved
|
|
||||||
from other messages – except for System Exclusive messages.
|
|
||||||
*/
|
|
||||||
void receive(byte* buffer, size_t bufferSize)
|
|
||||||
{
|
|
||||||
size_t index = 0;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
N_DEBUG_PRINT("Received (");
|
|
||||||
N_DEBUG_PRINT(bufferSize);
|
|
||||||
N_DEBUG_PRINTLN(") :");
|
|
||||||
for (int j = 0; j < bufferSize; j++) {
|
|
||||||
N_DEBUG_PRINT("0x");
|
|
||||||
N_DEBUG_PRINT(buffer[j], HEX);
|
|
||||||
N_DEBUG_PRINT(" ");
|
|
||||||
}
|
|
||||||
N_DEBUG_PRINTLN();
|
|
||||||
N_DEBUG_PRINTLN();
|
|
||||||
|
|
||||||
// Pointers used to search through payload.
|
|
||||||
uint8_t lPtr = 0;
|
|
||||||
uint8_t rPtr = 0;
|
|
||||||
|
|
||||||
// lastStatus used to capture runningStatus
|
|
||||||
uint8_t lastStatus;
|
|
||||||
|
|
||||||
// Decode first packet -- SHALL be "Full MIDI message"
|
|
||||||
lPtr = 2; //Start at first MIDI status -- SHALL be "MIDI status"
|
|
||||||
|
|
||||||
// While statement contains incrementing pointers and breaks when buffer size exceeded.
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
lastStatus = buffer[lPtr];
|
|
||||||
if( (buffer[lPtr] < 0x80) )
|
|
||||||
break; // Status message not present, bail
|
|
||||||
|
|
||||||
// Point to next non-data byte
|
|
||||||
rPtr = lPtr;
|
|
||||||
while ((buffer[rPtr + 1] < 0x80)
|
|
||||||
&& (rPtr < (bufferSize - 1)) )
|
|
||||||
rPtr++;
|
|
||||||
|
|
||||||
// look at l and r pointers and decode by size.
|
|
||||||
if( rPtr - lPtr < 1 )
|
|
||||||
{
|
|
||||||
mRxBuffer[i++] = lastStatus;
|
|
||||||
}
|
|
||||||
else if( rPtr - lPtr < 2 ) {
|
|
||||||
mRxBuffer[i++] = lastStatus;
|
|
||||||
mRxBuffer[i++] = buffer[lPtr + 1];
|
|
||||||
}
|
|
||||||
else if( rPtr - lPtr < 3 ) {
|
|
||||||
mRxBuffer[i++] = lastStatus;
|
|
||||||
mRxBuffer[i++] = buffer[lPtr + 1];
|
|
||||||
mRxBuffer[i++] = buffer[lPtr + 2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* //Too much data
|
|
||||||
//If not System Common or System Real-Time, send it as running status
|
|
||||||
switch( buffer[lPtr] & 0xF0 )
|
|
||||||
{
|
|
||||||
case NoteOff:
|
|
||||||
case NoteOn:
|
|
||||||
case AfterTouchPoly:
|
|
||||||
case ControlChange:
|
|
||||||
case PitchBend:
|
|
||||||
for(int i = lPtr; i < rPtr; i = i + 2)
|
|
||||||
sendMIDI(lastStatus, buffer[i + 1], buffer[i + 2]);
|
|
||||||
break;
|
|
||||||
case ProgramChange:
|
|
||||||
case AfterTouchChannel:
|
|
||||||
for(int i = lPtr; i < rPtr; i = i + 1)
|
|
||||||
sendMIDI(lastStatus, buffer[i + 1]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// Point to next status
|
|
||||||
lPtr = rPtr + 2;
|
|
||||||
|
|
||||||
if (lPtr >= bufferSize)
|
|
||||||
break; //end of packet
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reverse(mRxBuffer, i);
|
|
||||||
|
|
||||||
N_DEBUG_PRINT("mRxBuffer (");
|
|
||||||
N_DEBUG_PRINT(i);
|
|
||||||
N_DEBUG_PRINTLN(") :");
|
|
||||||
for (int j = 0; j < i; j++) {
|
|
||||||
N_DEBUG_PRINT("0x");
|
|
||||||
N_DEBUG_PRINT(mRxBuffer[j], HEX);
|
|
||||||
N_DEBUG_PRINT(" ");
|
|
||||||
}
|
|
||||||
N_DEBUG_PRINTLN();
|
|
||||||
N_DEBUG_PRINTLN();
|
|
||||||
|
|
||||||
mRxIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*
|
/*
|
||||||
The first byte of all BLE packets must be a header byte. This is followed by timestamp bytes and MIDI messages.
|
The first byte of all BLE packets must be a header byte. This is followed by timestamp bytes and MIDI messages.
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,36 @@ public:
|
||||||
_characteristic->notify();
|
_characteristic->notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The general form of a MIDI message follows:
|
||||||
|
n-byte MIDI Message
|
||||||
|
Byte 0 MIDI message Status byte, Bit 7 is Set to 1.
|
||||||
|
Bytes 1 to n-1 MIDI message Data bytes, if n > 1. Bit 7 is Set to 0
|
||||||
|
There are two types of MIDI messages that can appear in a single packet: full MIDI messages and
|
||||||
|
Running Status MIDI messages. Each is encoded differently.
|
||||||
|
A full MIDI message is simply the MIDI message with the Status byte included.
|
||||||
|
A Running Status MIDI message is a MIDI message with the Status byte omitted. Running Status
|
||||||
|
MIDI messages may only be placed in the data stream if the following criteria are met:
|
||||||
|
1. The original MIDI message is 2 bytes or greater and is not a System Common or System
|
||||||
|
Real-Time message.
|
||||||
|
2. The omitted Status byte matches the most recently preceding full MIDI message’s Status
|
||||||
|
byte within the same BLE packet.
|
||||||
|
In addition, the following rules apply with respect to Running Status:
|
||||||
|
1. A Running Status MIDI message is allowed within the packet after at least one full MIDI
|
||||||
|
message.
|
||||||
|
2. Every MIDI Status byte must be preceded by a timestamp byte. Running Status MIDI
|
||||||
|
messages may be preceded by a timestamp byte. If a Running Status MIDI message is not
|
||||||
|
preceded by a timestamp byte, the timestamp byte of the most recently preceding message
|
||||||
|
in the same packet is used.
|
||||||
|
3. System Common and System Real-Time messages do not cancel Running Status if
|
||||||
|
interspersed between Running Status MIDI messages. However, a timestamp byte must
|
||||||
|
precede the Running Status MIDI message that follows.
|
||||||
|
4. The end of a BLE packet does cancel Running Status.
|
||||||
|
In the MIDI 1.0 protocol, System Real-Time messages can be sent at any time and may be
|
||||||
|
inserted anywhere in a MIDI data stream, including between Status and Data bytes of any other
|
||||||
|
MIDI messages. In the MIDI BLE protocol, the System Real-Time messages must be deinterleaved
|
||||||
|
from other messages – except for System Exclusive messages.
|
||||||
|
*/
|
||||||
void receive(uint8_t* buffer, size_t length)
|
void receive(uint8_t* buffer, size_t length)
|
||||||
{
|
{
|
||||||
// Pointers used to search through payload.
|
// Pointers used to search through payload.
|
||||||
|
|
@ -75,13 +105,20 @@ public:
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
case 0xB0:
|
case 0xB0:
|
||||||
case 0xE0:
|
case 0xE0:
|
||||||
// for (auto i = lPtr; i < rPtr; i = i + 2)
|
for (auto i = lPtr; i < rPtr; i = i + 2)
|
||||||
// transmitMIDIonDIN( lastStatus, buffer[i + 1], buffer[i + 2] );
|
{
|
||||||
|
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i], portMAX_DELAY);
|
||||||
|
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i + 1], portMAX_DELAY);
|
||||||
|
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i + 2], portMAX_DELAY);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0xC0:
|
case 0xC0:
|
||||||
case 0xD0:
|
case 0xD0:
|
||||||
// for (auto i = lPtr; i < rPtr; i = i + 1)
|
for (auto i = lPtr; i < rPtr; i = i + 1)
|
||||||
// transmitMIDIonDIN( lastStatus, buffer[i + 1], 0 );
|
{
|
||||||
|
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i], portMAX_DELAY);
|
||||||
|
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i + 1], portMAX_DELAY);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr], portMAX_DELAY);
|
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr], portMAX_DELAY);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue