Android 13のMIDI 2.0サポートについて

Android 13正式版がリリースされてAOSPにcode dropされたようです。

Android 13には興味深い新機能がいくつかあって、個人的にはLE Audioサポートの追加で音楽ソフトの体験が変わりそうなのとAndroid 12Lで追加された(主に)タブレット向けの複数Activity並列動作のサポートが気になるところですが、それらと並んでMIDI 2.0サポートが追加されたことがAndroid Developers Blogに書かれているので、これを少し解説します。

MIDI 2.0 - Android 13 adds support for the new MIDI 2.0 standard, including the ability to connect MIDI 2.0 hardware through USB. This updated standard offers features such as increased resolution for controllers, better support for non-Western intonation, and more expressive performance using per-note controllers. More here.

MIDI 2.0プロトコルサポートの概要

MIDI 2.0サポートに対応するAPIとしては、android.media.midi.MidiDeviceInfoに追加されたgetDefaultProtocol())メソッドのように、新しいMIDIプロトコル定数を利用するものがいくつか増えた程度で、Android 10で追加されたNative MIDI APIのような目新しさはない(小さい)です。

Android 13でMIDI 2.0サポートが追加されたのはUSB MIDI 2.0デバイスのサポートのみです。しかも「USBプロトコルでネイティブにMIDI 2.0サポートに対応したもの」だけが新規にサポートされたことになります。

MIDI 2.0はMIDI 1.0との後方互換性を強く意識して設計されています。その成果のひとつとして、MIDI 2.0のメッセージをあらわすUMPのパケットは、MIDI-CIとMIDI 2.0 Protocol Negotiationを利用することで、MIDI 1.0な接続環境でも送受信できるように接続を調整できます(これを実現するためには、仕様上は、送受信の双方向接続が確立される必要があります)。5-PINのMIDIケーブルでの接続まではカバーできないような話がMIDI 2.0仕様書には書かれていますが、USBやソフトウェアによる仮想MIDIバイスに関してはMIDI 1.0の接続さえあれば、そこにMIDI 2.0 UMPを流し込めるというわけです。

Android 13にはMIDI 2.0 UMPを「扱う・処理する」APIは存在しません。そもそもMIDI 1.0を扱う・処理するAPIAndroidには存在しません。MIDIメッセージもUMPストリームもただのバイト配列であり、こういうのはアプリケーションで趣味に合わせて都合の良いものを使えばよく、プラットフォームAPIとして存在する必要はありません。筆者もそういう意識でMIDI 2.0 UMPを扱うライブラリktmidiを作ってGitHubで公開しています。C++ならJUCEのUMPサポートを使うのもいいでしょう。

100%手前味噌なのですが、この辺は先月COSCUP 2022でも話してきた話であり、また1年ちょっと前に発行した同人誌「MIDI 2.0エコシステム構築術」でもまとめています。

xamaritans.booth.pm

ネイティブMIDI 2.0プロトコルバイスのサポート

今回Android 13でサポートされたのは、このMIDI-CIとProtocol NegotiationによるMIDI 2.0プロトコルへの昇格ではありません。これはAndroid 12以前でも利用できたものである、と考えてよいのです。実際、筆者は上記ktmidiプロジェクトの一環として作成した仮想MIDIキーボードアプリkmmkで、MIDI 2.0プロトコルに昇格して…した気分になって(Protocol Negotiationの応答処理をすっ飛ばして)…UMPを送りつけるモードを実装して、別途Android用のオーディオプラグインフレームワーク(自作)から作り出した仮想MIDIデバイスに実際に送りつけて音を出すところまで作ってみたことがあります(今はちょっとまともに動作しない状態になっているので言及するのもちょっとアレですが…)。

Android 13でサポートされるようになったのは、MIDI 2.0プロトコルネイティブな接続です。MIDI 1.0の頃は、MIDIプロトコルMIDI 1.0によるものだけでした。MIDI 2.0の時代になって、このUMPのみを送受信するMIDIバイスという概念が新たに発生することになりました。すなわち、MIDI-CIによるプロトコル昇格を経るまでもなく、最初からUMPでやり取りするデバイスがあり得る、ということです。

あるUSB-MIDIバイスが最初からMIDI 2.0プロトコルしかサポートしていないかどうかは、USB-MIDI 2.0デバイスであるかどうかをUSBプロトコルに則って得られる情報から判断できます。そしてその情報が、冒頭で言及したAndroid 13の新しいAPIであるMidiDeviceInfo.getDefaultProtocol()などで取得できるというわけです。

