CLAP 1.0公開を機にオーディオプラグイン規格の何たるかを知る (1)

5月に「CLAPオーディオプラグイン is 何?」という雑なLT(LTなので!)を行いました。このときは短時間だったので技術的な詳細には踏み込ませんでしたが、より多くの人が踏み込んで技術的に評価できるように、もう少し技術的な詳細に踏み込んだ解説があるべきでしょう。そういうわけで、新たにこの文章を起こすことにしました。わたし個人にはCLAPを普及させる理由はなく、CLAPの話をする理由はないので、オーディオプラグインフォーマット全般に関する話としてまとめています。まだ書きかけの残りが3/5くらいあるので、(1)としています。たぶん3回くらいになります。

この内容の一部は7/6に開催予定のオーディオプラグイン勉強会#1でも言及する予定です。短めの発表 + カジュアルな検討会にしようと思っているので、この分野に興味のある方はお気軽にどうぞ。

music-tech.connpass.com

概論

オーディオプラグインフォーマットの基本

CLAPは汎用オーディオプラグインフォーマットです。汎用オーディオプラグインフォーマットは、任意のDAWで任意のプラグインを利用できるようにするために作られる規格です。。オーディオプラグインは、プラグインフォーマットが規定するAPIを実装し、DAWは、プラグインフォーマットが規定するAPIの実装コードをバイナリプログラム(DLLなど)からロードします。

2022年現在、オーディオプラグインフォーマットは複数の規格が並立しています(次節で列挙します)が、基本的な機能は大きく違うものではありません。

  • 動的ライブラリに類するかたちでロードでき、複数のインスタンスを生成できる
  • ステレオ等のオーディオ入力とMIDI等のコントロール入力を「オーディオ処理」のサイクルで受け取って、オーディオ出力およびコントロール出力に変換する
  • 外部から操作でき、変更をGUIに通知できるfloatのパラメーターがある(その他の型をサポートすることもある)
  • MIDIなどの「イベント」を受け取ったり通知したりできる(オーディオ処理と連動するかしないかは規格による)
  • プラグインのパラメーター等を状態として保存・復元できる
  • メタデータとしてプラグイン名やベンダー名をもち、システム上に有るプラグインをリストアップできる
  • ホストDAWからサブウィンドウに表示できるGUIをもつ

これらだけであれば、素朴に設計するのも実装するのもそんなに難しくはありません。特にプラグインフォーマットとはAPIであって実装コードである必要はないので、宣言してしまえば大部分の仕事は終わりです。

もちろん、適当にAPIを作っただけではプラグインでもDAWでも対応してもらえないので、実際にプラグインフォーマットを定着させるためには、それ以上の仕事をすることになります。魅力的な追加機能を用意したり、それらが多数になっても一貫性を保てたり、簡単に実装できたり…といった設計の調整力が必要になります。

各種オーディオプラグインフォーマットの状況

オーディオプラグインフォーマットとしてはVST、AudioUnit、LV2といったものが存在します。どのフォーマットにもさまざまな長所・短所があります。

AppleのAudioUnit以外はデスクトップのクロスプラットフォーム(Win/Mac/Linux)用と考えて良いです(VSTLinuxをサポートするようになったのはだいぶ最近になってからではあります)。

この他、ProTools用のAAXなど、汎用ではなく特定のDAW専用のプラグインフォーマットで著名なものもいくつかあります。

VSTはVST2とVST3で大きく異なり、SteinbergはもうVST2のSDKを公開していないので、新規企業がVST2製品を公開することは無いと想定されていますが、古くからある製品のバージョンアップでは残り続けるでしょうし、VeSTigeやvst-rsのようなVST2SDK非依存の実装も存在しており、VST2ロゴ以外でSteinbergがライセンスクレームをつけることも出来ないので、急速にフェードアウトしていくことは無さそうです(現在でもVST2版のプラグインは各所でリリースされています)。

AppleのAUv2とAUv3は、VST2/VST3とは全く異なる位置付けです。AUv2は従来型のデスクトップ用プラグインで、DAWのプロセスでロードできるプラグインです。AUv3はiOSMac App Store用のプラグインで、セキュリティ上の要件からプロセス分離が要求され、これが最適なリアルタイム処理を妨げる制約となっています。

(LV2についてはこのエントリの最後にまとめる同人誌で詳しく書いており、この一連のエントリではあまりLV2に寄せすぎた話をしたくないので最低限の言及にとどめようと思います。)

新しいオーディオプラグインフォーマットのインパクト、サポート状況

一般的には、DAWがサポートするオーディオプラグインには、そのDAW固有のものと汎用的なものがあります。VSTも元々はSteinbergCubase用に作ったものでした。

DAWが新たに汎用的なフォーマットをサポートするには、その機能を(一部ではあっても意義がある程度には)サポートできる状態になっていなければなりません。プラグインフォーマットに含まれる機能に、あまり本質的ではない過剰な機能が搭載されていてもいけないわけです。

CLAPを現時点でサポートしているのは商用DAWではBitwig Studioのみで、これは主要な開発メンバーがBitwig社のメンバーだからという非常にストレートな理由です。OSSでCLAPをサポートしているものは存在しませんでしたが、6月末の時点でQTractorのmasterに実験的なCLAPサポートが追加されています。

オーディオプラグインフォーマットの設計ポイント

拡張性

オーディオプラグインの拡張性 (extensibility) とは、シンプルにいえば機能追加のための仕組みです。プラグイン規格に追加機能を持ち込むには、APIを拡張しなければなりません。これを無計画に行うと、後から「やっぱりこの機能はいらなかった」とか「やっぱりこのAPIだとイマイチだから仕切り直そう」と思っても、後方互換を全面的に破壊することになってしまいます。つまり、古いプラグインのコードが新しいプラグイン規格SDKのバージョンでビルドできなくなったりするわけです。

VST2がこの無計画なスタイルで開発されてきましたが(20世紀に作られた仕様であり、誰もがAPI後方互換性を強く意識するような時代ではありませんでした)、VST3ではこれが大きく変わりました。VST3ではコア機能と拡張機能を切り分けて、拡張機能WindowsのCOM技術におけるクエリインターフェースの仕組みで動的に取得するようになりました。もし拡張機能の一部でAPIの進化が行き詰まったとしても、それ以外の部分は後方互換のままで利用できることになります。これはVST-MA (module architecture) と呼ばれる仕組みです。詳しくはこちらの記事などを見て下さい。

qiita.com

よくVST3はVST2と比べて複雑だと言われますが、この拡張性に関する設計方針は、フレームワーク開発者の間では広く受け入れられていて、LV2でもCLAPでも同様の機構をCで実現しています。オーディオプラグイン規格以外でも、OpenSLなどにも見られます。

何をもってコア機能とし、何をもって拡張機能とするかは、これらモダンなプラグインフォーマットの間でも違いがあります。CLAPはだいぶアグレッシブに「拡張機能化」を実現していて、オーディオポートやコントロールポートの定義すらも全て拡張機能で実現しています。

プラグインの列挙に対応するメタデータ取得API

われわれDAWユーザーがオーディオプラグインを使うとき、最初にローカル環境にインストールされているプラグインのリストを取得する必要があるのが一般的です。リストには次のスクリーンショットのような内容が含まれます。

プラグインリスト (JUCE AudioPluginHost) VSTAUには、このリスト取得処理に時間がかかりすぎるという問題があります。

VSTの問題の原因は、プラグインのリストに含まれるべき情報が、プラグイン実際にプログラムとしてロードしてプラグインインスタンスを生成しないと取得できないことにあります。これがメタデータの含まれたファイルをロードするだけで済めば、プラグインのリストアップは単に対象のファイルを開いて内容を解析するだけで終わるので、迅速に完了します。LV2ではこれをメタデータのテキストファイル(*.ttl)に格納するというかたちで実現しています。

CLAPは公式発表ではfast scanningをサポートしていると公言しているのですが、CLAPのメタデータは実のところライブラリに格納されていてDLL等をロードしないと取得できず、この点ではLV2に劣ります。プラグインのfactoryのインスタンスさえ取得すればメタデータを取得できるので、プラグイン本体のインスタンスを生成しなくても済む、という点においてのみVSTより高速だといえることになります。DLLをロードすると全てのstaticデータの初期化が発生するため、JUCEのBinaryData初期化などでDLLのmmapロード以上のコストがかかるということもありますし、プラグインによってはこのDLLロードとメタデータ取得の時点でライセンスアクティベーションダイアログを出してくるものがあり、これらが迅速なプラグインリストの生成を邪魔してくるわけです。DLLをロードする方式だとそういった問題があるため、JSON等でメタデータを生成して解析できるようにしたほうが良い、というコミュニティ(筆者も含む)からはフィードバックが出ているのですが、開発チームは「JSONを解析しないといけなくなるから嫌だ」というレベルで否定的な見解を示しており、改善が施されるかは不透明なところです。

ちなみに、プラグインの列挙が仕組み上高速に完了するとしても、プラグインリストをキャッシュするDAWの仕組みがなくなるというとは限りません。プラグインリストキャッシュには「ロードに失敗した」プラグインをリストから除外する、いわゆるallowlist/denylistを管理することも期待されるためです。

プラグインメタデータに何を記述するか

プラグインメタデータに「何を」記述するかも設計における考慮事項のひとつです。ここでひとつ意識しておくべきは、プラグインのプロパティというべき情報には、プラグインの状態(たとえば選択されているプログラム・プリセット)によって動的に変わり得るものがある、ということです。ファイルに書き込まれるメタデータは静的なので、プラグイン名など不変のものか、初期値くらいの意味しかありません。

