4月のmusic tooling hacks

4月というか平成も終わろうとしている今日この頃ですが、相変わらず時代をまたぐ無職生活エンジョイ勢です。相変わらず謎の方向性でコードを書いています。そんなわけでこのひと月くらい?のコーディング活動を雑にまとめます。

JUCE/VST3/Linuxの高い壁

楽曲制作環境の改善手順として、SMFベースのMIDIプレイヤーからオーディオプラグイン中心の音源ドライバーに移行しようと思っているのですが、2019年はLinuxデスクトップ開発者にとってたいへん難易度の高い年です(断言)。

昨年からSteinbergがVST2 SDKを廃止してダウンロードできない状態にしてしまい、VST3 SDKのみが入手可能な状態になったのですが、VST3 SDKGPLで入手できるものの、各種のネイティブVST*1プラグインDAW等のホストアプリケーションが追従していない状態です。VST2とVST3は根本的に別物に近いんですよね。

特にJUCEを使っているプロジェクトが、ホストもオーディオプラグインも全滅です。JUCEはLinux版VST3に対応しておらず、公式フォーラムに「おいおいLinux用VSTプラグインを作れると思って使ってきたけど詰んでるじゃん?」というスレッドが立っている状態です。 割と新鮮なUI設計で面白いhelioシーケンサーも、Waveformで使われているtracktion_engineも、Googleのmusic-synthesizer-for-AndroidベースのDX7互換FMシンセサイザーDexedも、サウンドフォントが使えるjuicysfpluginも動きません。*2

JUCEのプラグインならLADSPAでビルドすれば動くんじゃん?とか思うわけですが、dexedみたいにJUCE 5.2.1くらいのソースを取り込んでいるやつではProjucerでちょいちょいっとjuce_audio_processorsをいじってもVST2が無いだけでビルドエラーになるみたいな理不尽な状態なので、VST3でちゃんとビルドできるようになっていないとメンテナンス出来ない状態になるなあと思います。

そういうわけでたまにJUCEのソースを読みながら、Linux上でVST3を使えるようなブランチを作ろうとしているのですが、ちゃんと動くものが出来るまでには時間がかかりそうな気がしています。その間に本家で対応していてほしいけど、先のissueにsurprisingly difficultなどという供述があり…。JUCE、外部からのcontributionを受け付けない伽藍プロジェクトなので、今後こういうフレームワークに乗っかっていくことにはLinuxデスクトップユーザーとしては危機感があります。

オーディオプラグインフレームワークとしては、VSTの他にもLADSPA V2 (LV2) などがあって、各種ホストでこっちが標準でサポートされるようになってほしいところです。ちなみに今のところVST3をLinux上のDAWで使おうと思ったらBitwig StudioかArdour5訂正: 対応していると思っていたけどLXVSTのみでしたという選択肢しか無いと思います。Bitwig Studioえらい。

f:id:atsushieno:20190430211123p:plain

このスクショはJUCEのextraにあるAudioPluginHostなのですが、リストアップされているオーディオプラグインの中にVST3が含まれているのがミソです。juicysfpluginはguiが表示できなくて詰むのですが、mdaほげほげの類は音も出てGUIも表示され、パッチを作っていた自分がまずビックリでした…

fluidsynth-midi-service-j

github.com

先月までずっとfluidsynthのAndroidビルド用forkを本体にマージするための開発にかかっていたわけですが、ひと区切りついたので、Androidアプリケーション側の開発にシフトしました。まだ最初だけノイズが乗るみたいな問題があるのですが(ゴミのあるオーディオバッファが再生されている、だけでもなさそう…)、それなりに使える状態のアプリにはなってきたと思います。proof of conceptレベルでもちゃんとJava/Kotlinでアプリ開発するのはx年ぶり(思い出せない)なので*3なので、AACやらdata-bindingやらconstraint layoutやらをごく当たり前のように使ったり、DeployGateにも数年ぶりにうpしたりと、今らしいスタイルで開発できるのは新鮮です。これはこれで楽しい〜

先月の時点では単に和音を鳴らすだけのボタンがあるMainActivityしか無かったのですが、fluidsynth初期化設定をUIで調整できるようにして、Oboe/AAudioのLowLatencyモードやExclusiveモードも試せるようになったので、この辺に興味のある人にとってはちょっと楽しい感じです。

