以下の内容はhttps://atsushieno.hatenablog.com/entry/2025/10/31/222731より取得しました。


10月の開発記録 (2025)

年初に「このフォーマットで書き続けるのもどうかと思う」とか書いておきながら気がつくとほぼ1年終わりつつあるわけですが、とりあえずこのスタイルで書きます。

今月はM3 2025秋がありましたが、結局同人誌の執筆には割かず、デモ展示という名目でオーディオプラグイン仮想MIDI 2.0デバイス化プロジェクトであるところのuapmdとUMPキーボードであるところのmidicciを大改造していました。uapmdの大改造というか、どちらかといえばプラグインホスティング機能の拡充がメインだったといえます。そんなわけで、今月はuapmd + midicciの話しか無いのでその各論を書きます。全体像についてはM3直前に記事を書いて公開したので、そちらを見てもらえればと思います。

zenn.dev

uapmd-service: GUIコントローラー

uapmdの当初の構想では、uapmd-serviceがheadlessな仮想MIDI 2.0デバイスの実態として動作して、それとは別にuapmd-setupというGUI管理コンソールがプラグインの列挙とMIDIバイス起動・終了などを担当する予定でした。しかしuapmd-serviceは将来的には全デバイスを1つのオーディオエンジンで処理したほうが良いですし、GUI機能はImGuiで作成したremidy-plugin-hostのものを使い回せそうだったので、CodexとClaudeにGUIを作らせることにしました。現状これはそれなりにうまく動作しています。

ただ、GUIアプリとしてUIとロジックの分離などをそれなりにきれいにやってきていたのですが、プラグインUIのサポートを追加してきたあたりから、この辺の切り分けに気を配らなくなっているので、どこかしらの時点できちんと仕切り直す必要がありそうです。

逆にこの辺が雑に作られていたJUCEは、次のバージョンでどうやらjuce_audio_processors_headlessという新しいheadlessモジュールを追加するようで、近年のJUCEのリアーキテクチャの動きは(たぶんJUCE6の時に加入したリードデベロッパーの采配だと思いますが)とても良いですね。これでjuce_audio_plugin_client_headlessも出来てくれれば(やや高望み)、オーディオプラグインのテストをCIなどのheadless環境で自然に行えるようになるかもしれません。

remidy: プラグインUIのサポート

今月の目玉は何と言ってもプラグインGUIサポートの追加でしょう。プラグインUIが無いと人間にはパラメーターを意図したとおりに操作できませんし、まだろくに動作確認できていないStateの操作も、GUIで操作することでようやく意味を持ってくるといえます。uapmd-serviceがGUIを表示するようになって、インスタンスの細かい制御が可能になったので、GUIサポートを追加する時が来た、という感じでした。

新しく作られたuapmd wikiには、これまでblueskyで投稿してきた数々のスクショが掲載されています。現時点で「GUIだけが正常に動作しない」ものは、手元で確認できているのはVaporizer2くらいです(と書くと大変完成度が高いように聞こえますが「そもそもプラグインインスタンス生成に失敗する」ものが多数なので、それほどではないです)。Vaporizer2は多分GL ContextをホストのImGuiとの間で取り合っているんだろうと思いますが、OpenGLベースのVitalなどは正常に動作しているので、要調査ではあります。

GUIサポートの実装は、実のところほとんどCodexとClaudeにやらせています。共通APIとしてCLAPライクなAPIを定義して、「これをVST3で実装して」といった感じで実現させています。当時はVST3SDKではなくDPFのTravestyのAPIで書かせていて、最初はVST3SDKを無理やりC APIで実現するTravestyの流儀にClaudeもかなりやられていましたが、きちんと説明すると理解できたようです。TravestyのAPIを使ったコードなどはほとんど存在しないはずなので(特にホスティングで利用していたのは自分だけではなかろうか)、agentic codingでもこの程度は実現できるんのか、と試験利用の可能性を広げることになりました。今月だけでVST3, AU, LV2, CLAPの全フォーマットで最低限のshow/hideとデフォルトのsizingを実現できていて、だいぶいい仕事をしたと思います(自分が)。

uapmd: UMPデバイスとしてのポート再編成 (ongoing)

uapmd-serviceはこれまで、DAWライクなトラック編成を内部的に想定していて(複数トラックのサポートが実装できているわけではないのですが!)、それぞれのトラックに複数のプラグインを差して、トラックごとに1つの仮想UMPデバイスを作成する、というスタンスで作られてきました。

これまでは空想上の産物でしかなかったのですが、uapmd-serviceで複数トラックを簡単に作成できるようになったので(AIに実装させることができたので)、このまま1つのトラック上に複数のプラグインDAWのトラックのように差せるようにしよう、と実装させてみました。それで気付いたのですが、このトラック単位でプラグインのパラメーターを操作するとなると、トラックの最初に差されたシンセのパラメーターしか変更できないことになってしまい、そのトラックの以降のエフェクトプラグインの操作ができません。

これらを操作できるようにするにはどうすればいいのか、設計を見直す必要がありました。AllCtrlListやProgramListといったプロパティによって、プラグインのパラメーターを取得できることが必要ですが、Function Blockを切り分ける必要があります。さしあたって現時点ではそもそも仮想MIDIバイスを複数立てて、操作はそれぞれの仮想MIDIバイスに対して行う、オーディオプラグインのトラックとしては1つ、というかたちになっていますが、プラグインインスタンス数だけ仮想MIDIバイスが生成されるとものすごいことになりそうなので(これは30トラックくらいの楽曲でもそうですが)、早々に元の1トラック1デバイス構成(あるいはそれ以上に圧縮)というかたちに戻すかもしれません。