LV2では、プラグインのオーディオポートやMIDIメッセージの送受信に使われるコントロールポートの情報を、メタデータに記述することになりますが、VST3やAUの場合は、ポートのレイアウトはホスト(DAW)から提示された構成(ステレオ、モノラル、7.1chなど)をプラグイン受け付けるかどうかを判断する、という流れになります。LV2では、メタデータテキスト(*.ttl)に静的に記述されているポートのグループをホストが見てから「このレイアウトは受け入れられる」と判断できますが、VSTAUのように提示された構成の受け入れを動的に決定するには、dynamic manifestという拡張機能を使うことになり、その場合はやや複雑で面倒です。

CLAPはオーディオポートやコントロールポートの定義も拡張機能で定義し取得する仕組みになっており、メタデータをあらわすclap_plugin_descriptor_t型にはポートの情報は含まれません。コア部分に含まれない情報は拡張機能で取得できるかもしれませんが、拡張機能get_extension()関数によって取得することになるので、必然的にライブラリをロードすることになります。

6月の活動記録 (2022)

6月は雨が多くて好きじゃないという人も少なくありませんが、わたしは好きじゃないですね(時候の挨拶)。

AAPのPrefabパッケージ化とlibcxx-provider

AAPの開発がAndroid Studioデバッグ実行まわりの不安定さに引っ張られてスムーズに進まないので、今月は少し周辺的なタスクを片付けていました。その過程で、本来やるつもりではなかったAARのPrefab化が完了しました。Prefabパッケージ、当初は問題だらけで、こんなの採用しようがないと思っていたわけです。2020年に一度詳しく書いています。

atsushieno.hatenablog.com

ここで列挙した問題のうち、いくつかは未解決のままですが、2022年現在、少なくともAAPについては「Prefabとnon-Prefabは共存できるようになった」「project(...)を使ったモジュールの参照がまともに解決されるようになった」「ビルドタスクの依存関係はbuild.gradleの依存関係を手作業で書き加えて何とか解決できる」「ヘッダファイルのディレクトリは1つになったし、その後AGPも対応したっぽい」「STLの競合は解決するアプローチを見つけた」というレベルでざっくり解決しつつあります。そして、 デバッグ時も含めたライブラリの正しい参照解決がNDKを使った開発の課題になるのに、Prefabを使わないビルドの場合はCMakeビルドの調整でクリーンにならない、という事態は好ましくなかったので、それならPrefab荷移行したほうがマシだろう、と考えたのでした。

上記の解決課題のうち「STLの競合は解決するアプローチを見つけた」については、今月新しく公開したlibcxx-providerというAARのパッケージのREADMEで具体的に解説しています。

github.com

本当はブログエントリにしようと思っていた(思っている…)のですが、READMEでほぼ説明しきってしまったので、それで終わりかもしれません。7月もカンファレンストークの準備(調べ物)などをしないといけないので、落ち着くのは8月になってから…?

AAPクライアントAPI再構築(未了)

4月にAAPで汎用的な拡張機構を実現するAAP extensions APIを構築した話を書きましたが、今月はこれをstate APIにも適用して拡張機能化する破壊的変更を実装しました。ただ、これに伴って、Kotlin APIを抜本的に書き換える必要があることが分かって、思いのほか大掛かりな作業になりつつあって完了していません。

AAPはホストアプリケーション(DAWなど)をKotlinでも構築できることになっているのですが、現状ではAIDLで定義したAPIを叩くクライアントのレベルでKotlinとC++の両面で実装している状態です。4月に具体的に書いたのですが、AAP拡張機能は一般的なオーディオプラグイン拡張機能APIとは異なり、拡張機能の提供者が(まあこれは現状標準拡張を規定している自分だけなのですが)AIDLで定義された拡張機能操作メソッドextension()を呼び出すネイティブ実装も提供する必要があります。その実態は「渡された命令コードがn番だったら、共有メモリバッファの0..mは引数xとして扱う」といったプリミティブな処理になります。

これらはC/C++レベルで実装されますが、Kotlin側には対応する機能が現状ありません。Kotlinのプラグインクライアント(DAW)が使うAPIは、あくまでAIDLで生成されたKotlin APIでしかないので、Kotlinでこれらの拡張機能を使おうと思っても、再実装するか拡張機能そのもののラッパーを作るしかありません。前者はそもそもKotlinで拡張機能の作者がC/C++でやっていることを再実装するということなので筋が悪く、特にC/C++拡張機能の作者と別人でありうるKotlin API実装者が同じURI拡張機能を実装している状態は治安が悪いので、誰でもKotlinでC/C++ APIバインディングを作る必要がある(けど治安が悪いとまではいえない)後者のほうがまだマシということになります。

Kotlinで拡張機能のラッパーを作るとしても、そもそも何に対して「ラッパー」を作らなければならないかというと、実のところlibandroidaudioplugin.soに含まれる非公式のC++ hosting実装に対するラッパーとならざるを得ない状態でした。これは、拡張機能のサービスAPIがlibandroidaudioplugin.soのC++ hosting APIの実装に深く依存していたためです。そういうわけで、今月は少なからず時間を割いて、4月に実装していたこのAPIを再構築して、拡張機能APIホスティング実装のAPIを切り離しました。

本当はこの切り離しが完了(変更したAPIに合わせてaap-lv2もaap-juceもそれらを使ったアプリを全部変更)したら、その続きとしてKotlin APIで純粋に拡張機能を呼び出せるような仕組みを構築するつもりだったのですが、前述の通りその方式では拡張機能の再実装ということになってしまって筋が悪いことに気がついたので、やはりKotlin APIもlibandroidaudiopluginのhosting APIのラッパーにせざるを得ないかな…となっているところです。

オーディオプラグイン勉強会#1(準備)

そろそろまたオーディオ開発の勉強会をやりたいと思っていた頃に、6月にCLAP 1.0がリリースされたので、それならCLAP 1.0を肴に勉強会をやると良いだろうと思って開催することにしました。オンラインで7/6 20:00スタートです。今回もこの分野に関心がある人には大いに刺激になる勉強会になると思うので、ぜひ参加してもらえればと思います。

music-tech.connpass.com

勉強会のスタイルを設計するというのは(少なくとも自分としては)割と考慮事項がたくさんあっていつも悩むところで、今回は特に以下のような設計方針にしました。いずれ書こうと思っていたので、今回ここでまとめることにします。

  1. 勉強会は「参加者のため」にやる
  2. みんながしゃべれるようにする
  3. 発表者がしゃべるだけの会にしない
  4. ただし雑談に依存しない
  5. カジュアルからどっぷりまで各人の好きな度合いで参加できる

1.〜3.はざっくりセットです。聞いているだけ、質問・コメントでしかやり取りできない勉強会になってしまうと、どうしても「数字」(人数)・養分にしかなっていない感じになってしまいます。自分の場合、コメントが半分拾われなくなったら「他人事」になってストリームを閉じることが多いですが、ホスト側になったら全部拾っていられないですよね。自分の場合、資料を読み上げて発表したいのであれば1人でしゃべって動画をうpすればいいし、文章やスライドとして公開したほうが読む側も助かるだろうし、「参加人数」にKPIが無くて、どちらかといえば「せっかく関連技術に詳しい人が集まってくれるので、そこから最大限いいシナジーが生み出されてほしい」わけです。

これは普遍的な話ではなく、たとえば「多人数向けに話すためならたっぷり時間をかけて最高の資料とセッショントークを準備して最高のマテリアルを遺すことができる/業務時間なども使える」という環境にいる人にとっては、多人数向けのオンライン勉強会などが最適解になるわけです。わたしは「みんなを引っ張り上げる」立場にもないので、共同体的な勉強会が向いています。

このやり方は多分名目30人くらいが限度だと思うので、ストリーミングの制限にかかわらず最大30人としています(10〜15人くらいは完全に聞き専と想定)。トピック的にはもっと集められてもおかしくないですが、それは全くKPIに基づく別のスタイルになるでしょう(複数人に事前にセッションをお願いして人づての窓口も増やす)。まあイベント感ある勉強会もそれはそれで楽しいですよね。

資料発表の時間は全体の1/2〜1/3くらいにして、ざっくりにして、いつでもしゃべりを中断して質問・コメントできるようにしています。何なら「ちなみに…」と直接関係ない話をされても、経験上、これで治安が悪くなる(話題が逸れすぎる)ことはほぼありません。話題が逸れ過ぎたらいつでも「スライド(本題)に戻りましょう」といって元に戻れるのです。何なら話題が逸れ過ぎても、それがみんなの話したいことならそれが話題の本質なのかもしれません。予定時間をタイトにするとみんなしゃべらなくなるし、盛り上がっても話の腰を折ることになるので、避けたいところです。

一方で、勉強会の場が「100%ただの雑談場」になってしまうと、それはそれで「何しに来ているのかよくわからない」状態になってやっぱり満足度が上がりません。われわれには多かれ少なかれ「自分のためになる時間」である勉強会に参加するという建前が必要です。雑談だけの時間は予定時間の後に十分にあるので、「勉強会では何もしゃべらなかったけど終わった後にみんなで晩飯に行ったら急に喋りだす人」ムーブも全然OKですし歓迎です(オンラインなのであくまで晩飯云々は完全に比喩です)。

勉強会は録画しようと思っていますが、公開は前提ではないです。まず、役に立つ情報を公開したければ1人で録画できます。公開するとなると私的な話などを出しづらくなって、参加者が非参加者を意識して発言を遠慮するという本末転倒の事態になります。参加者が楽しめることが最優先です。その上で、「録画して可能なら公開する」ことにしています。これは、経験上この種の読書会スタイルで共有される情報はやっぱりめちゃくちゃ参考になる話が多く出てくるためです。

CLAP JUCE hostingの試験実装