あと先月ノリでmanaged-midi (C#) から移植したKotilnのktmidiが、主にbyteのsigned/unsignedまわりとIntへの型変換を含めた比較で大爆死だったので、ちゃんと動くように全面的に手を加えて、SMFもちゃんと再生できるようになっています。KotlinにはexperimentalでunsignedTypesというのがあるのですが、仮にそれがkotlincまでシームレスに統合されるようになっても、Int定数との比較などでIntへの型変換などが必要になってくると、常にunsignedなのか否かを意識したコードを書かなければならず、KotlinでMIDIアプリケーションを安全に書くのは極めて難しいのではないかと思うようになりました(experimentalが外れてUByteの定数が書けるようになれば、この問題は少し緩和されることでしょう)。少なくとも、MMLコンパイラをKotlinに移植しようという気持ちはなくなりました。

あとアプリで実践的にfluidsynthを使うようになった関係で、ちゃんとSF3 (compressed soundfonts) をサポートするためにlibsndfileをビルドできるように本家fluidsynthに変更を加えたり、bitriseやローカルのdockerでビルドを確認できるようにしたり、といったこともやっていました。Android用fluidsynthがビルドできないという問い合わせ、地味によく来ていたので…(しかもなぜかメールが多い)。

あとこの方面の問い合わせに連動して北米方面のDAWの開発会社からうちで仕事しないか?みたいなのが来て、ktkr! とか思って前向きに返事したのですが、「よっしゃ連絡するわ」という返事を最後に通信途絶した()ので相変わらず無職です。(どうでもいい)

英語では他にもいろいろ書いたのですが(Android Native MIDI APIの話とか)、めんどくさくなったのでこっちでは省略します(何)。

soundfont-player-cs

github.com

MIDI中心からオーディオプラグイン中心の制作環境に移行するためには、スムーズにリズムパートを打ち込めるような環境と音源が必要です(前回のイベントで頒布した作品では、実はリズムパートが皆無に近いんです)。これまでもMMLで打ち込んできていて、ノートベロシティを踏まえた打ち込みは簡単だし、DAWでやると面倒くさい3連符もごく簡単に打ち込めるし、MMLでの打ち込みで続けたいのですが、手元にあるSC-8820にある音は限られていて、リズムパートを希望通りの音色で打ち込むのは無理ではないかと思うようになりました。

オーディオプラグインであればSerumとかEZDrummerとか、手元にあるだけでもOmnisphereとかBatteryとかあるわけですが、Linux環境で使えるものがほしいわけです。ドラムパートくらいならサウンドフォントでもいけるのではないか(加工系のプラグインならLADSPA等でいろいろあるし)と思ったのですが、サウンドフォント自体は大量に手に入る時代とはいえ、それぞれのサウンドフォントにどんな音があるのかを簡単に知る術がないぞ…と思ったわけです。

とりあえず、GUI上に手持ちのサウンドフォントにある音色(プリセット = プログラム / バンク)のリストをありったけ表示して、選ばれたやつを広大な鍵盤リストのようなものに表示して、どこでも叩けるようにしたら、音色の確認は簡単にできるようになるのではないかと思って、Xwt, Fluidsynth, NAudioを組み合わせてざっくり作りました。意外とこういうツールが無いんだよな…

f:id:atsushieno:20190430204056p:plain

やっている事自体は難しくないので、それこそ仕組みだけならWeb Audioとかでも作れなくはないのですが、サウンドフォントはファイルがでかいのでWebには向いていません。サウンドフォントに限らず、音楽系ツールは膨大なデータを伴うことが多いので、全般的にWebには向いていないですね。ローカルに各種リソースがあることが前提になると思います。

今回はたまたま C# で組みましたが、既にUIにかなり不満があって(特にListViewあたり)、これを解消するにはもう言語ごと他所に引っ越すしか無いかなと思っているのですが、なかなか自分の需要に合うものが少なそうです。とりあえずQML.NETあたりを試してみようかなとは思っています(これもnugetパッケージ版のLinuxビルドがおかしくて試せなかった)。

managed-midi: CoreMIDI on .NET Core, etc.

もうひとつ、managed-midiの話なのですが、ひとつ長い間どうにかしたいと思っていた問題が解決しました。.NET Frameworkや.NET Coreのプロジェクトでmanaged-midiを使うと、Macで使えるネイティブバックエンドが無いという問題です。

MIDIアクセスはプラットフォーム固有のAPIアクセスが必要になるのですが、Mac上のCoreMIDIを使うにはXamarin.Macに依存するしか無かったわけです。そうするとプロジェクトそのものがXamarin.MacのProjectTypeGuidを前提とするものになり、デスクトップ用のmonoを使ったり(.NET Frameworkが全体的にdeprecatedになりそうなので忘れられているかもしれませんが、.NET Coreの範囲を超えるデスクトップ用アプリを作ろうと思ったらmonoを使うことになるのです)、.NET Coreを使ったりということを考えると、Xamarin.Macは難しくなってきます。Xamarin.Macにはfull profileがあって、これはnet4x互換なのですが、いずれにしろわたしがLinux上でビルドするときに「無いとビルドエラーになる」ようなものでは困るわけです。

いろいろ考えた結果、もうXamarin.Macに含まれるCoreMIDI API相当の部分を自前実装しちゃったほうが早いだろう(これ自体はMonoMacで実現していたわけだし)、となって、今のmasterには実装が含まれています。IMidiAccess APIを実装する範囲の最小限のもので雑ですが。

これで自分のプロジェクトがちゃんと単一バイナリでもクロスプラットフォームで動作するといえる状態になったので、気が向いたらバイナリパッケージも作るかもしれません(managed-midi自体はずっとNuGetで配布しています)。

あと最近はWindows方面の開発者がUWP実装やwinmm実装のissueを報告してくれたりパッチを送ったりしてくれているので、managed-midiユーザーいたんだ…?みたいな気持ちでありがたくcontributionを受けています。自分が普段全然使っていない環境をケアしてくれる開発者がいるのはありがたいですね。

残っている課題?で多く来るのが「Unityで使いたい」なのですが、どうしようかな…Unity普段使っていないし、今さら.NET方面に時間使うのもったいないな…という感じで「やる気があったらcontributeしてくれ〜」みたいな感じで雑に返しているのが現状です。(モバイルまわりになると割と大変なので自分で作ってあげたほうがいいのかなーみたいに思ったりはしますが…) MIDIJackとかで対応してくれればそっちに誘導するんだけどなあ。

managed-midiの仮想ポート作成API

あと、仮想MIDIポートを作成するAPIを追加したので、これを関連プロジェクトであるところの仮想MIDIキーボードアプリxmmkでMIDI入力用ポートを追加して、Tracktion Waveformから接続して譜面に入力をペーストできるようにしました*4

実のところ送信内容をキー入力に限定する必要はなく、xmmkにはmugene MMLコンパイルしてMidiPlayerでバックグラウンド演奏できる機能も追加してあり、この内容を仮想入力ポートに送るだけでDAWMMLからペーストできるようになったともいえます*5。ピアノロールに打ち込めるのもまあ面白いのですが、一番「これは便利」と思っているのは、DAWから開いているオーディオプラグインで試しに音を出すとき、自分の好きなように入力UIを設計できることですね。物理MIDIキーボードと違って、ソフトウェアMIDIキーボードならいくらでも工夫の余地があるので…

ちなみにCoreMIDI APIでの実装はまだ何やら機能せず、WinMMには仮想ポートを定義する機能そのものが無いので対応しません。UWPは知らんけど多分無いんでしょう。

f:id:atsushieno:20190430211756p:plain

that's all

とりあえずこんなところでしょうか。本当はもっと音楽制作とかやって遊んでいるつもりだったのですが、ちょっと易きに流れてしまった感じで割と反省しています。来月はもちっと打ち込みに興じたいところです。(フラグ?)

*1:ユーザーとしてLinux上でVSTを動かすアプローチは2つあって、ひとつはLinux用のビルドを使う方式、もうひとつはwineを利用してWindows用のバイナルを動かす方式です。後者は商用のめんどくさいやつ(Kontaktとか)が全く使えないので、VST開発者にとっては前者のサポートが必須といえます。

*2:正確にはjuicysfpluginなどは古いJUCEを依存関係に含んでいるのか未だにビルドできるのですが、ライセンス的に配布できなくなっている状態です。

*3:ここでも何度か書いているかと思いますが、フレームワーク開発者がアプリを開発しない問題…

*4:特別にコードで実装しなくても、OSの機能としてMIDI Throughなどのポートにroutingかければいけたのですが

*5:個人的には楽曲の「土台作り」をDAW上でやりたくないので、ここに大きな可能性はあんまり見ていません