2015年1月21日水曜日

MIDI over Bluetooth LE library for Android

I've been developing the library to enable BLE MIDI feature on the Android devices from last year. The Apple Bluetooth Low Energy MIDI Specification(PDF) had revealed at December 2014. And finally, I implemented all of features on the specification.

Using this library, the app can connect with BLE MIDI devices, and BLE MIDI compatible iOS/Android/OS X apps. On the Android Lollipop, the app can act as BLE MIDI device.

Note:
This Apple's specification has not been approved by MIDI Manufacturers Association(MMA). I've asked about the specification to MMA at the past, but it was under discussion with MMA members.
The MMA's official release version's specification might be different from Apple's one.

The library's features

With this library, the Android can provide BLE MIDI Central / Peripheral features.

BLE MIDI Central feature

The Android app can host BLE MIDI devices. The app can receive MIDI messages from BLE MIDI devices, and send MIDI messages to them.
This feature requires Android KitKat(4.4 / API Level 19) or later.

BLE MIDI Peripheral feature

The Android app can pretend as BLE MIDI device. The application on the another machine(Android / iOS / OS X) can connect with the Android app.


BLE Peripheral feature is supported since Android Lollipop. So, this feature requires Android Lollipop(5.0 / API Level 21) or later.

Try the sample app

The sample app has been published on the Google Play market
The app can send Note On / Off MIDI events, and show received any MIDI events.

Connected with Miselu C.24 keyboard.

Tested Android devices and its stability

I tested the library with Nexus 7(2013) and Nexus 6. Both devices' Android version is Lollipop 5.0.1.
  • Nexus 7(2013)
    • It doesn't support BLE Peripheral feature.
    • Its BLE connection seems very unstable. Too frequently disconnection is occurring.
      • The unstableness might be due to the library's bug...? I'm trying to trace details.
  • Nexus 6
    • It can also work as BLE Central / Peripheral device.
    • It has better connection stability.

Explore the code

The repository is on the github. This repository includes the library and sample projects.
The master branch is the latest release version. The develop (or feature) branch is the latest working commits.

Currently, this library is not refined well. So, it might have many issues. If you found a bug, please report it on the github issue, or the email.

Using the library

Step by step instructions

Edit the app project's Gradle configuration

Open 'build.gradle' file at the root directory of project.
  1. Add an URL entry to 'repositories.maven' configuration.
  2. Then, add the dependency entry to 'dependencies' configuration.

Initialise the feature provider

There are two feature providers on the library, 'BleMidiCentralProvider' and 'BleMidiPeripheralProvider'.
At first, create the provider's field member on the app's Activity.

Terminate the feature provider

When the app's Activity will destroyed, the provider's 'terminate' method should be called.

Connecting with device

The provider has 'setOnMidiDeviceAttachedListener' method. Create 'OnMidiDeviceAttachedListener' instance and attach to the provider.

When the new device detected, the listener methods 'onMidiInputDeviceAttached' or 'onMidiOutputDeviceAttached' will be invoked.

Disconnecting with device

The provider can attach 'OnMidiDeviceDetachedListener' instance with 'setOnMidiDeviceDetachedListener' method. When the device has been disconnected, the 'onMidiInputDeviceDetached' or 'onMidiOutputDeviceDetached' method will be invoked.

If you want to disconnect the device from user interaction, call the provider's 'disconnectDevice' method. This will disconnect the device, and also invokes the 'OnMidiDeviceDetachedListener' methods.

Sending MIDI events

The provider holds the all connected device instances. With calling the 'getMidiOutputDevices' method, the app can obtain the set of 'MidiOutputDevice'.
The 'MidiOutputDevice' instance has methods for MIDI sending, such as 'sendMidiNoteOn' method.


Receiving MIDI events

At first, implement 'OnMidiInputEventListener'. This interface class includes all methods for MIDI event specified events, such as 'onMidiNoteOn' method.
The methods' first argument is the 'MidiInputDevice' instance, so the Activity holds only one 'OnMidiInputListener' instance.

Then, attach the 'OnMidiInputEventListener' instance to the 'MidiInputDevice'. When the app received the MIDI event, the corresponding method will be called.

Note:

The all of listners' method will be invoked from out of the UI thread, so the app shall use 'Handler' if it want to change UI widgets.