CLAPはオーディオプラグイン勉強会ではあくまで「肴」という位置付けなのですが、発表資料をふわっとしたレベルで終わらせるのは躊躇われるので、ちょっと自分でもコードを書いてみることにしました。JUCEでプラグインを作るモジュールはclap-juce-extensionsという公式リポジトリで公開されているのですが、ホスト側で利用できる実装がないようなので、先週くらいから自分で作ってみようと思ってチマチマと作っています。現状、リポジトリにするほどメンテする意思も無いのでgistです。

https://gist.github.com/atsushieno/d47a82739c64595da2f15cd8bc87673a

CLAPホストは実際にOSSではまともに存在しないのが現状です(公式リポジトリのclap-hostは機能しません)…というのが作り始めた頃の状況だったのですが、作っている間にQTractorで実装されました。いずれにしろJUCEモジュールにすれば、AudioPluginHostで使えたりtracktion_engineやhelio-workstationに組み込んだりできるのであってほしいところです。LV2には(JUCE7で正式にサポートされる以前から)jlv2というホスト側実装のプロジェクトがあって、これでtracktion_engineに組み込んでLV2プラグインをロードしていたので、CLAPでも同じことが出来るとたぶん便利でしょう。

もっとも、LV2と違ってCLAPでやりたいことは特に無いので、これを進めたいという動機もメンテしたいという動機もほぼありません。勉強会資料作成の肥やしのひとつです。

CLAPに関してはもうひとつ技術調査の動機があって、AAPのネイティブAPIの実装を、Binderでやり取りするのとは別のレイヤーでCLAPに置き換えて実用できるかどうか評価する、という目的がありました。CLAPにはAPI設計で参考になる部分もあるのですが、現状ではホストとクライアントの相互運用(API呼び出し)が頻繁にあって、プロセス境界をまたぐ必要があるAAPには馴染まなそうだというのが現時点での評価です。

その他

6月の最初は内閣官房デジタル市場競争本部事務局の力作に応えるべくパブリックコメントを書いたり本文を読んだりしていました。これは前回書いたので詳細はまあ今回書くまでもないでしょう。

atsushieno.hatenablog.com

あと、7月末に台北COSCUP 2022MIDI 2.0に関するセッションをひとつ担当します(英語)。観光ビザでは相変わらず入国できない状態ですが、今回は渡航できる予定なので、問題が発生しなければ現地でしゃべることになると思います。来月はその発表準備や渡航準備で多少ごたごたする予定です。

モバイル・エコシステムに関する競争評価(中間報告)に対するパブリックコメント 最終版

話題の*1「モバイル・エコシステムに関する競争評価(中間報告)に対するパブリックコメント」を自分でも書いたので公開しておきます。

public-comment.e-gov.go.jp

以下本文:


この報告書の位置づけに対する理解

(この項目は、提出用フォーマットの「2.記載された内容の他に、考慮すべき視点とそれに対する意見」として記載します。)

パブリックコメントは公開されて読まれる前提である、という考えに基づいて、このコメントは担当者の方以外にも読まれる体裁でまとめられている。

本コメントはmarkdown形式で書かれたものをメールで送信しているので、デジタルデータがあれば読みやすく復元できる。

この報告書は内閣官房デジタル市場競争本部事務局の名義で出されている。競争政策だが公正取引委員会デジタル市場競争会議ワーキンググループの中で報告者として参加していたに過ぎない(ただGoogleの法務担当者から、ワーキンググループの議事録での参加は少なく見えるが実際には何度もミーティングしてきた旨、ジュリストNo.1564(2021年11月号)に書かれているとされている)。

本報告書に対しては、こんなかたちでAppleGoogleを規制しても日本の企業がAppleGoogleに勝てる市場を作れるわけではない、国粋主義者が非国産プラットフォームの足を引っ張る目的で作った非現実的な報告書である、といった批判が上がっているのが観測できる。前者については、本報告書の議題となる競争市場はプラットフォーム市場そのものだけでなく個別のアプリ市場(たとえば音楽ストリーミングアプリ市場)に対しても影響するものであり、本報告書の意図するかたちで対策を検討することは適切であることを確認しておきたい。

後者は国家による企業に対する正当な法規制ではないという主張であり、傾聴すべき意見ではある。これについて、米国でもモバイル独占市場にかかる規制法案が審議されるにあたって、議員の意見の割れ方に興味深い結果が出ている。現与党である民主党は全員規制側、共和党は半々に割れており、企業は国家に服従すべきと考える議員が民主党と同じ規制側に、企業の経済活動を最大限自由にすべきと考えるような議員が規制否定側に回っている状況であると理解できる。筆者は、競争法の観点から、合目的的な、最小限の、しかし積極的な介入は必要であると理解している。

デジタル庁には、かつてWindows PhoneというApp Storeのように独占的なモバイルプラットフォームを打ち出そうとして失敗し撤退した日本マイクロソフトの出身者が政府CIO補佐官の時代から何名も在籍しており、今回の報告書にも影響を及ぼしている可能性はある。一般にプラットフォーム企業の出身者は出身企業の従業員と密に連携して法に明確に反しない範囲で利益誘導を得ることがあり(たとえば招待講演を請けて現業を宣伝する場を設けてもらえる)、AppleGoogleから営業秘密を引き出す意図をもって関連制度の枠組みに参加する危険性もあることは意識しておきたい。関連プラットフォーム業者には忌避の申立を可能にする等の対策が考えられる。


(以降は提出用フォーマットの「1. 記載された内容に対する意見」として記載します。)

I. 総論

第1.市場の構造と実態

<中間報告の該当箇所:16ページ>

モバイル OS を維持するためには年間数百億円かかると言われているが、一方で、OS の事業に関しては、根源的に先行者メリットがある。

コストばかりが強調されていて、収益について言及が無いことから、これはプラットフォーム側(AppleおよびGoogle)が主張したい数字だけをそのまま書いているのではないかという疑念が生じる。この引用部分は、間接的な先行者利益がこれらのプラットフォーム運用の動機に直結しているかのように読めるが、AppleApp Store登録開発者は50万人おり、99ドル = 10000円という大雑把な換算でも1年で50億円の売上がある(アプリ内課金による収益のほうが大きいことは言うまでもない)。最終的な報告書では、開発者からのプラットフォーム利用料などが主要な収益源であることが読者にも理解できるようなまとめ方が望ましい。

<中間報告の該当箇所:17ページ>

ユーザーにとっては、ブランド・ロイヤリティだけでなく、使い慣れた UIやコンセプト、使い慣れたアプリなどをインストールする手間、既に端末内やクラウドに保存している多種大量のデータを移動する時間や労力などがあることから、スマートフォンの OS をスイッチすることについては、ハードルがある。

これに関連して、アプリ市場の消費者には、プラットフォームを切り替えるだけで同一のアプリケーションに再度対価を支払って購入させられているという状況があり、これが放置されていることが問題である。PCソフト市場においては、同一のソフトの市場において、同一ユーザーに対する複数のプラットフォーム分、数台のマシンへのインストールが可能になっているのが一般的であり、モバイルアプリマーケットが独占的であることは、対価の二重取りを肯定することになっている。

複数プラットフォームにおいて「同一の」アプリケーションが配布される場合に、対価の二重取りが生じないことを保証するような、同一ユーザーによる購入情報を確認できるようなアプリ市場間の相互運用の仕組みが、一定規模のアプリケーション市場において実装されるような施策が求められる。(同一性はアプリ名、アプリ内コンテンツの同一キャンペーン・イベント等、あるいは広告等で実質的に判断できる。)

第2. 目指すべき姿と対応に向けた基本的な考え方

<中間報告の該当箇所:35ページ>

「1. モバイル・エコシステム全体に関する認識」「2. モバイル・エコシステム全体のあるべき姿」ともに適切な内容でまとめられていると考える。

モバイル・エコシステムは、これらのサービスを利用する消費者の日常生活、そして、当該サービスを提供するビジネスユーザーの経済活動の基盤(インフラストラクチャー)としての機能を果たしているととらえることができる。

この他に、行政においてモバイルアプリケーションが開発・利用されているという観点が重要であると考える。そもそも論として可能な限りプラットフォーム依存性を排したWebでできる以上のことを行政で利用するアプリケーションにおいて利用すべきでないという問題もあるが、必要最小限の範囲でモバイルアプリケーションを利用せざるを得ない場合もあろう。そのプラットフォームは公正競争に則り独占に資することがあってはならないし、当該プラットフォームをサポートしないことで国民生活に多大な健康上の被害や金銭的利益の多寡といった影響が出るのであれば、それは国家がプラットフォームの機構に積極的に介入する必要がある。

この点で近年独占性が問題になったのはコロナウィルス濃厚接触を検出するExposure Notification APIとそのサービス実装で、日本でもCOCOAというアプリケーションがこれを組み込んでいる。COCOAは「公共事業案件を受注前のアピールだけは大々的に行い、受注後は何もしない」という方針に等しい開発企業のネグレクトによりユーザーフィードバックを放置して問題になったが、ここに競争原理が機能していれば、このような問題で国民の健康・生存権を幅広く損なうことはなかった。この独占構造に資することになったのがAppleGoogleの1国1アプリという私的な制限だった。独占禁止政策はこのような観点でも他の官公庁から独立して影響力を及ぼす、具体的には国民および公正取引委員会などから問題の指摘を吸収し改善を促していく機関が存在すべきである、と考える。

<中間報告の該当箇所:36ページ>

アルゴリズムを利用しているためにビジネス上の決定の過程がブラックボックス化していること等により、情報の非対称が存在しており、