プラットフォームMIDI APIバッファリングとの格闘 (ongoing)

uapmdとmidicciは、実のところktmidi-ci-toolと比べてだいぶMIDI-CIメッセージングが安定していません。下回りはどちらもlibremidiなので割と不思議ではあるのですが、midicciはそもそもagentic codingの産物なので、いろいろ完成度が低い可能性はあります。もっとも、ktmidi-ci-toolが試験的な用途でしか動作確認されていないのと比べて、uapmd-serviceもmidicci-keyboardもreal-world appsなので、単純な動作テストではハマらなかったような問題が発生することがあります。

たとえば現状でVitalのUMPデバイスを作成してAllCtrlListを生成すると、メガバイト単位のProperty Exchange JSONのやり取りが発生することになります。デフォルト値を極限まで最適化してMcoded7などを採用したりすれば、少しデータ量を抑えることが可能かもしれませんが、大前提として大容量データの送受信は問題なく行えるべきです。今月発見した問題のひとつは、プラットフォームのMIDI API(あるいはそれをラップしたlibremidi)の内部では有限のリングバッファが用いられているはずなので、それを超える大きさのチャンクを送受信することはできない、ということです。こちら側の実装は仮想UMPデバイスなので、31,250bits/sec.みたいな制約はありませんが(仮にMIDI 1.0の物理ケーブルを前提としたシステムのように1秒間に3000バイト超しか送信できないとすると、1MBのMIDI-CI JSONを送信するのに300秒以上かかることになり、実用性がありません)、プラットフォーム側でリングバッファを送信しないうちに次のチャンクを送りつけると死ぬ可能性があるので、現在はある程度のスロットリングを行っています。

いろいろな問題の切り分けと改善は行っているのですが、この領域は現在進行形でハマっている問題で、少しずつ改善していくしか無いと思っています。一番の問題はテスタビリティが無いことですね。CI環境にプラグインをセットアップする仕組みを作らないとなあと思っています(これはこれで大仕事)。

remidy: travestyからvst3sdkへの移行

10/20にVST3.8.0が公開されて、MITライセンスに変更されましたね。これについては今日、大掛かりな記事を書いて公開しています(だいぶ苦労した)。

zenn.dev

remidyはMITライセンスでリリースするためにvst3sdkを回避してtravestyを使い続けていたのですが、基本的にはC++のプロジェクトですし、vst3_public_sdkAPIなどもそのまま使えるほうが良いので、travestyに拘り続ける理由は特にありません。というわけで、勢いで全てvst3sdkに移行させました。Claude Codeで。travestyのAPIくらいならほぼ資料が無くてもVST3 APIからの推測でいろいろ自走できることは先のGUI実装で体験済みだったので、vst3sdk APIへの移行程度の「機械的な作業」なら処理できるだろうと踏んでやらせました。一部コードを読み落として移植コードが動かなかった等の問題は発生しましたが、人間がやっても同じことに(あるいは多分もっとひどいことに)なったでしょう。

プリセット実装の再整理

先月VST3 ProgramListの設計をいろいろこねくり回していて「これは無理かも」と半ば投げ出していたプリセットの問題ですが、今月LV2、AU、CLAPの3フォーマットでそれぞれ実装してみました。AUを除いてはプリセットのサポートは鬼門で、CLAPは特にpreset-factoryのAPIからしっかりサポートしているプラグインがほとんどありません。Six-Sinesですらソースコードのレベルで無効化されているレベルです。LV2もURIで識別するので安定的な番号を振れず、プログラムチェンジとの相性は良くありません。とりあえずAUだけは単なるAudioUnitGetProperty()の延長線上でいけるので、サポートしてあります。Dexedがmidicci-keyboardでプログラムリストから音色を選択できる状態です。

uapmd-serviceではなくremidy-plugin-hostのレベルでは、LV2プリセットもロードできています。Audible Planetsのプリセットなんかが選択可能です。VST3はプリセットは列挙できるもののロードに失敗する状態で放置されています。この辺もいろいろ手が空いた時に埋めていく感じになりそうです。

公開プロジェクト化

uapmdとmidicciは、ここに書いているのを除いては、ほぼ空気として進行してきたのですが、今月はM3の展示物として公開して、ついでに翌日行われていたAMEIのMIDI meetupでもちょろっと見せて回っていて、少しずつ公開プロジェクトっぽくなりつつあります。現状使えるプラグインが限られているので、まだまだ実験用という感じではありますが、動作するようになったプラグインも少しずつ増えてきています。今月は特にSerum2が問題なく使えるようになったのが割とターニングポイントだったと思います。これはGUIサポートつまりIEditControllerまわりの実装の足りない部分を埋めていた(埋めさせていた)時に改善された部分だったので、今月は空き時間を見てオーディオ処理やバス調整まわりも改善させてみようと思っています。今のところNative Instruments製品がだいたい死んでいるので、これを何とかしたいですね。

11月の予定

11月はADC 2025が開催されるので、ブリストル会場で参加してくる予定です。そこからダッシュで帰国して技術書典19で出展予定です。観光する暇が無い…! まあ今年はKotlinConf, LAC, ADCとカンファレンス参加しすぎなので、観光は来年どこか他でのんびりしよう…と思っています。




以上の内容はhttps://atsushieno.hatenablog.com/entry/2025/10/31/222731より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14