目次
4月頃に、自作オーディオプラグインフレームワークのUI構想についていろいろ検討していて、SFZサウンドフォントのARIAまわりを取り込んでsfizzというSFZサンプラー(プラグイン)に統合したいという話を書きました。
これをaria2webというプロジェクトとして開発して公開しています。まだ実用品ではないのですが、いろいろ知見があったので今のうちに書き連ねておこうと思います。
aria2webは、ひとことでまとめると、ARIA GUIをHTML(+SVG+JS)化して、WebViewが使える任意の環境でオーディオプラグインのGUIとして汎用的に使えるようにしよう、というものです。
動機: なぜSFZを使うのか
オーディオプラグインフレームワークを作る目的は、音楽制作・再生のためのエコシステムを構築することです。古典的なDTMでは「楽器」に相当するのはMIDI音源でしたが、MIDI (1.0)の表現力では自由に思ったとおりの音楽を表現できないことが多いので、現在ではオーディオプラグインを使うのが一般的です。
オーディオプラグインには(ちょうざっくり分けると)楽器とエフェクターがあって、自分のフレームワークでは、とりあえずproof-of-conceptレベルではVSTのサンプルとして使われてきたmdaがLV2に移植されたmda-lv2が、すでに動いています(何しろLV2が実質無修正で動くので)。また、JUCEのプラグインにちょっとモジュールを追加するだけで対応プラグインがビルドできるので、それで取り込めるプラグインもいくつかあります。(UIをホスト側で出すのは現状では無理だけど模索中です。)
楽器のほうもfluidsynthをオーディオプラグイン化したjuicysfpluginやsfizzを使えばいけるはずです。juicysfpluginはJUCEソリューションなのですが、内部的にはgtkにも依存していてちょっと使えないし(ここ後で触れる予定)、SF2/SF3のFluidsynthより表現力の高いSFZをサポートしたほうがより本格的な楽器プラグインを実現できる(何しろFluidsynthはMIDI 1.0のレベルなので)と考えてSFZとsfizzのほうを主なターゲットにしています。
SF2/SF3もSFZも同じ「サウンドフォント」ではないのか、何が違うのか、と思われそうですが、SFZにはキースイッチ*1のサポートなどで、SF2/SF3より柔軟な条件式で対応するサンプルを選択できるようになっており、本格的に楽器を表現できるフォーマットとして現在も進化しています。(独自拡張から標準化に進む世界であるようです。)
オーディオプラグインの世界では「サンプラー」というジャンルがあって、サウンドフォントの再生エンジンはこのカテゴリーに属することになります。サンプラーとして有名な音源はKontaktとかVSLとかです。Cubaseに付いてくるHALionとか、わたしが使っているWaveform付属のCollectiveなんかもそうですね。SFZにもこれらの商用音源に匹敵する機能を実現できるポテンシャルがあります。
自分のオーディオプラグインフレームワークでKontakt並の音源を実現できるとしたら、だいぶ「エンドユーザーが使いたくなるもの」なのではないかという気がしてくるのではないでしょうか。
ARIA GUIとは何か
SFZはSF2/SF3より詳細な条件式でサンプルを選択できるという話を書きましたが、条件式の記述に用いられるのはopcodeと呼ばれる命令識別子であり、要するにごく単純なプログラムを書いているようなものです(プログラムの著作物とまでは言えないレベル)。SFZのopcodeは特に技術標準とまで言える仕組みではなく、これを各サンプラーのベンダーが独自拡張して使っていることがあります。
ARIAというのは*2、Plogue社のsforzandoというサンプラー製品で使われている独自拡張ですが、これにはSFZのopcode拡張の他に、GUIを定義するXMLマークアップのボキャブラリーも含まれています。SFZの仕様にはGUIの定義が含まれていないので、SFZのサンプラー音源をいじるときは数値と格闘するか、標準的なコントロールを操作するしかないのですが、どのパラメーターが重要なのかはユーザーには分かりません。GUIがあればこの問題が緩和されます。
<GUI w="775" h="335"> <StaticImage x="0" y="0" w="775" h="330" image="Main/Control.png" transparent="1" /> <Knob param="20" x="53" y="168" image="Main/Window1.png" frames="101" /> <OnOffButton param="23" x="660" y="282" w="52" h="21" image="Main/Button.png" />
x
, y
, w
(width), h
(height), image
程度のもので、GladeやXAMLなどに比べたら内容も多くが自明です。これで、例えばこんな画面ができます。(Unreal InstrumentsのMETAL-GTX)
この画面では、ツマミの部分と数値入力っぽい部分がKnob
要素で表現されています。Knob
のparam
、frames
、image
には説明が必要でしょう。まず簡単なframes
のほうを説明しますが、これは数値の範囲に対応します。frames="101"
というのは、数値が0〜100の101段階であることを意味します。param
は、サウンドフォントのどのパラメーターを操作するものなのかを、MIDIのコントロールチェンジのように数値で指定します。.sfz
ファイル側で規定しているはずです。
ツマミの部分は画像を自由に指定できます。それがimage
属性の内容なのですが、リンク先を見てみてください。巨大な内容なので埋め込みはしません。
https://aria2web.firebaseapp.com/ui-metal-gtx/gen/GUI/Main/Main_Knob.png
あれ? 見えなくない…?ってなりますが、実はものすごい縦長の画像が、ブラウザウィンドウの幅に合わせて縮尺を調整した結果です。上方のごく一部だけを切り取るとこんな感じになっています。
ツマミですね…! ひとつひとつをよく見ると、ダイヤルが少しずつ上に移動しているのがわかります。縦長なのは、これが101個ぶんだけ縦に連結しているからです(!)。画面上には「今の値に対応する画像」を表示するだけです。とんでもないやっつけ仕様ですが、確かにこのフォーマットであれば、サンプラーのコードでは何も面倒を見る必要がないので、プラグインを作る側は自由なデザインでツマミを実装することができる、というわけです。
そして数値入力っぽく見えるのも実はダミーで、これはKnob
コントロールです。マウスホイールで数値を変更できます。キーボード入力はできません。もちろん数字はツマミと同じ超縦長画像に描かれています。なんか…とんでもねー世界に来ちまったぞ…
webaudio-controlsを活用してHTML UI化する
GUI拡張と聞くとなんかものすごい技術努力によって実現しているかのように思えてしまいますが、ARIAはごく単純な仕組みとデータ形式でUIを表現していました。この程度であれば、HTML+JavaScript+CSS+SVGで表現できるでしょう。sforzandoはLinux版を提供していないので(もちろんAndroid版もありません)、ARIAのGUIをロードできるようにするには自前で実装するしかありません。
aria2webのREADMEでも言及しているのですが、実はもう出来ていて、ここで試すことができます。
https://aria2web.firebaseapp.com/
今回これを作るにあたって活用したのは、この方面ですでに存在していたwebaudio-controls
という完成度の高いUIコントロールです。Web Componentsに基づいて作られていて、Javascriptから操作するのも簡単です。元コードの開発メンバーがだいたい日本のWeb Music Developers JPあたりにいそうです。
実のところ、ARIAがそこまでGUIの詳細な表示内容をデータ上に持っているとは考えていなかったので、ツマミやスライダーはこのwebaudio-controlsを使えば「それっぽいもの」が作れると思っていましたが、結果的には「ほぼ元通りのUIっぽいもの」を再現できるところまで出来ています。
ARIAのXMLをHTMLに変換する処理は本当に簡単なもので、現状では100行も無いXSLTスタイルシートで実現しています。あの妙な画像も変換しなくていいの?と思うでしょうが、webaudio-controlsに含まれるwebaudio-knob
に、完全に同じ機能が含まれています。
これはどうやってARIA用にこういう画像を作るのかを調べていて割といろいろびっくりしたんですが、そもそもwebaudio-controlsを開発しているg200kgさんがKnobManというこのKnobコントロール画像を作成するツールの開発者で*3、これを使えばgimpとかでがんばって手作業でこういう画像を加工する必要はないわけです(最近はWebKnobManがメインらしい)。そもそもKnob Galleryに膨大な数のフリーKnob素材があるので、自分でゼロから作る必要はあんまり無さそうです。
もうちょっと調べてみると、KnobManの使い方はNative Instrumentsのフォーラムでも議論されていて、要するにこの画像フォーマットはもともとKontakt(たぶん)で決められていて、KnobManはそれを簡単に作るために作られたツールであって、ARIA GUIもKontakt用音源のデータと同じ画像を再利用できるようにしたものっぽい、ということが把握できました。完全に謎のエコシステムが出来ている…!
ともあれ、当初予想していた以上にwebaudio-controlsを使ってUIを実現するというアイディアは的を射ていたことがわかりました。
ちなみにaria2webで使っているwebaudio-controlsのコードには少し手を加えてあります。具体的には、knobのサイズが不明な場合でも元画像のとおりによろしくやってくれるように変更しています*4。XSLTで任意のARIAから変換してwebaudio-knobを生成している自分としては、画像のサイズがわからないので指定できないわけですが(これがXSLTでなければ画像をロードしてサイズを取得するだけなので瞬殺…)、webaudio-knob
ではサイズ指定がない場合はデフォルト値(120pxかなんか)で描画してしまうので、当初は常に変なサイズで描画されてしまう問題で悩みました。
なぜWeb AudioでもないのにWeb UIなのか
ここから先は現在も開発中なのですが、aria2webはそもそもオーディオプラグインのUIとしてARIAを流用するのが目的なので、活用するにあたってはこれをLV2やVSTのようなプラグインに統合することになります。最近ではどのプラットフォームにもWebViewがあるのでそれを使えば十分可能だろう、というのがわたしの理解でした。でした…とは!? この詳細は「Part IIに続く」(!)
…なのですが、もう少しこの設計について書きます。
先日も書いたのですが、LV2オーディオプラグインのGUIの世界はバベルの塔が崩壊した状態で、各種のGUIフレームワークに分かれていて全部をサポートするのが難しい状態です。前回はsuilを紹介しましたが、suilでも解決できない課題があります(Part IIで書く)。
WebテクノロジーでUIを構築するというのは、この問題を解決するひとつの手段として考えたものです…というのは半分ウソで、そもそもWeb UIを使おうと思ったのはAndroidやiOSのような特殊な世界でプラグインUIをどう構築するかという課題への解決策として思いついたものでした。つまりWeb UIならホスト側アプリでもロードできる、というわけです(詳しくはここで)。
いずれにしろ、ローカル環境を問わずにUIをホストする、一部で「ガワネイティブ」と呼ばれる技術が、オーディオプラグインUI開発の裾野を広げたり、あるいは一般的なアプリケーションのUI開発手法に近づけるために、有用だと思っています。個人的にはオーディオプラグインUIの開発手法は10年遅れている、juce_gui_basicsに技術投資する時代ではない、くらいの認識でいます。もっとも、ここは実のところ要件次第のところがあって、オーディオ処理ほどではないが演奏者が違和感を感じない程度に可能な限りレスポンシブに動くUIにはネイティブコードが最適でしょう。ただこれは設計次第なのと過渡的な問題だと理解しています。
ちなみに、この観点で紹介しておくべきものとして、JUCEのGUIをReactで開発できるBlueprintがあります。BlueprintはWebViewを使うのではなく、JUCE用のrendererを提供するreconcilerの実装になっている、すなわちもうひとつのReact Nativeのように振る舞っている、というところが特徴です。つまり、Reactのやり方で構築したUIが、JUCEのネイティブコンポーネントとして動作することになります。
これはこれでスマートなやり方なのですが、あくまでReact資産があったり、React開発でゼロから構築することを前提としないと難しいです。今回はwebaudio-controlsを使っていて、これは内部的にWeb ComponentsやSVGをDOMも含めて活用して実装されているため、React化するという選択肢はありませんでした。Blueprintはreconcilerを自前で実装していて、YogaやDuktapeを組み合わせて実装していて、issuesを眺めてみてもそれなりに未実装の部分がいろいろあることがわかるので、あくまで出来る範囲のことをやる方針プロジェクトと理解しています。自分にはむしろCordovaやIonicのやり方が必要となったわけです。
今回は試験的にVue.jsを使っていますが、無くても良かったというレベルなので、今後依存関係として邪魔だな…となったらたぶん消します。(試験的なプロジェクトなので、ライブラリを開発している時みたいに「余計な依存関係はなるべく減らして…」とかは考えてはいません。)
ローカルプラグインからの利用については、Global空間に適当なWebViewからのフック用のJSオブジェクトを用意しておいて、webaudio-controlsからの操作通知はそこに送るように作ってあります。現在開発が進んでいるローカルのプラグインではこれでイベントを受け取っています。
ちなみに(言うまでもないかもしれませんが)Web上のデモはGUIのみです。音は出ません(デスクトップでも「まだ」音は出ませんが)。というのは、SFZサウンドフォントは大規模なものだと1GBにもなるような巨大なデータであるため、Web上環境には現状馴染まないためです。ダウンロードしてWeb Storage APIで格納するようなソリューションは実現可能かもしれませんが(あとはWeb Audio Pluginsと組み合わせたりとか)、個人的には現状あまり関心が無いです。
後半へ続く
本当は1回で全部まとめるつもりだったのですが、HTML化の部分だけでかなり長くなってしまったので、オーディオプラグインに組み込む部分はPart IIとして書きます。そもそもまだ出来ていないしな…!