diff options
-rw-r--r-- | media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java index ea95a01c1f78..c51c8fa73c4e 100644 --- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java +++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java @@ -22,24 +22,41 @@ import android.util.Log; import java.io.IOException; /** - * This is an abstract base class that decodes a packet buffer and passes it to a - * {@link android.media.midi.MidiReceiver} + * This is an abstract base class that decodes a BLE-MIDI packet + * buffer and passes it to a {@link android.media.midi.MidiReceiver} */ public class BluetoothPacketDecoder extends PacketDecoder { private static final String TAG = "BluetoothPacketDecoder"; private final byte[] mBuffer; + private int mBytesInBuffer; private MidiBtleTimeTracker mTimeTracker; - private final int TIMESTAMP_MASK_HIGH = 0x1F80; - private final int TIMESTAMP_MASK_LOW = 0x7F; - private final int HEADER_TIMESTAMP_MASK = 0x3F; + private int mLowTimestamp; + private long mNanoTimestamp; + + private static final int TIMESTAMP_MASK_HIGH = 0x1F80; // top 7 bits + private static final int TIMESTAMP_MASK_LOW = 0x7F; // bottom 7 bits + private static final int HEADER_TIMESTAMP_MASK = 0x3F; // bottom 6 bits public BluetoothPacketDecoder(int maxPacketSize) { mBuffer = new byte[maxPacketSize]; } + private void flushOutput(MidiReceiver receiver) { + if (mBytesInBuffer > 0) { + try { + receiver.send(mBuffer, 0, mBytesInBuffer, mNanoTimestamp); + } catch (IOException e) { + // ??? + } + mBytesInBuffer = 0; + } + } + + // NOTE: this code allows running status across packets, + // although the specification does not allow that. @Override public void decodePacket(byte[] buffer, MidiReceiver receiver) { if (mTimeTracker == null) { @@ -47,14 +64,11 @@ public class BluetoothPacketDecoder extends PacketDecoder { } int length = buffer.length; - - // NOTE his code allows running status across packets, - // although the specification does not allow that. - if (length < 1) { Log.e(TAG, "empty packet"); return; } + byte header = buffer[0]; if ((header & 0xC0) != 0x80) { Log.e(TAG, "packet does not start with header"); @@ -64,52 +78,46 @@ public class BluetoothPacketDecoder extends PacketDecoder { // shift bits 0 - 5 to bits 7 - 12 int highTimestamp = (header & HEADER_TIMESTAMP_MASK) << 7; boolean lastWasTimestamp = false; - int dataCount = 0; int previousLowTimestamp = 0; - long nanoTimestamp = 0; - int currentTimestamp = 0; + int currentTimestamp = highTimestamp | mLowTimestamp; - // iterate through the rest of the packet, separating MIDI data from timestamps + // Iterate through the rest of the packet, separating MIDI data from timestamps. for (int i = 1; i < buffer.length; i++) { byte b = buffer[i]; + // Is this a timestamp byte? if ((b & 0x80) != 0 && !lastWasTimestamp) { lastWasTimestamp = true; - int lowTimestamp = b & TIMESTAMP_MASK_LOW; - if (lowTimestamp < previousLowTimestamp) { + mLowTimestamp = b & TIMESTAMP_MASK_LOW; + + // If the low timestamp byte wraps within the packet then + // increment the high timestamp byte. + if (mLowTimestamp < previousLowTimestamp) { highTimestamp = (highTimestamp + 0x0080) & TIMESTAMP_MASK_HIGH; } - previousLowTimestamp = lowTimestamp; + previousLowTimestamp = mLowTimestamp; - int newTimestamp = highTimestamp | lowTimestamp; + // If the timestamp advances then send any pending data. + int newTimestamp = highTimestamp | mLowTimestamp; if (newTimestamp != currentTimestamp) { - if (dataCount > 0) { - // send previous message separately since it has a different timestamp - try { - receiver.send(mBuffer, 0, dataCount, nanoTimestamp); - } catch (IOException e) { - // ??? - } - dataCount = 0; - } + // Send previous message separately since it has a different timestamp. + flushOutput(receiver); currentTimestamp = newTimestamp; } - // calculate nanoTimestamp + // Calculate MIDI nanosecond timestamp from BLE timestamp. long now = System.nanoTime(); - nanoTimestamp = mTimeTracker.convertTimestampToNanotime(currentTimestamp, now); + mNanoTimestamp = mTimeTracker.convertTimestampToNanotime(currentTimestamp, now); } else { lastWasTimestamp = false; - mBuffer[dataCount++] = b; + // Flush if full before adding more data. + if (mBytesInBuffer == mBuffer.length) { + flushOutput(receiver); + } + mBuffer[mBytesInBuffer++] = b; } } - if (dataCount > 0) { - try { - receiver.send(mBuffer, 0, dataCount, nanoTimestamp); - } catch (IOException e) { - // ??? - } - } + flushOutput(receiver); } } |