COSCUP 2026のセッション用スライドを作っているのですが、今回それなりにふわっとさせたつもりが、やはり「こんなトピックについて話します」のリスト項目がそれなりに足枷になっていて、もう少しフリーフォーマットでしゃべれるようにしないとな…という思いが強まりました。本当に話したいこと・話すべきことは、より妥当で「誰も排除しない」汎用的なプラグインホストはどのように設計すべきなのか、AndroidもWebも排除しない、VST3もAUv2もAUv3もLV2もその他の第三者フォーマットも等しく受け入れるDAWのエンジンを作るぞ、みたいな宣言なのですが、十分な時間は取れない気がします。まあ何とかしたいところです。
AAP Version 1.0 Preview released
2019年に乗りで作り始めたAAPですが、ついに 1.0 Previewと称するリリースを公開しました。大部分は先月リリースしたAAP v0.11.0に基づいています。正確には微調整を加えたv0.11.1です。どちらかというとそこそこ重要なバグを直したUAPMD v0.5.2の作業を待って正式にリリース(?)とした感じです。
Releases to Google Play Store (TBD)
リリースのためにかかった時間の大部分はGoogle Play Storeです。これは別途レポートを書いて出そうと思います。
https://play.google.com/store/apps/developer?id=atsushieno
現状Play Storeには「たった」10本程度しかAAPのパッケージをリリースしていません。Obtainiumを使えばatsushienoのGitHub releasesからもっと幅広くプラグインを入手出来ます。
KVR news (which I likely ignore next time…)
以前にketmidi-ci-toolやresident-midi-keyboardの情報をKVR Audioに登録したことがあったのですが、プロダクトの登録と記事は別物だということを把握していなくて、KVRAudioのアカウントから記事になって出てこないな…と不思議に思っていたことがありましたが、今回は「newsだと公開されるらしい」と把握して、AAP 1.0 PreviewとUAPMDの2本について記事を書いて投稿しました。これがなぜか「1本にまとめろ」とrejectされてしまい、仕方ない…と2本をあまり無理のないかたちで結合して修正投稿したら、一応は記事ページに掲載されました。
しかしこれがいつまで待ってもBskyのfeedに出て来ません。2026年にわざわざkvraudio.comまで見に行く人は滅多にいないはずなので、bskyのfeedに出てこないのでは意味が無い。しかも「フィードに投稿される記事はもしかして限られているのかな…」と思ってKVRのトップページと比較してみたら、なんと自分の投稿以外は全て掲載されていました。「自分の記事だけ排斥されている」というのは容認しがたい事態なので、もうKVR Audioには投稿しないと思います(運営体制の改善確認くらいの目的で投稿することはあるかもしれない)。正直20年前レベルのmarkdownも書けないWebフォームに記事を投稿するのも体験悪いので…
AAP AELAPSEとAAP ZLEqualizer
今月はひさびさにÆLAPSEというJUCEプラグインを新しくAAPに移植してみました。モバイルにもちょうどいいサイズです。
https://bsky.app/profile/atsushieno.bsky.social/post/3mqrzwg4t7k2r
これ自体は前々から移植しようと思っていたのですが、AELAPSEはJUCEのソースをCMake FetchContentで取得するスタイルで作られていて、aap-juceはどこにチェックアウトされるか分からないJUCEのソースツリーに対するパッチを当てるように作られていなかったので「後で余裕が出来たら…」と後回しにしていました。余裕ができたのと、これはAIに適当にやらせるべき仕事だと判断して終わらせました。
今月はもう1つ、ZLEqualizerのAAP移植も使えるようになりました。
https://bsky.app/profile/atsushieno.bsky.social/post/3mqfjgqboak2q
これは前々から移植されていたのですが、オーディオ出力に何も出てこない問題があって、やはり「後で余裕が出来たら…」と後回しにしていたものを回収した感じです。Fableの調査力で何とかなった…みたいな難題ではなく、単にjuce::AudioProcessorのオーディオバッファの使い方を修正しただけでした。Sonnetでも調べられたレベルでしょう。同じ原因でysfx effectも音が出るようになったので、他にも期待通りに動作しなかったエフェクトプラグインもありそうです。
aapval
ADC Japanに来ていたAndroidオーディオクラスタの知人に「auvalやpluginvalみたいなやつがあるといいんじゃね?」と言われて、なるほどauvalは使ったこと無いから知らんけどそうかもしれん、みたいに返していたのですが、AndroidManifest.xmlやプラグインメタデータのバリデーションはあってもいいだろうと思って、Codexに適当に作らせてみました。
UAPMD major fixes for AAP 1.0 Preview Release
UAPMDはAAP 1.0リリースにおいて「実際に利用できる実用的なプラグインホストがある」という立ち位置でアナウンスされる必要があり、そのために今月は「以前から問題は把握していたけど先送りしていて、リリース前にどうしても修正しておきたい」類の問題をいくつか修正することになりました。
track list minimap + zoom
uapmd 5.0時点でのタイムラインエディターの一番の懸念点が「まともにスクロールできない」と「Androidで全トラックが表示されない(!)」という問題でした。uapmdはシーケンサーエンジンとして機能さえすればとりあえず十分で編集機能はショボくても問題ない、というスタンスだったわけですが、公開されたアプリとしてまず目につくのはここなので、ここが使いにくいと致命的です。
タイムラインにはいろいろな操作が求められますが、今回は拡大縮小とドラッグによる移動をminimapにアウトソースするかたちにして、ImTimeline上での操作・機能をスリムダウンしました。ImTimelineが起点になって生じる問題はひと通りなくなったと思います。
Linux event loop + threading fixes
uapmd-appはクロスプラットフォームで問題なく使えることを前提に作られているのですが、Linuxでのプラグインの挙動はよく不安定になります。LinuxのプラグインUIをホストする際にはアプリケーションループをホストが握っているという前提で作らなければならず、ホストもたとえばVST3のIRunLoopを適切に使用してプラグインUIの機能を呼び出さなければUIがフリーズする、というかたちで問題になります。
UAPMD on Androidの場合、楽曲プロジェクトをデスクトップ上で作って、それをモバイルに移植すれば、プラグインの割り当ては別途やり直さないといけないにしろだいぶ省力化出来る、という特徴があって成り立つ側面があるので、Linuxデスクトップ上で作業していてまともにプロジェクトを構築できない、というのは放置できない問題です。何とか解決したようなので、安心してv0.5.1をリリースできました。
UAPMD minor fixes
AAPに影響のある修正ではなかったので後回しにしていたuapmdの修正や機能追加もいくつか施しました。
UAPMD WebCLAP instruments
UAPMDのWebCLAP版は、Instrumentプラグインがまだ動作しないと思っていたのですが、たまたまWebCLAPを使っている他のサイトを発見して、そこに独自プラグインがいくつか置いてあるのを見つけたので、早速uapmdでも使えるようにしてみました。その際にInstrumentプラグインが動作しない原因もAIに調べさせて(そもそもプラグイン呼び出しの実装は自分でやっていないのですが)、無事使えるようになりました。
UAPMD MIDI I/O connector
UAPMDはDAWらしい機能を実装して回っているのですが、元々UAPMD自身が仮想MIDIデバイスとして機能することが主目的のアプリケーションだったので、uapmd「が」MIDIデバイスに接続する機能は用意していなかったのですが、UAPMDに入力デバイスをマッピングして使える機能も必要そうだと思って追加しました。
UAPMDのトラックフリーズ実装とその下回り
UAPMDはモバイル環境で動かせることを目的として作られているので、少ないCPUリソース・メモリリソースで複数トラックを処理しなければならず、一般的なDAWよりもトラックのフリーズ処理の需要が高くなることが想定されます。そういうわけで、フリーズの実装に着手しました。
やる前は「まあオーディオファイルにレンダリングしておくだけだし大して難しくはないだろう」と思っていたのですが、蓋を開けてみるととんでもない…いろいろやることがあるな…という感じでした。
UAPMD document dirty state monitor(セーブ前の保存確認)
トラックのフリーズに着手する前に、それとは無関係に、ちょっとVST3のインターフェースで未実装のものがあったらやっつけておくか…と思って、IComponentHandler2::markDirty()が実装されていないことに気付いて実装しました。
そして、これを使う場面はどこにあるんだ…と考えて、そういえばアプリケーションの修了時に未保存のデータがあったらdirtyだから保存する、みたいなワークフローがuapmd-appには存在しない、と気付いて、これを実装しました。そして実際に実装してみると、特に開発作業中はこれが邪魔でしょうがないので、この機能を無効化するオプションを実装しました。現状自分がこの機能を使う場面は皆無です(!)
そして今月その他の各種機能を開発していて得られた教訓としては、このインターフェースがVST3でプラグイン側をsingle source of truthにしている諸悪の根源ではないか…というところです。ホスト側はこの通知を受け取ったら「プラグイン側に未保存の状態があるが、それが何であるかは知らされていない」という状態になります。あまり相手にしたくない状態です。
uapmd-engineでは、これが通知されてきたら、そのプラグインは要保存確認としてマークされます。トラックが追加されたりクリップが変更されたりしても要保存確認の状態になるので、状態チェックの一部という感じです。これは面倒だけど難しくはない作業です(AI任せ)。
UAPMD latency compensation manager
uapmd-engineには、今は単純なプラグインのリストと、DAGの、2種類のオーディオグラフの実装があって、ユーザーがグラフを編集しようとしたらDAGに切り替える、という仕様になっています。DAGのメリットはレイテンシー補償 (latency compensation) が機能する余地があるということです。複数トラックでオーディオ処理が行われる場合に、そのタイミングの違いから生じるサンプル単位のずれを補正できます。
単純な直線グラフではこれが実装できない(意味がない)ので、DAGがあって初めて意味を持つ実装なのですが、最短経路の計算や処理順序の差し替えなど、いろいろな作業が必要になってきます。DAGを実装してレイテンシー補償のためのAPIを生やしたとき、ADC登壇やAAP 1.0 Previewのリリースという優先タスクがあったので、そこまで実装しておらず、いろいろ積み残しになっていました。今月余裕ができたので、宿題を片付けたという感じです。
UAPMD tail process manager
トラックのフリーズ処理に着手し始めてから、レンダリングの最後がブツ切れになってしまう現象が発生しました。明らかに、最後のノートオフが送られたタイミングで、そのトラックの処理は終了したとみなされていたわけです。原理的には、プラグインのオーディオ処理には末尾処理 (tail processing) が行われている間はレンダリングを終了すべきではない、ということになります。tail lengthの取得はどのAPIでも可能なので(といってもAAPだけ未実装なのですが)、APIの共通化も実装も簡単でした。
この辺に手を加え始めてから、だんだんオーディオ処理が複雑化しすぎて、実装をAI任せにしていてもコードの追跡が手に負えなくなってきました。これは悪い傾向だと思ったので、レイテンシー補償や末尾処理のような高度な機能(何しろこれまで実装しなくても済んでいたわけです)については、オーディオ処理の拡張機能としてエンジン上にイベント等で登録して、拡張機能の処理は拡張機能のクラス内で終わらせる、というかたちで実現することにしました。これで数百行のオーディオ処理コードが拡張機能のほうに切り出せたので、自分の仕事に満足しています(自画自賛)。
UAPMD FrozenTrackManager
uapmd-appのフリーズ機能は、こういった下回りの実装の整備があって、初めて実現しました。たとえば、フリーズがいつトリガーすべきかというと、MIDIノートの変更やパラメーターの変更、クリップの位置やその他プラグインの設定変更、あるいはトラックのゲイン等の変更があった時、ということになりますが、これらが検出できないと、フリーズキャッシュを無効化できません。あるいは編集作業を一切禁止としても良いのですが、編集作業のフリーズを解除する操作を要求するのも、編集作業の発生を検出するのも、そんなに難易度の違いはありません。
フリーズ処理を実装するうえで壁になったもうひとつの機能は、プリセットのロードです。今月はUMPからのイベント処理にも手を加えて、プログラムチェンジからのプリセットのロードという処理が発生する場面を減らしているのですが、この処理はfire and forgetの非同期スタイルで実装されていたので、オフラインレンダリングではリアルタイム打ち込み時に想定していた「これくらい時間的ブランクがあればプリセットのロードは完了しているだろう」という想定ができず、プリセットのロードが完了しないままにレンダリングに突入してしまうという現象が発生してしまいます。
これは、ADC 2026でテクノスピーチの石井さんがVoiSona AUv3版の開発現場で遭遇した問題を紹介したセッションに出てきた話と同様です(まだ動画出てこないだろうなあ)。今回は、オフラインレンダリングの場面ではプリセットのロードは同期的に行うことにして解決しています。プラグインAPIによっては設定でレンダリングモードを指定できます。
トラックのフリーズ処理についてはそのうちテクニカルノートを公開するつもりですが、数十回のCodexとのやり取りと成果のお蔵入りを複数回繰り返して、ようやく実現しています。
ARA2 interoperability
6月にARA2のサポートに着手したときは、ARA2をサポートするOSSプラグインが見当たらないので放置していたのですが、7月にはTracktion Waveform14もARA2サポートを追加していたり、ACE StudioにもARAプラグインがあることに気付いたり、JUCEのARAPluginDemoが使えることに気付いたりしたこともあって、実装が少し先に進みました。
https://bsky.app/profile/atsushieno.bsky.social/post/3mrsmgj5u6c2i
ただ、Waveform14とACE Studioなどの組み合わせでも試してみた結論としては、これらのARA2サポートもそんなに先進的なわけではなく、ノートイベントの反映などは実現できていないようです。やはりARA3が出てくるまで待ってもいいかもしれません。
8月の予定
8月はCOSCUP 2026のために台湾に行くのですが、まだセッション準備が全然期待通りに出来ていないので(そのための実装の調整をいろいろやっている段階)、無駄にあたふたしながら過ごすことになりそうです。あと7月に勉強会を開催したかったのですが、リリース作業に想定の10倍くらいリソースを取られてすっかりタイミングを逃してしまいました。8月にできればやりたいと思います…