先月に続き2月も自分の開発に100%集中できていて、生産的な時間を過ごしています。といっても生産性の亡霊みたいに生きたい願望は皆無ですし、生産性を最大化して日々過ごしているわけでもないですが。
あとADC Japan 2026がいつの間にかCFPを出していたので1つだけ投稿しましたが、3/2まで時間があるのでもしかしたらもう2つくらい作るかもしれません。
正直どちらかといえばLinux Audio Conference 2026のほうが自分のあり方に近いので、そっちでしゃべったほうがいいのかもしれません。スケジュールを見る限りADCの採択からLACの締切まで1日の猶予があるので、落ちても再利用できそうですが、ちゃんとスケジュール通りに動いていれば…という前提がありますね。
UAPMD v0.2.0 and MIDICCI v0.2.0 released
2月中旬にUAPMDとMIDICCIのv0.2.0をリリースしました。実際には、v0.1.4を2月初頭にリリースして、その2週間後にv0.2.0をリリースして、実際にはちょっとやらかしててuapmdはv0.2.1をリリースしているのですが、まあ誤差でしょう。
UAPMD v0.1の主要なアチーブメントが「任意のオーディオプラグインをMIDI 2.0デバイス化する」にあるとしたら、v0.2は「マルチトラックのオーディオ / MIDI (2.0) クリッププレイヤー」を実現できたことをもって決定されたリリースです。SMF2 Container Formatはこういうフォーマットとして作られているはずなので、それを実現したものである、ということもできます。これを実現するために、UAPMD v0.2.0にはいくつか新機能が追加されました:
- プラグインにUMPイベントを送信できるSMF2クリップをトラックの一部として再生できるようになりました。SMF2クリップの送信対象はプラグインであり、オーディオクリップと並列に走らせることもできるので、エフェクトプラグインオートメーションに相当する処理もSMF2クリップで実現します。
- UAPMDプロジェクトファイルのロードとセーブ: SMF2 Containerフォーマットはまだ仕様が公開されていないので、独自形式で保存されています。
- SMF importer: SMFで制作された楽曲の各トラックをSMF2Clipに分解できる(保存はプロジェクト保存と同時に行われる)。これで既存のSMFファイルからSMF2ファイルをカジュアルに作成できるようになりました。
- マスタートラック: SMFでは明確な仕様ではないのですが、テンポや拍子の管理は1つのトラックに吸収して管理されています。管理といっても現状では全トラックから吸い上げているだけで、正直これを編集可能にするときにどうしたものかはわかりません。MIDI 2.0の場合テンポや拍子の設定はUMPの一部 (Flex Data) なので情報の保持は難しくないのですが。
- トラックのタイムラインのコンセプトがほぼクリアになりました。具体的には、オーディオI/Oからのオーディオグラフにおける位置付けが、再生時にはいったんトラックの内容から「今回のオーディオ処理に含まれるサンプルとイベント」を切り出して、プラグイングラフに渡す(プラグイングラフの構築と処理は実装次第)、というかたちが明確になりました。
- SMF2クリップの内容を表示するMIDIダンプリストを表示できるようになりました。
MIDI 2.0楽曲ファイルの作成と再生については、ktmidiにSMFをそのまま延長したような構成のAPIがあったのですが、UAPMDというかたちで音源というかプラグインホストを作成してみると、明らかにこの構成では足りないことが明白になったので、先月ktmidiからumppiとして取り込んだばかりのMidi2Musicクラスは消えて無くなる事になりました。
UAPMD & MIDICCI app design polish
UAPMDは元々GUIアプリケーションにするつもりが無かったこともあって、GUIとしての見てくれはUIテーマをBootstrapっぽいやつにしたりフォントをRobotoにした以上のことはしてこなかったのですが、MIDICCIと併せて今回はもう少し手を加えることにしました:
- Lightテーマ対応: ImGuiにデスクトップからlight/dark themeを判別する機能は用意されていないようなので手動切替になりますが、一応ホワイト中心の配色を用意しました。ただImTimelineの中は調べきれていなくてそこだけ暗いです(逆効果かもしれん)
- GUI上の機能が増えすぎて文字ボタンがスペースを取りすぎるのが無視できなくなってきたので、FontAwesome + fontaudioを使って画像で代用することにしました…のつもりが、fontaudioはまだ出番が来ていません(取り込みはしましたが)。カスタムフォントとしてImGuiに統合するのはjuliettef/IconFontCppHelpersと組み合わせてC++ヘッダー化したフォントファイルのリソースを使えば簡単…というわけでAIにC++ blob headerを自動生成させていたのですが、最近公開されたeyalamicmusic/ResEmbedを使うとさらにクリーンなかたちで統合できたので、公開が告知されたその日のうちに対応しています。
- アプリアイコン: v0.1の時点ではアイコンの類を何も用意しなかったのですが、アプリケーションとしてインストールできるようにしているわけだしもう少し実用品っぽくしておこう…と思って用意することにしました。とはいえ考えるのめんどいしどうしようかなあ…とぼやいていたらmuojpせんせいから天啓が…
bsky.app最近ClaudeでAndroid用のXMLアイコン描かせてるんですが、妙に味があって気に入ってしまい困る事案にw
— muo (@muo.jp) 2026-02-14T06:19:49.867Z
DroidKaigi 2025の関連セッションなどを見ているとわかりみが出てくると思いますが、完全にそれっぽい…!と思って真似してみました。おかげさまでそれっぽいものが生成できています:
VST3/AU host on macOS: every plugin loads
UAPMDの大きな弱点のひとつはremidyのプラグインホスト機能がjuce_audio_plugin_clientなどと比べると安定的にあらゆるプラグインを利用可能になっていなかったことでした。具体的には、Absynth5のAUがインスタンス生成に失敗したり、Kontakt 6/7/8のGUIがAUでのみクラッシュしたり、KORG M1やVienna EnsembleのVST3がインスタンス生成時にクラッシュしたりといった問題が起こっていました。
これらについては毎月のように修正を試みていたのですが、今月はついに自分の手元にあるプラグインについては全て解決しました(そんなに大量に抱えているわけではありませんが):
- Absynth5 AUとKontakt 6/7/8のUIを妨げていたのはAUのインプロセスモードの明示が原因でした(!) プラグインインスタンスの生成は時間がかかるので非同期の
AudioComponentInstantiate()で行うべきですが、その引数にkAudioComponentInstantiation_LoadInProcessを指定すると、インプロセスモードで実装されていないプラグインの機能が全て死にます。- Absynth5 AUが死んだ理由はこれがarm64ではなくx64のABIでビルドされた旧時代のプラグインであり、Rosetta2経由で動いていたため、別のプロセスでロードしなければならず失敗していた(クラッシュまではしなかった)ということになります。
- Kontaktのほうは、おそらくmulti outの機能を実現するうえで1つのGUIプロセスが複数のプラグイン インスタンスとやり取りするかたちになっていて、DSP側のインスタンスだけなら正常に動作できてもGUIを表示しようとした瞬間にAUのフレームワーク側から想定外のブロックを食らって死んでいたのでしょう。
- VST3のM1とViennaのほうは、単純にremidyのオーディオバス調整まわりでプラグインとの不一致が原因でした。
そんなわけで、VST3とAUのプラグインホスト機能は少なくともmacOS上ではだいぶ安定感が出てきました。とはいえ何もかもが動くようになったというわけではなく、CLAPプラグインではFloeが動かず、またLinuxではyoshimiが自分の知る限りでは動いていません。この辺はもう少し修正が続いていきそうです。とはいえ互換性地獄のプラグインホスト開発でここまで順調にいろいろ使えるようになったことを考えると、だいぶいい戦果を出しているのではないかと思います。
MIDI Message Report: The Latest Parameter Value Saga
先月の作業の最大の成果は、プラグインのパラメーターリストの動的な変更とホスト側への最新パラメーター情報の通知を何とか実装したことだったのですが、これがuapmd-appからmidicci-appへの通知となるとまだまだ完成していませんでした。これは、簡単にいえば「仮想MIDIデバイス生成時にはプラグインパラメーターの値が既に初期値から動いてしまっているため」です。同様の問題はuapmd-app自身がホストとしてプラグインのパラメーターの現在値を通知してもらう流れでも発生していました。
この問題を解決するために、仮想MIDIデバイスにMIDI-CI接続が新たに発生した時に、MIDI-CIの機能の一番目立たないMIDI Message Reportという機能を使って、現在のプラグインのパラメーター…に対応するAssignable ControllerとPer-Note Assignable Controllerのリストをmidicci-appからリクエストできるようにして、またuapmd-appもMIDI Message Reportに応答できるようにしました。
Process Inquiryの機能を実装しているのはktmidiとmidicci(とuapmd)だけなので、juce_midi_ci(と呼ばれていたモジュール)を使っていると実現できません。
あと関連項目として、UAPMDのAllCtrlListプロパティでは、パラメーターの最大値と最小値を指定するminMaxという項目を生成しなくなりました。これが指定されると、パラメーターのnormalized valueの値域が0..1からシンプルに0..UINT32_MAXに対応しなくなってしまい、ユーザーに余計な混乱を与えることになります。MIDIデバイスとしてやり取りするのは常にnormalized value、enumなどのdiscrete valueに変換するときも0.0..1.0にマッピングしていたのと同じことをする、という前提で再構成しています。
midicci diverged: UMP type migration from uint8_t to uint32_t
midicciはそのアイデンティティが「C++プロジェクトに組み込めるktmidi相当のMIDI-CI機能を実現するライブラリ」にあって、これまではずっと「ktmidiに新機能を実装し、それをコーディングAIエージェントに移植させる」というモデルで進めてきました。
このアプローチは現状でも破綻しているわけではないのですが、今月になってmidicciはついにAAPにも組み込まれるようになり…さまざまな問題が噴出しました。現時点でもAAPのMIDI-CI統合は期待通りに動作していません。uapmdとmidicciは2026年の今を生きる人類として開発が進められているライブラリで、libremidiなど2026年のライブラリを想定して設計されています。
ktmidiがUMPサポートを追加したとき、あるいはAAPがMidiUmpDeviceServiceサポートを追加したとき、それらのAPIが念頭に置いていたのは「MIDI 1.0とのシームレスな互換性」でした。そのため、これらのAPIはMIDI 1.0のAPIと同様、1バイト単位(kotlin.Byte, uint8_t)でUMPを受け渡しています。これがlibremidi、ALSA、CoreMIDIなどとデータのやり取りをする場面ではuint32_tなど4バイト単位の受け渡しが必要になります。この変換は単なるポインタのキャストではうまくいきません。なぜならエンディアンネスの問題が発生するためです。UMPのuint8_t*のストリームとしては40 90 2B 00 F0 00 00 00のように渡さないといけないのに、4バイトのlittle endianのメモリには00 2B 90 40 00 00 00 F0のように格納されているためです。こういった複雑な前提の違いは、特にコーディングAIがすぐ間違えます。人類も間違えるでしょう。
そういうわけで、midicciはUMPを扱うAPIの一般的な潮流に合わせて、uint8_tからuint32_tの単位でUMPを表現することにしました。これは結果的にktmidiに追従する開発方針からの転換ということになります。まあ実際これで困ることはもう無いでしょう。midicciの実装は、可読性はともかく、挙動としてはだいぶ信頼できるコードになってきました。
ktmidiもそのうち追従するかもしれませんが、ktmidiのほうをいじっている暇がないので、しばらくは現状の1バイトAPIを維持することになりそうです。
UAPMD: U is for Ubiquitous
UAPMDは特にWindowsがMIDI 2.0をサポートしていない現状ほぼLinuxとmacOSで動かすために作られたものですが、次世代プラグインホストに相応しい立ち位置を実現するために開発しています。これは特にAndroidを含め「デスクトップ限定のホスティングライブラリで終わらない」という側面があります。UAPMDのUはubiquitous(遍在)のUであり、元々は「どんなオーディオプラグインでも」UMPデバイス化する、という意図だったものですが、今月はさまざまなプラットフォームで動かせる可能性が見えてきました。
uapmd-android
まずはAndroid版です。リポジトリはuapmdに統合される可能性がありますが、とりあえずは独立して作られています(雑にAndroid Studio Pandaで作られていますがAGPのバージョンさえ調整すればNarwhalでもいけるはず):
どのプラットフォームでも一番問題になるのは「ImGuiが動くかどうか」ですが、Android上ではSDL3 on Androidがそこそこ本気で作られているので、この上で動かしています。SDL3 on Androidは特にSDL3のメイン開発者が積極的にコミットしていることもあって、今後が期待できそうです。ただ現時点では「SDL3のメインスレッド」がAndroidのメインスレッドではないという問題があって、挙動が安定しません。Flutterがv3.29で大改修を実現したやつと同根ですが、こちらは単なるリグレッションのようなので、そこまで時間がかからずに直るかもしれません。
Android版のuapmd-appは、ImGuiアプリケーションとしては概ね問題なく動いていたので(最近はやや不安定でしたがこれはuapmd-app本体が不安定という可能性が高いです)、新たにPluginFormatAAPのAPIを作ってmainブランチにも取り込まれていますが、まだプラグインの列挙から先は未確認です。というのも、現状uapmd-appはファイルをロードできないとプロジェクトに取り込むことすらできないわけですが、AndroidでファイルI/Oというわけにはいかないので…