「企業秘密である非公開アルゴリズムに基づいており公開できない」といったエクスキューズのことを指していると思われるが、アルゴリズムに計算機にかかる判断処理がブラックボックス化されることは無い。 特許技術であればそれは公開されていなければならないし、営業秘密の保護は独占禁止法違反を正当化するものではなく、企業には官公庁において事実関係を確認するための監査を受け入れる義務がある、と立法で対策することが考えうる(もちろんこれは独占禁止法に基づく行政手続であって犯罪の捜査等に目的外利用できてはならない)。

<中間報告の該当箇所:37ページ>

複数のレイヤーで影響力を行使し得るプラットフォーム事業者による一定の行為に対し、現行の法的枠組みの制約にとらわれず
に、実効的に対応することができる方策を検討することとしている。

根拠法なしで実効的に対応する方策を検討するのは法律による行政の原理に反するので、少なくとも対応根拠に関しては明確に法に基づく対応が求められる。弊害の類型化と明示があれば、対応手段まで詳細に規定することは必須ではないと考えるが、基本的に政令等に基づいて対応する必要があろう。

<中間報告の該当箇所:38ページ>

今回競争評価の対象としているモバイル・エコシステムにおける競争上の諸課題については、その特性から、これまでの競争法によるアプローチとは異なるアプローチを考えていく必要があるのではないか。

本項に関連して、「独占的状態に対する措置」(独禁法第2条第7項、第8条の4)が注釈として言及されているが、本条はいわゆる伝家の宝刀であり、その適用を視野に入れるのは不当とまでは言えないものの、現状で野放図である市場の独占的状態に対して、最初から用いていく筋書きよりは、着実な競争促進策を推し進めるほうが適切であると考える。

<中間報告の該当箇所:39ページ>

セキュリティやプライバシー保護など例外的に何らかの理由を持つ場合もあり得ることから、プラットフォーム事業者がそれを示した場合、十分に精査したうえで正当な理由と認められる場合には、禁止から取り除くといった対応が可能ではないか。

「正当な理由のない禁止の禁止」は、法の原則として適切なものであり、プラットフォームが公共的存在である認定される以上は、これはユーザーおよびプラットフォーム内開発者に対するプラットフォームからの「禁止」についても妥当する原則といえる。

とはいえ、それがあまねく事前規制として存在すべきかどうかは別の問題である。行政にたとえるなら、地方自治体が独自の規制を定める際に、国政に対して事前に届け出をすることはないはずである。プラットフォームによる競争阻害行為についても、それが類型的に予測可能で事前承認を必要とする場合もあり得るが、それ以外は事前規制には馴染まないと考える。

セキュリティの関連では、プラットフォームに対する根源的に解決困難な攻撃が比較的短期間で可能になる状況がしばしば存在する。Intel系CPUに対するSpectre攻撃は、WebブラウザにおけるShared Array Buffer機能の利用を封印させるに至った。またセキュリティ対策がある時期に一気に普及することもある。HTTPSでないHTTPトラフィックの一般的な乗っ取りは、20世紀には理論上の存在でしかなかったが、現在では現実的な脅威となってきたため、ある時期にWebブラウザのベンダーやプラットフォーム側でHTTPの接続要求がHTTPSの接続要求に置き換えられるようになった。これらは安全策の強制が良い意味で世界を改善した例といえるが、いつから「対応必須」と言えたかは判断が難しく、「禁止の禁止」が強制されていたら実現は困難だったと考えられる。

この点では、プラットフォーム事業者がTerms of Serviceなどにおいて反競争的な禁止項目を追加したときに、そのプラットフォーム上のアプリ開発者やユーザーが幅広く反競争行為について申告できる対応窓口を行政側で提供し、それに基づいてプラットフォーム側に対応を要求する仕組みが構築されることが望ましいと考える。

一方で、類型的に反競争的なTerms of Serviceの追加などを事前に禁止類型として提示しておくことは、問題にならないと考える。プラットフォーム側に十分な対応リソースがあると考えるのが合理的である範囲においては、それを為さなければ独占禁止法違反となるという法的根拠がある限りにおいて、作為義務を認めることも妥当であると考える。なお、これに対して、たとえば「著作権法違反を防ぐため…」のような理由付けは独占禁止法違反の認定に内在する曖昧さとは無関係であり、本項に基づく作為義務の対象にはなりえないと考える。

<中間報告の該当箇所:39ページ>

デジタルプラットフォーム事業者が行っている行為については、データやアルゴリズムなどに関して、プラットフォーム事業者との間で情報の非対称性がある。このため、規制当局に対して、広範な情報提供や説明を求める権限を付与するなどの仕組みも考えられるか。

本項で注記された欧州委員会のほか、米国でもAmerican Innovation and Choice Online ActやOpen App Markets Actの制定といった動きがあり(これらは本報告書で後々に言及されている)、日本の行政においてもこれらの担当部署・機関と連携しての情報交換および国民に対する成果公開を期待したい。

第3. モバイル・エコシステムにおける各レイヤーに関する評価及び対応の方向性

総論としての事実認識、問題の提起については適切にまとめられていると考える。対応策に関しては、その妥当性および実効性について、II.各論で検討したい。

第4. モバイル・エコシステムにおける諸課題への対応における対象の考え方

<中間報告の該当箇所:52ページ>

モバイル・エコシステムにおける諸課題への対応策を検討するに当たっての対象の考え方について、どのように考えるか。

本報告書から想定される法規制の対象を競争市場とすることは妥当と考えるが、モバイルアプリケーションのプラットフォームに限らず、パーソナル・コンピューター市場も規制対象として考えるのが妥当であると考える。現状ではWindowsMacのシェアが大きいが、Chromebookも普及しつつあり、Googleが対象となる日が来る可能性もあろう。ただし、本報告書で指摘されている通り、モバイルプラットフォームではデバイスの性質上プラットフォームベンダーがユーザーのアテンションを集中的に得られる等の側面があることが法の積極的な介入の理由のひとつであり、この問題が当てはまらない場面ではPCプラットフォーム市場は対象外とするのが適切であると考える。いずれにしても、独禁政策における市場策定や法の適用は公正に行われなければならない。

この他にゲームプラットフォームも独占的なアプリケーションの配布モデルとなっており、競争促進の観点では対象になりうるように思われるが、モバイルプラットフォームやPCプラットフォームとは異なり、行政の場面で利用するようなプラットフォームとはなっていないため、積極的な法システムが介入すべき市場としての側面が小さいことは否めない。

第5. モバイル・エコシステムにおける諸課題のとらえ方と対応の方向性

総論としての反競争状態に対する取り組みの方向性は、本節に付された諸外国動向資料を踏まえるに、正当なアプローチであると考える。

II. 各論: 第1. エコシステム内のルール設定・変更、解釈、運用

第1-1. 【OS・一部ブラウザ】

1. OS 等のアップデート・仕様変更への対応

<中間報告の該当箇所:72ページ>

オプション A は、問題の解決に有効か。また、どのようなメリットがあるか。
オプション A 以外に、問題の解決のために有効に機能すると見込まれる方策はあるか。
オプション A の実施に伴い、セキュリティ、プライバシー等どのようなコスト、リスクが生じるか。
その問題を軽減させる方策として、どのようなことが考えられるか

本項で論じられる本質的な問題は2点、(1)アップデートに(主に)Appleの規定する期限内に十分に対応できない (2)プラットフォームの新バージョン公開時に告知される新たな要求事項に対応する期間がAppleGoogleにとって先行者利益をもたらす結果になっていること、と解釈できる。

このうち、後者を事前規制するのは困難で、独占的状態に対する規制すなわち事業分割を伴わなければ実効性が無いと考えられる。先行者利益は毎年とはいえ「たかだか数ヶ月」であり、これが長いか短いかは対象事業次第だが、独占的状態の規制を持ち出すにはさすがに問題が小さすぎると考えられる。プラットフォーム規制には、より直近に解決すべき問題が山積みである。

アップデートの内容および対応期間の問題について、特に日本語での「最新バージョンに関する適切な情報開示」「デベロッパからの問い合わせに関する手続・体制の整備」はほぼ実現できないと考えられる。プラットフォーム企業の日本法人はそもそも営業拠点でしかなく、プラットフォーム開発部隊のメンバーはおらず、短期間で新発表の技術等について伝達できる開発スキルを有する人材が十分にいない可能性が高く、簡単に増員できるものでもない。また、新バージョンの公開に伴って公表される資料は通常は膨大なもので、通常は一生日本語化されない。開発者が自己責任で機械翻訳にかけて読めれば十分である。

「運営状況の政府への報告」は、特に前者をプラットフォーム企業主導で行うことを要求しても、開発者が実際に直面する問題が適切に反映されない可能性がある。「政府によるモニタリング・レビューの実施」は、そのフォーマット次第ともいえるが、政府はアプリ開発者ではないので、プラットフォーム事業者から提供されるリソースをレビューできる技術力も時間リソースも無いであろう。それよりは、アプリ開発者および一般ユーザーが政府に対してプラットフォームの新たな制限等にかかる問題を報告できる窓口を設け、それに沿って政府側から新バージョン公表後は3ヶ月程度は毎月、各種変更追従対応にかかる要請(〜命令)を連絡する制度で対応するのが現実的かと思われる。

また、反競争的契約条項に関する報告窓口は常時設置して、新たな問題をタイムリーに審議し対応できる体制があることが望ましい。

2. OS のアップデート等に伴うアプリ開発の時間的優位性

<中間報告の該当箇所:77ページ>

事実関係や懸念事項について、さらなる情報(具体例の追加や補足等)はあるか。

Appleはこれまでに何度も反競争的な制限を開発者に課している。最初期に話題になったのは2010年にAdobe Flashを排斥するためにiPhone Developer Agreementに追加されたsection 3.3.1すなわちアプリケーションはObjective-C, C, C++コンパイルしたものかWebKit上で動作するJavaScriptのみが許される(当時)とした条項である。

