先月ちらっと書いたのですが、今月はAndroidオーディオプラグインの抜本的な仕切り直しを計画していました。
今年は完全個人プロジェクトを卒業して他の人にも使ってもらえるようなところまで持っていきたいという気持ちがあります。去年も1人で続けていましたが、だんだん個人の開発リソースでは足りない/主要な開発作業が進められなくなりつつあります(LV2とJUCEのプラグイン移植をAAPの最新版に追従させるだけでもそれなりの仕事になるのです)。Androidオーディオアプリの開発者の人たち(希少種!)からたまに「手伝えることがあれば言ってくれ」と言ってもらえてありがたいのですが、他人を巻き込むためには、既存コードはあまりにもスパゲッティすぎるのと設計がぐちゃぐちゃなのと、だんだん開発を進めるうえでブレーキになりつつあったので、一度やっておくべきと思った次第です。
仕切り直しを「計画していた」と過去形になっているのは、とりあえず現時点ではプラグインフレームワークとしての互換性が維持された範囲でリファクタリングを行っているためです。一番過激な仕切り直し構想では、新規リポジトリ(未公開)にGUI統合なども考慮した新しいモジュール構造を作って既存コードをビルドできるところまでやっていました。ただこれは現在リファクタリング中のソースコードと大きく乖離してしまっていて、再利用されることはないでしょう。
AudioPluginMidiDeviceServiceの安定化
AAPをオーディオプラグインAPIとして他の人に使ってもらえるようにするには、APIがまだまだ安定しませんし、実のところリアルタイムで安定的に使えるほど実装の品質も良くありません。そういう現状でAAPを使ってもらえるようにするには、現状2つの方向性があると思っています。
- 仮想MIDIデバイスとして利用できるようにする: これならAndroid MIDI APIの範囲でしかいじられないので、APIの安定性を気にする必要がほぼありません。できればプリセットまでサポートしたいところです。
- サンプラー等で静的にエフェクトをかけられるようにする: リアルタイムで厳しくても静的なら問題ないだろうし、それでも一定の需要はあるだろうという考えです。基本的なAPI安定性が必要になるのと、UI無しでどこまで利用可能性があるのかやや未知数なことがあります(これもプリセット次第かもしれない)。GuitarMLみたいにモバイルでのリアルタイム利用が現実的でなさそうな分野では有用かもしれません(まだ移植したことがない)。
ただ、MIDIDeviceServiceの実装が、1月時点では非常に不安定で、「他のMIDIデバイスに切り替えたら落ちる」「2回インスタンス生成したら落ちる」みたいなレベルだったので、コードの改善が急務でした。現在ではこれらの問題は解決していますが、それはネイティブコードにそれなりに抜本的に手を加えて実現したものです。
ネイティブ実装まわりはしばらく真面目にデバッグする必要がなかったこともあって、開発体験が非常に悪かったのですが(NDKとAndroid Studioの完成度に大きく依存するし…!)、今はデバッグビルド用にAddressSanitizerなどを利用しやすく整備したので、少なくともそこでやる気をフルブーストする必要はなくなりました。本当はAndroid NDKのバージョンをr21からr23に上げたかったのですがNdkBinderまわりのリグレッションに当たってしまい、修正されるまで棚上げです…
理想的な安定化が実現できたかというと、長大なリソースロード時間を要するプラグインなどがまだクラッシュする問題などがあって、他の人に「使ってくれ〜!!」と言うにはまだ片付けるべき作業があると思っています。(ただ先に後述の課題を片付けたいところ…)
aap-lv2-string-machine
去年は雨後の竹林のようにプラグイン移植のリポジトリを生やしていたものですが、今年はなるべく控えめにしようかな…と思っていました。が結局今月もひとつ作ってしまったり…(!?)
AAP-LV2の移植まわりで長らく問題になっているのがdragonfly-reverbの移植がまともに機能しない問題です。オーディオ処理した結果の波形がめちゃくちゃになったり音が何も聞こえなくなったり…。それで、まず問題を切り分ける目的で、dragonfly-reverbが使っているプラグイン開発フレームワークであるDPFを使った他のプラグインとしてstring-machineを移植してみました。2時間とかからずに移植できて問題なく動いたり…
そんなわけでDPFには問題がないことがわかったので、もう少し別の角度から検証が必要そうです。DPFのプラグインはビルドがMakefileなので、どうしてもandroid-native-audio-buildersでバイナリビルドせざるを得ず、Android Studioからデバッグどころかprintfデバッグすらできないのが難儀なところです…
AAP 2022 roadmap and design docs
今月の半ばに、2022年版の開発ロードマップを公開しました。実のところ半分くらい2021年版から引き継いでいますし、1年かけてこれを進めるとか、逆にこれ全部やるのに1年かける予定だとか、そういうものではないです。他にもやることあるだろうし。
designing new ports and parameters
これで、まずは地味だけど重要な部分として、プラグインのポートとパラメーター(現在存在しないコンセプト)から着手しようと思い、新しいポート設計の構想から練り直したのですが、すでにいくつかissueとして登録してあったのをまとめるだけで割としんどい作業でした。しかも1年以上ずっと残っていたり…
AAP開発当初は、オーディオプラグインのポートはとりあえずLV2と同じ方式にしておけば良いだろうと考えていました。オーディオプラグインのコードに手を出し始めたのも4年くらい前からだったと思います。それからそれなりに経験を積んで、プラグインのパラメーターは何百もあったりするからポートを何百も作るのではなくパラメーターとしてちゃんと作ったり、設定にはlv2:patchみたいな新しい仕組みでやり取りすべき、みたいなことが分かってきました(この知見自体LV2コミュニティでも割とモダンな知識)。
パラメーター変更を受け付ける手段は、デスクトップのオーディオプラグインフレームワークでもGUIを含むイベントメッセージングの統合部分で課題になります。AAPの場合は(長らく着手できていない)GUI統合がプロセスをまたぐこともあり、またAndroidのServiceとしてクライアント(GUI)から接続することを考えると、接続は1つだけど対象インスタンスもクライアントも複数あって…といったモデルを考えなければなりません。
そんなわけで新しく設計ドキュメントをまとめたわけですが、コレに着手する前にやることがある。そう…
ネイティブAPIの破壊的な整備
まずネイティブAPIがスパゲッティなのをどうにかしないと…となったわけです。スパゲッティになっていることにはいくつか歴史的な理由があるのですが、やはり去年まででいろいろプラグインを移植してみて分かってきたことが増えてきたのと、デスクトップとは根本的に設計が違うものを無理に合わせてきたことが積み上がってのことでしょう。これもとりあえず大掛かりな変更作業になりそうなので、先にドキュメントとしてまとめたのですが、長期的に残したい内容でもなかったのでissueで済ませています。
MIDIまわりのリファクタリングの際に、1年以上固定していたバージョン0.6.xを0.7.0に上げたところだったので、今のうちにいろいろ破壊的変更を加えてしまおうという気持ちでアグレッシブに手を加えています。ユーザーがいないうちにやってしまおうという感じです。あまりアグレッシブに変更すると自分でも大量の移植コードが追従できなくなるのでやりたくはないのですが、この辺はバランスですね…。この作業は現在進行形でmainにもマージされていないので、月を跨いで継続していく予定です。