uapmd on Windows
次にWindows版です。Windows MIDI Servicesがついに出る出る詐欺を脱して正式リリースされそうということもあって、だんだんこの界隈が賑やかになってきました。先月libremidiの仮想ポートサポートがまだ出来ていないという話を書きましたが、今月になってこのissueにmicrosoft/MIDIの設計開発者も参戦してきて、実装されたけど動作確認できない〜、みたいな状態で来月に持ち越しそうです。
Windows版はまだまだ全体的に安定しないのですが、プラグインホストまわりでは大きく2つの修正を加えた結果、そこそこプラグインが使えるようになりました:
- Native Instrumentsのプラグインが全て使えていなかったのですが、これはVST3のバンドルで呼び出すべき
InitDll()ExitDll()の関数名が間違っていたのが原因で、これらを修正したら正しく使えるようになりました。 - 先月までImGuiのバックエンドがGLFWだったのですが、まずSDL3を使うようになり、さらにDirectX11を使うようになり、その後安定性の観点でSDL3に戻ったものの、プラグインUIの描画に問題が出たため、現時点ではDX11に戻っています。SDL3の描画問題はかつてはmacOSでも出ていたので、似たような問題で解決可能かもしれませんが、現状DX11もSDL3も同じくらい不安定なので、今後DX11からさらに動くかはわかりません。
uapmd WebAssembly build
現状まだ本気で取り組むつもりはないのですが、uapmdにはEmscriptenビルドも存在していました。ただ古いブランチのままで、その後のuapmdの成長に全く追従していなかったため、mainブランチに取り込めるようなものではありませんでした。今週ちょっとCodexのトークンが余りすぎていたので一念発起して「ちゃんとmainブランチに取り込んで維持できる」前提のものを作ろうと思い至って、何とかCodexのweekly limitの範囲内で実現できました。

