以前の記事でFaustを使って2opのFM音源を作りましたが、周波数をスライダーを手でいじって音程が変わるというのはやっぱりちょっと寂しい…ということで、Audio Unitによるソフトウェア音源として利用できるようにします。MacであればGarageBandとかのDAWで読み込ませれば、鍵盤叩いて音を鳴らせるはず…。

方針

Faustには様々な形式でファイルを書き出せます。今回はJUCE向けに書き出すことにしました。Faust側で対応しているVSTプラグインは自分の環境ではソフトがなくて動作確認できないのと、JUCE向けに書き出しておけば、何かコードを修正することも可能だからです(今回は単にコンパイルするだけです)。

JUCE?

JUCEはAudioUnitやVSTなどのマルチプラットフォームに対応したオーディオプラグイン開発ツールキット…という感じでしょうか。言語はメインはC++です。KORGなどもJUCEを使っているようです。

Faust側の事前準備

MIDI対応にする

ソフトウェア音源化にあたっては、MIDI入力イベントをFaust側で受け付けられるようにします。鍵盤が叩かれたら、その音程の音が鳴って欲しいですし、どれだけ強く引っ叩いたかによって音の強さも変わって欲しいです。

さてこれどうやって実現されるかなんですが、ドキュメントにはこう書かれています

Most Faust architectures allow for the implementation of polyphonic instruments simply by using a set of “standard user interface names.” Hence, any Faust program declaring the freq (or key)gain (or vel or velocity), and gate parameter is polyphony-compatible. These 3 parameters are directly associated to key-on and key-off events and have the following behavior… 

Faust Manual: MIDI Support

つまり、UIの名前を「freq」「gain」「gate」にしておけば勝手にそのUIに値が入るとのこと。なぁんだ、ですね。また、

declare options "[nvoices:12]";

と記述すると最多同時発音数が12になるとも書かれているのですが、自分が試した時はうまくいかず、代わりに、

declare nvoices "12";

で宣言したらうまく行きました…と思いますが、もしかしたら別の原因でうまくいかなかったのかもしれません。

FM音源のコード修正

以前のコードに上記の修正を入れればそれで良いのでしょうが、せっかくなのでADSRの値もいじれるようにします。

一旦は全部スライダーにしてみます。groupを使ってパラメータをいじるUIを束ねてみました。また、フィードバックは8段階の係数で指定するようにしました。テーブルを使ってみたくて、rdtableというものを使っています。

declare nvoices "16";
import("stdfaust.lib");

//operator function
operator(freq, index, adsr, amp, phase) = os.oscp(freq * index, phase) * amp * adsr;


// UI elements
freq   = hslider("/[2]freq",200,40,2000,0.01);
gain   = hslider("/[3]gain",0.5,0,1,0.01);
gate   = button("/[1]gate");
feedback = hslider("/[4]op1 feedback", 0, 0, 7, 1);


adsr(g) = vgroup("[9]ADSR", en.adsr(a, d, s, r, g))
    with {
        a = hslider("[1]attack", 0.1, 0, 10, 0.01);
        d = hslider("[2]decay", 0.1, 0, 10, 0.01);
        s = hslider("[3]sustain", 0.9, 0, 1, 0.01);
        r = hslider("[4]release", 0.5, 0, 10, 0.01);
    };

operator_control(ch, phase) = hgroup("[9]Operator #%ch", operator(freq, _index, _adsr, _amp, phase))
    with {
        _adsr = adsr(gate);
        _index = vslider("[1]freq index",1,1,10,1);
        _amp = vslider("[0]amp", 1,0,10,0.1);
    };

//0, PI/16, PI/8, PI/4, PI/2, PI, PI x 2, PI x 4
feedbacktable = waveform{0,0.1963495,0.392699,0.785398,1.570796,3.141592,6.2831,12.566};
fbvalue = feedbacktable,int(feedback):rdtable;
op1 = operator_control(1) ~ * (fbvalue);
op2 = operator_control(2);
process = tgroup("[5]Operator control", op1:op2)*gain;

何だかんだグループ化したりして見通しが悪くなってきているかもしれませんが、これを動かすと以下のように見えます。

オペレータのパラメータをADSRとそれ以外に分けて配置しています。また、オペレータごとにタブで切り替えるような形にしています。ボタンを押すと今まで通りに音が鳴るはずです。またADSRの値を変えると雰囲気も変わると思います。

JUCE形式での書き出し

FaustのIDEから、JUCE形式で書き出しを行います。

左側のメニューから黄色いボタン(トラックのようなアイコン)をクリックし、その後exportの種類を選択します。

  • Platformをjuceに
  • Architectureを、(正しいのかはよく分からないのですが)plug-in-midi-poly16に

してCompileボタンを押します。しばらくするとDownloadボタンが現れるので、ダウンロードします。

ちなみに、ファイルネームを数字を頭にしてダウンロードすると、後ろのXcodeの工程でビルドエラーが発生します(おそらくファイル名か変数名あたりに埋め込まれてしまってコンパイルできない)。英字スタートにしておくのが吉です。

JUCEのセットアップ

JUCEのセットアップ方法については様々なところに記載されています。例えばQiitaのこの記事など。特に難しいことはありませんので、手順通り進めてもらえれば。

JUCEファイルの立ち上げとXcodeでのコンパイル

FaustのIDEからダウンロードしてきたファイルには、HOGEHOGE(ファイル名).jucerというファイルが入っています。これをダブルクリックするとProjucerが立ち上がります。

フリーエディションの場合一番最初はライセンスがどうこうと言われるかもしれません。左下にダイアログが出てきたら「スプラッシュスクリーンが出てくるのもやむなし」みたいなボタンを押します。

その後は画面中央のXcodeのアイコンが押せるようになりますので、クリックしXcodeにジャンプします。

Xcodeを立ち上げたら、ビルドするターゲットを選びます(VSTやAudio Unitなどを選べます)。

上記赤字の部分です。自分の場合はAudio Unitなので、以下のような形に。

このターゲットでビルドを行うと、~/Library/Audio/Plug-Ins/Components/にAudio Unitコンポーネントを自動で配置してくれます。あとはGarageBandなどのDAWで確認です!

GarageBandでの動作確認

GarageBandで新規トラックを「ソフトウェア音源」で作成すると、下記のような画面になります。

この中央下側の「プラグイン」という部分にご注目。デフォルトではE-Pianoとなっていますが、ここをクリックすると他の音源に切り替えられます。以下のような画面になります。

ここで、ご自身が作った音源が見つかればOK。使えるようになります。

何だか随分と白色基調で目がチカチカしますが、音が鳴るはずです。

MIDIキーボードがつながっている方はポロリ〜ンと弾いていただいて、繋がっていない方は画面上に表示されたキーボードで我慢しましょう。

まとめ

FM音源自体は2オペで以前から変わりませんが、Web上のIDEでぽちぽちやっても何だかおもちゃ感覚だったものが、きちんとソフトウェア音源として認識され、実際にDAWで演奏に使えるところまで辿り着きました。

UIに関してはFaustからの移植だけだと早晩物足りなくなる気がしますので、何らかの形で修正するか、JUCE一本で行くかする必要が出てくるかもしれません。

いずれにしても、これだけ簡単に(といってもほとんど情報がないので試行錯誤しましたが)Audio Unitとして書き出せるとなるとお遊びの幅も広がりそうです。今後も乞うご期待。

不要と思いますが、一応出来上がったAUコンポーネントをアップロードしておきます。