ゲーム開発フレームワークを開発しているUnity社は、それまで何の問題もなくC#でアプリケーションを開発し公開できていたものを、いったんC++コードに変換する仕組みに着手せざるを得なくなり、その後本条件が実質的にAdobeのみを狙い撃ちにするかたちで実施されているとわかるまで開発コストを割くことになった。(この仕組みはその後JITにかかるコーディング制限の緩和の目的でIL2CPPという名前で公開されている。)

本報告書で全く触れられていないと思われるのは、Google以外のAndroidバイスベンダーが必要とするコードは、正式版のリリースまで全く公開されないことである。GoogleAndroid 12が正式公開される前に3回のプレビュー版をリリースしたことが言及されているが、これはアプリケーション開発用のバイナリコードのみの公開であり、これは自社デバイスに向けてAOSPをカスタマイズしなければならないデバイスベンダーにとっては意味をなさない。ここで、アプリケーションではあまり問題にならない「2年間のサポートライフサイクル」の問題が、デバイスベンダーにとっては大きな問題になりうる。特に終期のないアプリケーションにとっての3ヶ月の先行利益とは異なり、最先端デバイスがリリースされてからの2年間のうち3ヶ月をキャッチアップに費やされる問題に対しては、何らかの制度的な救済が必要と思われる。

オプション A は、問題の解決に有効か。また、どのようなメリットがあるか。
オプション A 以外に、問題の解決のために有効に機能すると見込まれる方策はあるか。

いずれの分離政策も、日本単独で規定しても実効性が担保できない懸念があるものの、サンクションとしての制裁金を回収するレベルにまで至れば法的に完全に無意味というわけではないので、その方向で規定することに反対するものではない。とはいえ、規定の実効性が確保できる方が望ましく、EU・米国等関心のある各国で提携して、あるいはWTOのような組織レベルで、条約レベルで独占禁止政策を共同施行できる仕組みを模索されたい。

もっとも、コロナ禍も経て世界的にリモートワークが普及した2022年以降の世界で、データ分離は開発業務においてオフラインワークの強制に繋がることにもなりかねず、また分離業務が行われているという虚偽の申告に対しても検証可能性が低く(AppleGoogleEU圏では法令遵守より法規違反に伴う制裁金のほうが安いと判断すればその道を選んでいるという実績がある)、実効性が疑わしいように思える。

私見としては、独占的プラットフォームにかかるこれ以外の問題が解決されれば、この問題自体は「プラットフォーム開発者は先行者利益だけは引き続き得ることになるが、それも競争政策上否定すべきか?」という問題になり、これに対しては答えは割れるのではないかと思う。その意味では「他の問題が解決するまでの条件付き規制」という位置付けにする選択肢もあると考えられる。

