Android 6.0(Mashmallow)API Level 23から、MIDI機器を制御できるAPIが追加されたので試してみました。
■ 準備するもの
- Android SDKとAndroid StudioをインストールしたPC
- Android 6.0をインストールした端末
- USB接続可能なMIDI機器
- Android端末とMIDI機器を接続するUSBケーブル(USB B-A + A-microB など)
必要なものが準備できたら、以下の手順でAndroid端末とMIDI機器をセットアップします。
接続の順番を間違えると、WiFi越しのadb接続が切れたり、MIDI側がAndroid端末を認識しなかったりする可能性があります。
■ Android端末をセットアップする
- あらかじめPC上でAndroid Studioを起動しておく(あとでadbがrestartされないように)
- Android端末とPCをUSBでつなぎ(通常どおりMTP)接続する
- Android端末をWiFiネットワークに接続する
- 「adb tcpip 5555」「adb connect IPアドレス:5555」でWiFi下でadbを使用できるようにする
- 「adb device」でWiFiのIPに接続された事を確認する
- Android端末とPC間のUSBケーブルを外す(いったんadbは切れる)
■ MIDI機器をセットアップする
- MIDI機器の電源をオンし、起動時の入力をUSBにして動作するように設定して電源オフ
- Android端末上で開発者向けオプションなどから「USB設定の選択=MIDI」に切り替える
- Android端末とMIDI機器をUSB接続してから、MIDI機器の電源をオン
- 再度「adb connect IPアドレス:5555」でWiFi経由で再接続する
セットアップ後は、Android Studio上で適当なプロジェクトを作成し、
以下の解説を参考に、MIDI機器を制御するアプリを作成します。
なお、minSdkVersionは23で作成してください。
■ MIDI APIを使用するには?
AndroidManifest.xmlへ以下を追加します。
<uses-feature android:name="android.software.midi" android:required="true"/>
■ MIDI機器の情報を取得するには?
システムサービスからMidiManagerを取得後、MidiManager#getDevices()を呼び出すと、
Android端末に接続されているMIDI機器の情報が、MidiDeviceInfoとして取得できます。
MidiDeviceInfoは、MidiDeviceInfo#getProperties()を呼び出すことで、
各種プロパティー情報にアクセスできます。
MidiManager midiManager = (MidiManager)getSystemService(Context.MIDI_SERVICE);
MidiDeviceInfo[] infos = midiManager.getDevices();
if (infos.length > 0)
{
MidiDeviceInfo info = infos[0]; // 説明用に先頭の情報のみアクセスしてます
Bundle prop = info.getProperties();
// 製造元文字列("Roland"など)
String manufacturer = prop.getString(MidiDeviceInfo.PROPERTY_MANUFACTURER);
// 製品名文字列("EDIROL SD-90"など)
String product = prop.getString(MidiDeviceInfo.PROPERTY_PRODUCT);
// 機器名文字列("Roland EDIROL SD-90"など)
String name = prop.getString(MidiDeviceInfo.PROPERTY_NAME);
// バージョン文字列("1.16"など)
String version = prop.getString(MidiDeviceInfo.PROPERTY_VERSION);
// MIDI機器とUSB接続している場合のみインスタンスが取得できる
UsbDevice usbDevice = (UsbDevice) prop.get(MidiDeviceInfo.PROPERTY_USB_DEVICE);
// MIDI機器とBluetooth接続している場合のみインスタンスが取得できる
BluetoothDevice btDevice = (BluetoothDevice) prop.get(MidiDeviceInfo.PROPERTY_BLUETOOTH_DEVICE);
// 入力ポート数(4など)
int numInputs = info.getInputPortCount();
// 出力ポート数(4など)
int numOutputs = info.getOutputPortCount();
}
■ MIDI機器の接続/切断/状態変化を知るには?
MidiManager#registerDeviceCallback()を呼び出し、MidiManager.DeviceCallbackインスタンスを登録することで、各種コールバックを受け取ることができます。
midiManager.registerDeviceCallback(new MidiManager.DeviceCallback() {
@Override
public void onDeviceAdded(MidiDeviceInfo device) {
super.onDeviceAdded(device);
// デバイスが接続された時に呼び出される
Toast.makeText(MainActivity.this, "onDeviceAdded()", Toast.LENGTH_SHORT).show();
}
@Override
public void onDeviceRemoved(MidiDeviceInfo device) {
super.onDeviceRemoved(device);
// デバイスが切断された時に呼び出される
Toast.makeText(MainActivity.this, "onDeviceRemoved()", Toast.LENGTH_SHORT).show();
}
@Override
public void onDeviceStatusChanged(MidiDeviceStatus status) {
super.onDeviceStatusChanged(status);
// デバイスが状態が変化した時に呼び出される
Toast.makeText(MainActivity.this, "onDeviceStatusChanged()", Toast.LENGTH_SHORT).show();
}
}, new Handler(Looper.getMainLooper())); // 第2引数
■ MIDI機器をオープンするには?
MidiManager#openDevice()を呼び出します。
第1引数には、上述したgetDevices()で取得した1つ分のMidiDeviceInfoをセットし、
第2引数には、MidiManager.OnDeviceOpenedListenerインスタンスをセットします。
midiManager.openDevice(info, new MidiManager.OnDeviceOpenedListener() {
@Override
public void onDeviceOpened(MidiDevice device) {
if (device == null) {
// オープン失敗
} else {
// オープン成功
// ...引数として渡された device インスタンスを使用してMIDI機器を制御する...
}
}
}
, new Handler(Looper.getMainLooper())); // 第3引数
■ MIDIメッセージを送るには?
オープンして取得したMidiDeviceインスタンスから入力ポートを取得後、
入力ポートに対してMIDIメッセージ(バイト配列)を送信します。
以下の例では、MIDI機器から「ぽーん♩」という感じの音が鳴なります。
MidiInputPort inputPort = device.openInputPort(0);
byte[] buffer = new byte[32];
int numBytes = 0;
int channel = 3; // MIDI channels 1-16 are encoded as 0-15.
buffer[numBytes++] = (byte)(0x90 + (channel - 1)); // note on
buffer[numBytes++] = (byte)60; // pitch is middle C
buffer[numBytes++] = (byte)127; // max velocity
int offset = 0;
try {
inputPort.send(buffer, offset, numBytes);
} catch (IOException e) {
e.printStackTrace();
}
ここまでで、Android端末とMIDI機器を接続し、MIDI機器を制御することができました。
さらなる情報は、公式サイトから得られますので、参考にしてみてください。
http://developer.android.com/reference/android/media/midi/package-summary.html