もうひとつ、MIDIアプリケーション開発者にとって重要な機能としては、MidiManager.getDevicesForTransport())というメソッドを使うと、MIDI 1.0あるいはMIDI 2.0専用のデバイスに限定してリストを返すことができます。

なお、android.media.midiのAPIリファレンスには、USB-MIDI 2.0をサポートするデバイスでも、MIDI 1.0プロトコルによる接続もサポートするべきである、と書かれています("A MIDI 2.0 USB device should create two interfaces, one endpoint that accepts only MIDI 1.0 packets and one that accepts only UMP packets.")。

また、Android 13のAPIで追加された定数は、MIDI 2.0プロトコルのいくつかのオプション(たとえばJRタイムスタンプを伴うか否か等)に関連するものですが、これらについてはMIDI 2.0 UMP仕様書の"3. MIDI Protocls in UMP format"などを参照してください。

MIDI 2.0ネイティブのサポートはUSB-MIDI 2.0デバイスのみ

この意味では、Android 13に追加されたMIDI 2.0サポートはUSB-MIDIに限定されたものであるように見えますが、実のところそのとおりになっています。USB-MIDIMIDI 2.0プロトコルネイティブなものを作成できるようになっているのであれば、仮想MIDIバイスでもそうなっていてほしいと考えるのは自然なことだと思いますが(!)、現状ではMIDI 2.0ネイティブなMidiDeviceServiceは作成できません

MidiDeviceInfoクラス経由でわれわれMIDIアプリケーション開発者が取得できる情報は、別のわれわれMIDIバイス開発者がdevice_info.xmlなどの「デバイスマニフェスト」で公開できる情報に含めることができる情報であり、ここに「MIDI 2.0プロトコルネイティブだよ」と記述すればOKとなってほしいところです。そう考えてGoogleissuetrackerにfeature requestを出したのですが、先送りになってしまいました。

理由はこのissueに書かれているのですが、もしデバイスマニフェストプロトコル情報を追加するだけで対応してしまうと、MIDI 2.0プロトコルネイティブのMidiDeviceServiceはMIDI 1.0と後方互換性が無いにもかかわらず、MIDI 1.0デバイスに接続するアプリケーションからも接続可能なデバイスとして列挙されてしまいます。これではユーザーがちゃんと使えるデバイスを利用できないことになるので、恐らく別のIntent Actionが必要になることでしょう。

そもそもUSB-MIDI 2.0対応デバイスは現状ほぼ存在しない

前述のCOSCUP 2022のセッションでも話した(スライドにも書いた)のですが、2022年8月の時点で、MIDI 2.0に対応したMIDIキーボード等のMIDIバイスはほぼ何も存在しません。開発用の基板のようなものを作って売っている会社はあるようだ、というレベルです。MIDI 1.0インターフェース上でMIDI-CIのプロトコル昇格を利用してUMPをサポートするほうが現実的なので、MIDI 2.0ネイティブのデバイスというものがリリースされ、サポートされないと困る…!とまで言えるようになるのは、近くない将来のことになるでしょう。

そういうわけで、Android 13のMIDI 2.0対応は、現状ではほぼ無視してよいレベルであるといえます(断言)。一方で、USB-MIDI 2.0仕様はもう確定していて変わらないので、Android 13の現時点でUSB-MIDI 2.0に対応できているというのは良いことだといえます。MIDI 2.0ネイティブデバイスの普及期にはAndroid 13が普及機で動作しているというのが理想的な状態です。

MIDI 2.0サポートに向けてとるべき対応

われわれMidiDeviceServiceの開発者がMIDI 2.0に対応するには、ソフトウェアレベルでMIDI-CIのプロトコル昇格に対応してUMPを処理できるようにすることです。これをしっかり実装しようと思うと、それなりのMIDI-CI基盤を構築しなければならず、これは少し骨の折れる作業になるので(送受信のcorrelationが必要になる)、Androidオーディオチームではこの目的でみんなが使えるMIDI-CI実装を開発して公開するつもりであるようです…と先のissueでコメントされています。コメントしているのはAndroidオーディオチームのリーダー(Oboeの開発者でもある)なので、それなりの確度で出てくることでしょう。

MIDI 2.0をサポートするDAWなどのアプリケーションもまだまだAndroidでは存在していないので(完全にchicken and eggの問題)、われわれが「MIDI 2.0をサポートしてほしい」という機能要望を見るようになるまでにはしばらくかかることでしょう。その間にAndroidオーディオチームがMIDI-CI対応ライブラリやAPIを出してきたら、そこから対応を始めるくらいでも十分ではなかろうかと思います(個人的には自分でMIDI-CI対応機能を作ってしまうと思いますが)。