5. ブラウザにおけるトラッキングのルール変更(Google

<中間報告の該当箇所:89ページ>

本件にかかる最終的な意見は「2. OS のアップデート等に伴うアプリ開発の時間的優位性」におけるものと変わらない。

Google Privacy Sandboxについては、Google Play Servicesの機能のアプリケーションバンドル(aab/apk)からの分離によって「悪意のある改ざんが加えられていない」広告SDKの仕組みが期待でき、セキュリティと透明性に資するものと考える(Google Play Adsの仕組みが透明化されるという意味ではなく、Google Play Servicesの機能の一部がPrivacy SandboxによってGoogleの制御下でダウンロードされるようになれば、GPSを利用するアプリケーションにGPSのコードをバンドルする必要も、それに伴ってapkがGoogleのライセンスに拘束されることもなくなる、という意味において)。とはいえ、現時点ではAndroid 13以降でのみ利用可能な機能であり、まだ未来形の話であると理解している。

6. クローズド・ミドルウェアGoogle

<中間報告の該当箇所:94ページ>

一定規模以上の OS を提供する事業者が、当該 OS をオープンソースで提供している場合には、アプリの開発環境を提供するときは、その開発環境に、当該オープンソースの OS を利用して自らの OS を提供する事業者がアクセスできるようにすることを義務付ける規律を導入することが考えられるのではないか。

オプション A は、問題の解決に有効か。また、どのようなメリットがあるか。
オプション A 以外に、問題の解決のために有効に機能すると見込まれる方策はあるか。

これは公平性に欠け、プラットフォーム事業者に要求できることではない。「当該 OS をオープンソースで提供している場合には」という条件の設定が失当である。プラットフォームAPI非独占的であることがプロプラエタリ部分のオープンソース化を要求できる正当な理由にはならない。クローズドミドルウェアによる囲い込みの解消策は、Windowsを公開しているMicrosoftにも、iOSmacOSを公開しているAppleにも、等しく公正に要求すべきである。モバイル・プラットフォームであるか否かは、囲い込みの成否に影響する問題ではない。本項目の記述からは、そのような公正な発想が欠落している。実務上も「(理由は全くわからないが)プロプラエタリOSにすれば解決だ」と考えてプラットフォームコードの一部を非公開にして回避されるだけであり、透明性確保に完全に逆行することになる。

サードパーティのOS開発者には許可制で見えるようにするのは一つの手」などと意見しているのは、おそらく日本マイクロソフトの関係者かアマゾン・ジャパンの関係者からの差し込みであろうと考えられる。日本の競争政策はGoogle/Apple以外の独占的プラットフォームが横槍を入れるために存在するものではない、ということを確認したい。

Google Play Services (GPS)の囲い込み問題を解決するための、より適切な方法は、GPSに相当するプラットフォームサービスプロバイダーAPIの策定とその適用をプラットフォーム提供者に義務付けることである。これならばGoogle等プラットフォーム事業者に「反競争状態を解消するための現実的かつ妥当なコスト」として認められると考えられる。Google Android以外のAOSP互換プラットフォームで当該サービスプロバイダーAPIの実装が存在しない状態がある場合に、それによってアプリケーションが利用できない不利益を受けるべきはプラットフォーム事業者であるべきである。

第1-2. 【アプリストア】

7. アプリストアの拘束(Apple

<中間報告の該当箇所:98ページ>

報告書に示されているようなAppleの主張は、米国でOpen App Markets Actが審議されていたときに、日本も含め世界的に名前が広く知られている米国のセキュリティ研究者Bruce Schneierによって幅広く否定されており、日本語でもその詳細が「競争法案に反対するアップルの主張に反論するブルース・シュナイアーの意見書」という翻訳文書で読めるようになっている。

実際、Appleは開発者向けオンラインカンファレンスWWDC 2022において、iOS 16で開発者モードを導入し、開発者署名が付いたものはApp Storeで公開されていないアプリケーションであっても実行できるようにしている。Appleの開発者用ベータテスター向けアプリ配布サービスTestFlightを使用するとアプリケーションが配布できたため従前と変わらないという主張も見かけるが、開発者署名が付加されていれば配布チャンネルを問わないというのはsideloadingに近いと考えられる。何より、これはEUのDMAに対応するための機構と考えられている。開発者署名はAppleの有償サービスに開発者登録しないと付加できないため、これが実際にDMA適合的であるとは言えないとも考えられるが、まずは具体法をもつEUの判断が待たれる。日本でも同等の立法に着手し、反競争行為を積極的に規制していく必要があろうと考える。

なお、iOS16によって実現している開発者モードには、「8.サイドローディングの制限(Google)」で指摘される問題が同様に当てはまると考えられる。

サイドローディングが認容されている Macバイスとの違い

この節にまとめられているAppleの主張にも理由がない。macOSからもiCloudに保存されている情報をはじめとする重要な個人情報にアクセスできることにも、ユーザーからの承認を得ない限りこれらの情報にアクセスできないことにも、iOSmacOSで違いはない。

12. OS 等の機能のブラウザに対するアクセス制限(Apple

<中間報告の該当箇所:166ページ>

事実関係、懸念事項に関するさらなる情報について
・事実関係や懸念事項について、さらなる情報(具体例の追加や補足等)はあるか。

本節によればAppleは「JIT は、攻撃者が iPhoneバイスにアクセスするために悪用できる攻撃対象領域を提供するため、JIT コンパイラを使用する代替エンジンは、セキュリティ上の大きな脅威となる」と説明しているが、このAppleの主張は、GoogleがかつてWeb Assembly技術の前身ともいえるNaCL (Native Client)と呼ばれる技術において、コードの書き換えに繋がる命令を書き換えることで危険なコードの実行を抑止しつつJITを有効にする手段が有効であったことから、端的に事実に反している。

*1:と書くと他人事っぽいですが多少は自分も波風を立てたはず…

5月の開発記録 (2022)

5月、割と大したことをしていないうちにあっという間に過ぎましたが、ちょいちょい活動していました。

MIDI Innovation Awards応募記録

これは正確にはほとんど4月なのですが、4月にオーディオ開発者界隈でちまちまと話題になっていたMMA (MIDI Manufacturers Association) のMIDI Innocation Awards (MIA)のSoftware Prototype/Non-Commercial部門にひっそり応募していました。

www.midi.org

募集の存在自体は4月初頭には気づいていて、ちょっとAAP MIDIDeviceServiceにプリセットを切り替えられる機能くらい実装すれば音源だけでもそれなりにいけるかな、と思っていたのですが、先月はそれでそのままずるずると拡張機構そのものを全面的に作り込むことになってしまい、プリセット切り替えまでは至らなかったわけです。それまで"Prototype"の部分に気づいていなかったので、下旬にはこりゃ間に合わんから諦めよう…と思っていたのですが、月末になって他の応募作品を眺めながら「あ、完成していなくてもいいんだ…」と気づいて、さらにWebMIDI.jsやらags (advanced GTK sequencer)やら、昔からずっとあったソフトが新作みたいな顔をして並んでいるのをみて、「今年出来たものじゃないといけないはずなんだけど、MIDIの新機能があるだけでOKなら(MIDIDeviceServiceの実装は2021年4月だし)出すだけ出そう…」という感じで1日で適当にエントリーを作文して出しました。MIA、去年からやっていて今年で2回目らしいですが、Webサイト自体が割と雑で(!)、エントリーに複数段落書いていたのが全部1段落にまとめられて何かしら脳に病があるような体裁の文にされています…(他のエントリーもちょいちょいそんな感じのやつがある)

応募するコストは低い割に、見返りとしてMMAから応募者向けに、6月上旬に開催されるNAMM招待券(数量限定)みたいなやつがもらえることになっていて、これが割とおいしそうなやつでした。オフラインとオンラインがあって、オフラインは確か$900くらい、オンラインも$50くらいはして、オフラインに申し込んだほうが圧倒的にお得感はあるしNAMMは一度くらい見てみたいと思っていた(いる)のですが、今このご時世に観光旅行も十分に楽しめないだろうし(普段ドミトリーとかで過ごしてたことも多いし)、ちょっと足を伸ばしてトモダチを訪ねるのもだいぶ気が引けるので、心理的コストが大きかった(めんどくさかった)のでやめました。オンラインは誰でも参加できると思います(参加って言えるほどの体験があるのかはわかりませんが)。特に秘密だと書かれていないので数字も書いちゃいますが、オフラインチケットもオフラインチケットも65枚あって(ただこれは特別招待枠などを含む数字)、応募が全部で100件ちょいだったので、1応募あたり2名くらい、半分は参加しない(たぶんフツーの人は仕事があるし…)と考えると多分オフラインを申し込めばもらえたと思います。

Software Prototype/Non-Commercial部門で受賞したのはMusiKrakenというモバイルアプリなのですが、これはデバイスで取得できるモーションセンサー類を入力としてオーディオグラフノード化して出力まで(これもオーディオとMIDIがあり、ただしMIDIは有料版)いろいろ繋ぎ込める面白いやつでした。デモ動画がよく出来ていたので動画も出しときます(47:40くらいから)

youtu.be

MIAは、Commercial Software部門にも今年ちょっと話題になったFluid Chordsが出てきたり(この記事が詳しい)、この業界の技術開発の最先端が垣間見えるので、これは面白い企画を回すようになったな〜と思っています。まあNAMM Ticketsがもらえたのは今年限りかもしれませんが(2019年までは1月頃にやっていたので)。

CLAPオーディオプラグイン is 何? @ MusicLT vol.2

昨年12月に開催されたMusic LTが今月に早くも2回目を開催していて、完全に視聴者モードで眺めていたのですが、登壇側が少なそうだったのでじゃあ何かしゃべろうと思い、とりあえず年末頃に出てオーディオプラグイン開発者界隈(?)で注目を集めたCLAPについてざっくり発表しました。資料はspeakerdeckに置いてあります。カスタムURL作成が有料アカウント限定機能になちゃったのでもしかしたら引っ越すかも…

speakerdeck.com

CLAPは特徴も用途も概ねLV2とかぶるので、将来性があるかというと個人的には半信半疑なところがありますが(特にLV2はこれからJUCE7で公式サポートされるようになるので商用ソフトでの利用可能性が広がるはず)、仕様としては面白いところが少なからずあるので、選択肢として期待したいところです。ノートメッセージひとつとっても、MIDI 2.0にあるノートエクスプレッションやノート別コントローラーはもちろん、ノートオフの後tail完了後にホスト側に通知するコールバックを呼び出すような仕組みまで整備されています。

個人的にはCLAPの開発者は "Proprietary Audio Plugin for Linux, but the right way" という文章をまとめた人として注目しています。

https://gist.github.com/abique/4c1b9b40f3413f0df1591d2a7c760db4

はてなブログのgistの埋め込み、無駄に長文埋め込もうとしてでかくなるのでURLだけにします)

Linuxで商用オーディオプラグイン(特にGUI)をどう構築して配布するかはここでもちょくちょく書いていますが悩みの種で、このメモだとオーディオプラグインのプロセスを分離することでGtk/Qt混在問題を解決しようと提案していて、Ardourの開発者が全面的に反論して議論が紛糾しているのが面白いやつです。(わたしはオーディオだけRTで回せばプロセスコンテキストスイッチいらんだろ派なので他人事気分で読みました。)

この方面では今月ロンドンでオフライン(ハイブリッド)で開催されたTAP meetupに登場したJUCE始祖のJulesがぶち上げたSoundStacksの新しいアーキテクチャ(構想)のセッションが完全に面白いやつだったので、興味ある人は見てみるといいと思います。

www.youtube.com

UIにはWeb関連技術を見込んでいるというので、先のLinux GUIの話とこのSound Stacksの話を組み合わせると2年前に自分がやっていたaria2webの実験とだいたい同じアプローチになるので、みんな早くこっちに来てくれ〜ってなっています…といえるほど自分は作ってないわけですが…! (最近Androidしかやっていない)

今月CLAPを調べていたのは、「AAPの拡張機能サービス実装があればコールバック呼び出しにも対応できそうな気がするし、AAPのネイティブ処理部分は案外CLAPみたいなやつに置き換えても何とかなるんじゃないか?」みたいなことを考えていて、そのために調べていたということもあります。現状リアルタイムイベントにおけるコールバックはやっぱり無理そうなので、CLAPで置き換えるのはナシかな、というところに落ち着いています(Realtime Binderがアプリ側に開放されていたらまだ可能性があるところですが)。CLAPのGUI統合は、作者が↑のようなプロセス分離の構想にも親和的にできているのではないかと期待していることもあります(LV2でも出来なくはないと思いますが)。

AAP

実は作業に費やした時間の多くがバグフィックス…以前にASANを有効にしてビルドするまともな方法を模索するのに費やして、ほとんど生産的なことが出来ていない感じです。まあ今月はGoogle I/Oもあったしな…!(正直ほぼ関係ないです。コミュニティ・バインディング・コンテンツがほぼなかったこともあってあんまし見ていない。)

ただ先月ついにbreaking changeを導入したので、ついでに今のうちにいろいろ破壊的変更を目論んで手を加えたりとかはしています。が、ここに書くような話もほとんどないです。てか「開発記録」とか言いつつ開発に関する話ここだけだしその内容がうっすらしてる…(!?)

その他

今月はモバイルプラットフォームと独禁法に関する調べものや文書作成にも時間を使っていることがあり、コードを書く時間が相対的に減っている感じです。ネタ自体はこの記事で話題になっています。

www.itmedia.co.jp

この記事以前にわたしもTwitterでまあまあ拡散しようという意図を持った書き方で紹介していますが、このパブコメ募集自体はそもそも小寺さんから教えてもらったから読んだ、という流れです。300ページ近くある大作で明らかに複数人の作業の集大成なので、とても全部は見ていられないのですが、6/10までなのでまだちょっと時間があるので、書けそうなところを増やしていきます。

他にもやっていたことはあるのですが(異世界の仕事とか)、そういうのはまた追々…

4月の開発記録 (2022)

4月が終わろうとしています。今月は副業で某XIVの冒険者を始めてしまって進捗がひどいことに…

ADC21セッション動画鑑賞会 #1 をやった

4/6にひさしぶりにオーディオ開発の勉強会を開催しました。

music-tech.connpass.com

見たのはVitalの開発者がウェーブテーブルの最適化手法について語っているセッションです。

www.youtube.com

ADC動画鑑賞会やろうとは昨年から思っていたのですが、例年だとカンファレンスの1週間後くらいに全部上がっていたのが、今年はなぜかいつまで待っても公開されず、出てきたと思えば毎週1本程度ちょろちょろと出すだけ…という体たらくで、いつ出来るのやら…という感じでした。今回の動画も含めて、実は今でも大半の動画は既にアップロードされているのにunlistedのままだったりします(公開動画から他の動画にリンクされているのに気づけば掘り出せます)。

この種の勉強会をひさびさに開催したこともあってか、当日は参加者の方々からさまざまな補足説明や参考情報の提供をいただけて(主催した自分が雑談の20%もしゃべっていないくらい)、非常に有益で楽しい会になったと思います。もともと録画して公開する予定はなかったのですが、録画くらいはしておいてもよかった…。初回からちょっと難易度が高すぎるかな?と思ったのですが、結果的には大正解だったと思います。1/5くらいはわたしがDSPの素人に毛が生えた程度の知識しかなくて話をリードする役に立たなかったことに起因しています(!) これはいいことなので継続してそうやっていきたいですね(!?)

第2回もカジュアルに1週間くらいでふらっと計画・実行したいと思っています。

AAP extensions

今月は、ほぼ1ヶ月ずっとandroid-audio-plugin-framework拡張機能を実現する方式を見直し、設計を書いては投げ、実装しては投げ…をやっていました。どんくらいずっとかというと、githubにほとんど草が生えないくらい(mainブランチでやっていないから一切が草にならない、という要因もありますが、開発ブランチでも更新頻度は低い)

拡張機能はAAPのようなプラグインフレームワークAPI安定性を維持するために「コアだけは安定させ、追加機能は全部拡張APIとして作り込む」というもので、VST3でもVST-MAとして実現していますし、LV2も大量のモジュールで編成されていますし、CLAPも数多くのfundamental extensionsを設計しています。

AAPも建前上はLV2やCLAPに近い拡張機能をサポートしていることになっているのですが、一方でもともとJUCEモジュールとして作り始めたこともあって(JUCEではAudioProcessorさえサポートできればよく、AudioUnitも対応しているので拡張機能なにそれおいしいの状態)、ちゃんとしたサポートが後回しになっていました。proof of conceptとして当初は「プラグインとホストで共有するASharedMemoryを管理する構造体」やら「MIDI 1.0を使うか2.0を使うか指定する構造体」だのをextensionとして定義して(本来前者は拡張にするのが相当ではない)、何となくやったつもりでした。

しかし今月になって「MidiDeviceServiceで出音を調整するのは無理があるし、カジュアルにプログラムチェンジで音を切り替えられるようにpresetsを実装するか〜」と雑に思いながら、実際に「拡張機能」に相応しいAPIを設計しようと思って着手してみると、LV2やCLAPとは全く異なるレベルの問題を解決しなければならず、実はこれめっちゃ難しいやつでは…!?となりました。メモリ空間が別々にあるので関数コールバックは使えない、ということは以前から把握していたのですが、もう少し上位の視点でまとめると、AAPはAudioPluginServiceとclient hostの分離プロセスの構造の上で以下の3つを実現する必要がありました:

  • プラグイン開発者もホスト開発者も自然に拡張機能を使えるようにする
  • 拡張機能の開発者がAAPの内部構造に依存せずに実装を提供できるようにする
  • libandroidaudiopluginがホストでもプラグインでも任意の拡張機能をハードコーディングなしでサポートできるようにする

これ、LV2やCLAPどころかAUv3でも実現していないやつでは…!? (デスクトップのプラグインフレームワークではdlopen/dlsymで一発だし、AUv3に拡張機能らしいものは無さそう)

これを実現するためには、AAPコア部分でやっているのと同じように、Binder等を使って拡張機能の呼び出しを処理できなければなりません。しかしプラグイン開発者がBinderまで意識してその処理を実装しなければならないという事態は(aap-juceやaap-lv2のような中間層が全部吸収することになるとはいえ)避けたいですし、ホスト開発者にプラグイン拡張機能を外から操作するコードをBinderをいじるレベルで実装させるというのも避けたいところです。

それならば、拡張機能の C APIを呼び出すホストと、拡張機能のC APIを実装するプラグインでは、シンプルなAPIの入り口だけを用意して、それらがBinderでクライアント・サービスを実現する部分については拡張機能の開発者が提供するようにすれば良いのではないか、と考え、extensionの開発者にはextension serviceも実装してもらう、という方針にしました。拡張APIで利用される「関数」は、ホスト側ではBinderを使ったいわゆるproxyが担うことになる、というわけです。ホスト「を」開発する人はそんなことを意識しなくても、get_extension(URI)だけでそのextensionの構造体が返ってくる、みたいな仕組みです。

プラグイン開発者が実装した拡張機能のコードが動作するのはプラグイン(サービス)側のアプリなので、プラグインによって拡張機能が呼び出されて処理している範囲では難しいことは何もありません。一方、そのプラグインアプリ全体としては、その拡張機能を呼び出すコードは、ホストからのリクエストをさばくAAPフレームワークのAudioPluginService(のBinder)であり、AAPフレームワーク開発者としては「誰が書いたかわからない拡張機能のコードをプラグインのプロセス空間で実行できる必要があります。そのためには、「Binder経由のリクエストで指定された拡張機能の指定された関数を呼び出す」ためのルーディングを実装して、それらのリクエストを拡張機能の開発者に渡して処理してもらう必要があります。

AAPとプラグインを繋ぐ部分と、AAPとホストを繋ぐ部分は、それぞれその拡張機能で出来ること・やるべきことを掌握している拡張機能の開発者が担うのが適切です。わたしは当初この部分を甘く見ていて、たとえば「ホスト開発者はpresets拡張機能をサポートするコードを自分で書いているのだからホスト側が直接presetsをサポートするコードを書けばいい」と考えていたのでした。それだとAAPのフレームワークのレベルで実装が追加されない限り、誰もこのproxy部分を開発できないわけです。

機能要件としては、この3〜4者(プラグイン開発者、ホスト開発者、拡張機能開発者、AAP開発者 = 自分)の役割をきちんと切り分ける必要があり、またそれぞれがアクセスできるAPIを適切に限定するのもフレームワーク設計でやるべきことです。特に現状どれもC APIとして提供することにしているので(拡張機能くらいはC++限定でも許されたいところですが)、実装言語であるC++との調整作業でさらにバグにハマって神経を削る…という感じです。

そのへんの話をgithub issueやドキュメントとしてまとめる作業もやってあって、ただ設計初期の内容なので更新しないとな…という感じです(あくまで雰囲気だけ共有):

ちなみに、これだけ設計を練っていても設計時点で解決できていない課題があって、この拡張機能はオーディオ処理の中で使えるようにはできていません。拡張機能をホスト側から操作することはあっても、プラグイン側からホストを操作できるようにはなっていませんし、オーディオ処理自体がBinderのリクエストの処理となっているので、その中でさらに拡張機能をBinder経由で「操作」することは考えられないためです。その代わり、ホストとは共有メモリのチャンネルを確立しているので、ホストからプラグインが必要としそうな情報を共有メモリ上に展開しておくことで、一般的なリアルタイム需要は満足できるはず、という設計になっています。たとえばLV2 Timeが提供する現在の演奏位置やテンポといった情報は、共有メモリデータだけで実現できるでしょう。

一方で「拡張機能がホストに追加情報を問い合わせて処理を続行する」ような仕組みにもできないので、典型的な拡張機能が何かしら実装できないという可能性もまだあります。たとえば、拡張機能ではありませんがjuce::AudioProcessor::getPlayHead()juce::AudioPlayHeadを取得してtransportRewind()を指示するような機能は実現できません。この辺は実際に拡張機能をひとつひとつ実装してみないと見えてこないでしょう。

5月は…

…というわけで、今月はこの課題にずっとかかりっきりでアウトプットの少ない日々でした(まあそんなことより冒険者としての副業がry) この辺の知見もいずれ改めてまとまった文章として英語版を公開したいと思っています(未定)。

3月には「Android 13のMIDI 2.0をいじったり…」みたいなことを書いていたのですが、どうも現状でUSB MIDI 2.0しかサポートしていなくてMidiDeviceServiceではまだ使えないみたいなので、extensionsとpresetsの実装が終わったら、たぶん新しいaudio ports (channels)に踏み込んだりするんじゃないかなと思います(今書いてて気付いたけどportsって書くとaudio port / midi portの話なのかAndroidへの移植 = ports, portingの話なのか一見して分からないな? 前者の話です)。

オーディオプラグインのインスタンス生成スレッドに関する覚書

AAP (android-audio-plugin-framework) のホスト実装のひとつとして、JUCEのAudioPluginHostを利用しているのだけど、最近全面的に再構成しているホスティングAPIに基づいてJUCE統合(AndroidAudioPluginFormat)を書き直していて、だいぶ行き詰まった問題がある。プラグインを生成するスレッドの問題だ。結論からいうと、AAPやAU v3ではmainスレッド以外からプラグインを生成するか、あるいはmainスレッドをブロックしないことが求められる。mainスレッドをブロックするのは大抵のプラットフォームではアンチパターンあるいは禁止となっているから、ロジックとしては妥当だとわかってもらえるとは思う。

AAPを設計しているのは他ならぬ自分自身なので「求められる」などと他人事みたいに書いているのは不自然に見えるのだけど、自分の趣味で求めているわけではない。

AAPはホストとはAndroidプラットフォームとエコシステムの構造として必然的に別アプリケーションとなり、インスタンスの生成においてはプラグインAndroid ServiceとしてApplication.bindService()を呼び出して生成する必要がある。bindService()を呼び出した後、その結果はそのメソッド呼び出しで引数として渡したServiceConnection(インターフェース)の実装のonServiceConnected()メソッドがコールバックされるという流れで渡される。このonServiceConnected()はメインスレッドで実行されることになるので、メインスレッドが他のコードでブロックされていると、onServiceConnected()にお鉢が回ってこないことになる。

自分の場合、メインスレッドでkotlinx.coroutines.channels.Channelwait()で待機させておいてonServiceConnected()signal()を送るようになっていて、一生先に進まない状況に陥っていた。

juce_audio_processorsを使う場合の注意点

JUCEを使ってオーディオプラグインインスタンスを生成するコードを書いている場合、そのインスタンス生成にはAudioPluginFormat(Manager)::createPluginInstanceAsync()を使うことが期待される。createInstanceFromDescription()は同期APIなので、これを使うと生成結果が返ってくるまでその実行スレッドがブロックされることになる。

std::unique_ptr<AudioPluginInstance> AudioPluginFormat::createInstanceFromDescription (
        const PluginDescription & ,
        double initialSampleRate,
        int initialBufferSize,
        String & errorMessage)

void AudioPluginFormat::createPluginInstanceAsync (
        const PluginDescription & description,
        double initialSampleRate,
        int initialBufferSize,
        PluginCreationCallback)

AudioPluginFormat(Manager)::createPluginInstanceAsync()にはひとつ注意すべき事項として、実際のプラグイン生成処理が内部的にMessageManagerを経由してmainスレッド上で行われてしまうという問題がある。つまり、たとえ自分のホストアプリケーション上ではmainスレッド上でプラグイン生成されないように(juce::Thread等を使用して)別スレッドでこの関数を呼び出していたとしても、実際のインスタンス生成処理はmainスレッドで走ってしまう。

もしプラグインフォーマットのホスティングAPIを実装できる立場であれば(筆者はそう)、mainスレッドでのインスタンス生成を「禁止」しないようにできるが、そうでなければ、juce::AudioPluginFormatを自ら実装して、createPluginInstanceAsync()の実装の中でさらに別のnon-mainスレッドに処理を非同期に実行させる必要があるだろう。

プラグイン・サービス接続処理とインスタンス生成処理の切り離し

オーディオプラグインインスタンス生成はMIDIのポート接続と似ている側面がある。1つのMIDIバイスに接続して複数のMIDIポートを利用することがあり得るように、同一のプラグインの複数のインスタンスを生成するのは一般的なシナリオだ。

Androidアーキテクチャの場合、別アプリケーションのServiceに接続するのは1つのBinderでも、そこから複数のプラグインインスタンスを生成して利用するという構成になる。Android MIDI APIの場合、MIDIバイスへの接続はMIDI_SERVICEへの接続という非同期処理から始めることになるが、いったん接続したMIDIバイスのポート接続は同期的に開くAPIになっている。

仮想MIDIバイスであれUSB/BLEデバイスであれ、対象Serviceとのやり取りはIPC(Androidの場合はBinder)ベースになるので、ポート接続も非同期であるべきではないかとも思えるけど、いったん接続したMIDIバイスとのやり取りにはrealtime IPCが活用され得るため、スレッドの切り替えを伴う非同期APIではむしろ適切ではない可能性がある。

これと同じことがオーディオプラグインインスタンス生成についても当てはまるといえそうだ。AAPの場合は、接続処理は必然的に非同期にならざるを得ないが、すでに接続済みのAudioPluginServiceであれば同期的にインスタンス生成を行える。Androidフレームワークでは現状AAPホストのような任意のアプリケーションにおいてrealtime Binderを生成する窓口が開かれていないようなので、あくまで一般的なpthreadの優先度でしか接続できないが、それでも非同期スレッドによる切り替えが発生しないほうが良いだろう。

3月の開発記録 (2022)

早いもので3月が終わろうとしています。2月の終わりから全く世界情勢が安定せず、誰もが落ち着かない雰囲気の中で日々を過ごすことになったと思います。自分も例外ではないところですが、多かれ少なかれ影響を受けつつも、自分の作業は進められるだけ進めておきたいところです。

AAP hosting overhaul

2月からずっとやっていて、今日3/31にようやくmainにマージできた作業です。

2月はAAPのnative (C++) hosting APIの仕切り直しに着手していましたが、3月も引き続き泥沼に入っていました。native hosting APIは現時点では (1) MidiDeviceServiceの実装と (2) aap-juce-plugin-host (JUCE AudioPluginHostの移植)の2つしかなく、aap-juce-plugin-hostは「起動時にインストールされているオーディオプラグインの全てをbindService()で接続する」という割とシビアな実装になっていました。これには当然ながら(?)理由があって、まずBinder APIに基づいてServiceと接続する必要があったため不可避だったのです。が、aap-juceに基づくプラグインの移植は今や↓のように大所帯になっていて(README.mdからのコピペ)、今やこれを全て接続するわけにはいきません:

そういうわけで、native hosting API仕切り直しにあたっては、native APIからServiceのAPI…を操作するAAPのKotlin API…をJNI経由で呼び出してBinderを生成する(そのBinderはJNI経由でネイティブコードに渡されてNative Binderとなるわけで多重に境界を往復するわけですが)…という仕組みを作りました。

fixing JUCE Thread

構想としてはシンプルですが、よくある話ながらAudioPluginHostが実行できるようにコードを書き換えて動作させてみたら全くうまくいきません。まず自分のライブラリのクラスをJNI経由で呼び出そうとしてもClassNotFoundExceptionで堕ちてしまう。JNIのClassNotFoundExceptionはJNIをそれなりに使ったことがある人なら、あるいはJNI経由で他言語とinteropするフレームワーク(XamarinとかReact Nativeとか)のユーザーであれば馴染みがあると思いますが、JUCEでも同じ目に遭いました。

この話は前回ここに書いたネタに繋がってきます:

atsushieno.hatenablog.com

ここにまとめたパッチは、その後この記事の英語版を作成してからJUCEへのPRとして登録したのですが(長らく「contributionは受け付けない」方針だったJUCEが1月にポリシーを変更していたのです)、現状音沙汰なしです(issueにしろPRにしろJUCEはだいたいcontribution体験が悪いのであんましお勧めしないです。JetBrainsとかは割とおすすめ。dotnetもそれなりにいいほうだと思います。)

JUCE AudioPluginHostをいじっている過程でこのパッチを作成したということは先のエントリ(日本語)でも言及している通りで、まずはこの問題を追及してパッチを作る作業でそこそこ時間が溶けました。

async-ify plugin instancing API

スレッディングの問題を片付けたら、いよいろJNI経由でContext.bindService()を呼び出してAudioPluginServiceとbindするコードを実装しました。

bindService()は呼び出してもすぐに返ってくるもので、実際にServiceに接続できたらServiceConnection.onServiceConnected()というメソッドにコールバックが返ってくるようになっています。そのため、JNI経由で呼び出すインスタンス生成のメソッドではkotlinx.coroutines.channels.Channelインスタンスを作って.wait()させておいて、onServiceConnected()のコールバックの中で.send()して続行させるコードを書いていましたが、これがまた案の定うまくいかずにハマりました。AudioPluginHostでaap-juceのjuceaap_plugin_clientモジュール経由でAAPの新しいnative APIプラグイン インスタンスを生成しようとしても、途中で返ってこなくなるのです。

しばらく調べてみると、ServiceConnection.onServiceConnected()は(生成スレッドを問わず)常にmainスレッドで呼び出される仕組みになっていました。JUCEのアプリケーション・ループはmainスレッド上で動作しており、そこから呼び出されるインスタンス生成のネイティブ関数もmainスレッドで動いていたので、ここでブロックされていたわけです。

この問題も別エントリでもうちょっとだけ詳しくまとめようと思いますが、結局この問題を解決するために、AAPのAPIにasyncificationを施すことになりました。"asyncification" というのは一部で使われている非同期API化(あるいは非同期APIの提供)をあらわす俗語です。xxx()メソッドに対応するxxxAsync()を生やすやつです。AAPの場合、同期APIで実装すること自体が無理なので、非同期APIのみで作り直すことになりました。

今まで同期APIで設計していたものを非同期APIで作り直したので、内部的には大幅なコードの書き換えを伴うことになりましたが、差分はAAP本体とaap-juceのモジュールのレベルで吸収しているので、移植したアプリケーションのレベルでは書き換えが必要ないところまで収まりました(別途ヘッダファイルのパスの統一などを施しているので、AAP 0.6.xから0.7.0へのアップグレードでは書き換えが必要になっています)。

GitHub Sponsors set up

これは去年の話なのですが、わたしが一時期アプリ開発をちょっとだけ(本当にちょっとだけ)手伝っていたサンプラーアプリがあって、もともとはその開発者がAAPに興味をもって連絡を受けてやっていました。AAPは当時まだJUCEのエフェクトプラグインの移植が使い物にならなくて、「まだ…その時ではない…」と言っていたのでした。サンプラーでエフェクトプラグインが適用できないんじゃ利用機会が無いですし。

それで今は特に一緒にやっていないのですが、そのコミュニティで開発者にAAPを紹介されたという人がコンタクトしてきて、sponsorさせてほしいと申し出をいただけたので、ありがたい2〜と思いながらやりかけで放置していたGitHub sponsorsを設定していました。スポンサープログラムを始めるといろいろサポートを考えないと…となるところですが、あまり気負わずに運用していこうと思います。donationwareとして始めてしまうと仕事見つけづらくなるかな〜とか考えてしまいますし。

WeMove, ADC21動画鑑賞会

しばらく前からMusic Hackspaceというオンラインセミナーを運営しているところで無料のセミナーがあるとたまに参加しているのですが(最初はAndroid Audioだったような気がする)、最近#WeMoveというWomen in Audioのコミュニティと連携して25回の無料セミナーを毎週のように開催するという狂気のような企画があるので(言い方…!)たまに見ています。off-siteではUKの夕方にやっているのでリアルタイムで見られる人はだいぶ限られると思いますが、録画も上がっているので興味がある人はチェックしてみるといいかもしれません。

musichackspace.org

あと最近ようやく昨年のaudiodevcon 21の動画が上がってきています。1週間に1本みたいな感じでちょろちょろと出ていて、このペースでいつ終わるんだろう…?となっていたのですが、最新の動画を最後まで見ていて、見慣れない他のADC21動画へのリンクが出てきたので「あれ?」と思いながらクリックしたら、何やら非公開リストにすでに大量の動画が上がっているらしいことがわかりましたw そういうわけで、そのへんの動画を見ながら勉強する動画鑑賞会を企画しています。来週1度やってみる予定なので興味のある方はお気軽にどうぞ(2020年にやったMusic Tech Meetupのメンバーの承諾のもとこのグループで公開しています)。

music-tech.connpass.com

その他

2〜3月には他にもちょいちょい試したことがあるのですが、今のところボツネタばかりです。最近のボツネタだとBYODを移植しようとしましたが、全く動いていないです。うまくいかなかったVialFX(謎)とかもあるし、まあそういうこともあるよね〜という感じで草の生えていないgithubを眺めています。

4月の予定

native hosting APIの書き直しがざっくり終わったので、3月に公開されたAndroid 13 DP2Android MIDI APIMIDI 2.0対応でもいじって遊んでみたいという気持ちがあります。AAPのMIDI2対応もテコ入れし直しの機運ですね。

4月にはM3 2022春が開催される予定ですが、今回はサークル申し込みしませんでした。今回は入場規制がないので、まだ安全に開催できるのかちょっと未知数だなと思っていることが正直あります(特に音楽関係はソフトウェア業界と違ってリアル空間で生きている人が多いこともあってかそこそこルーズなので…)。せっかく休みにしているので、この機会(?)にAAPの作業を進めておきたいなと思っています。