wasm版では意外にもchocのAudioFileReaderが(基本的にファイルI/Oで動いていたのでそのまま動かないのは当然として)iostreamでも期待通りに動かないという問題が出て、miniaudioの組み込みAPIでようやく再生できる(miniaudio自体はWeb Audioバックエンドもサポートしているのでそのまま使える)が、flacは再生できてもoggが再生できない…という事態に陥っています。
また当然ですがwasm版では現状利用可能なプラグインフォーマットが無く、WebCLAPかもしかしたらWAM2が今後サポートできるかどうかわからない状態にある、という感じです。どちらもプラグインを列挙するAPIがまだ無いはず。
AAP midicci integration
AAPには元々ktmidiを利用してMIDI-CI機能を実現するつもりでした。これを実行に移していなかったのは、Kotlinで実装してしまうとMIDI-CI処理をAAPから操作したい場合にややこしい事態になると想定されたためです。この考え方がmidicciの成長を見ていくうちに変わってきました。midicciを使ってAAPのC++実装から調整したほうがuapmdに近いことが出来そうな目論見が立ってきたので、ktmidiの代わりにmidicciを使うルートで実装することにしました。
ただ、midicci-appが存在しているデスクトップ環境とは異なり、midicci-appはまだAndroidに移植されていないので、接続確認にはktmidi-ci-toolを使っています。これがまだAAPのmidicci統合と相互接続できず、まだ試行錯誤している段階です。AAP側にも、インスタンス生成時にパラメーターリストを取得できない問題などがあり、AAPもいろいろ再設計したいという気持ちが高まってきました。ただそれは抜本的な再設計になるので、UAPMDが落ち着いてからがっつり時間を取って着手したいところです。
3月の予定
11月から3ヶ月ほどuapmdとmidicciに集中できていたのですが、4月には技術書典20とM3 2026春があるので、新刊の準備をしないといけなそうです。プラグインホストの設計解説書あたりが良いかと考えていたのですが、Windows MIDI Services正式公開の流れに乗るならMIDI 2.0総合開発本あたりが良いのかもしれません。まあ来月末には告知できる段階にあろうかと思います。


