情弱

情弱のVST作製メモ

音響信号処理言語"Faust"の勉強会に参加してきました

f:id:aogiri_m2d:20170828225718j:plain

はじめに

 先日、こちらの勉強会に参加してきました。

faust-jp.connpass.com

 "Faust"は関数型音響信号処理言語で、慣れれば爆速でDSPアルゴリズムの試作・検討ができるようです。 しかしながら、日本語による情報はまだまだ少ないのが現状とのことなので、 勉強会に参加したばかりで言語仕様もほとんど理解できていない状態ではありますが、 ざっとFaustを触ってみた感想などをここに残しておこうかと。  

Faustのここがすごかった

・記述量が少なくてすむ

 下記のような、エコーエフェクトの実装を考えて見ます。

y(n)=m=0MAmx(nmd)

これを以下のようにFaustで記述してみました。

import("stdfaust.lib");
dtime_sec = hslider("time", 1.0, 0.1, 5.0, 0.1); //d
decay = hslider("decay", 0.75, 0.10, 0.90, 0.01); //A
toSamp(t) = t * ma.SR;
echo(n, x) = (x : @(n * toSamp(dtime_sec)), pow(decay, n)) : *;
echoLine(N, x) = x <: par(i, N, echo(i)) :> +;
process = echoLine(6), echoLine(6);
view raw echo.dsp hosted with ❤ by GitHub
一方、これと同様のものをC++ & JUCEで記述してみると以下のようになるでしょうか。

//echoMod.h
#include "JuceHeader.h"
namespace effect
{
class Parameters {
AudioParameterFloat* pTimeSec;
AudioParameterFloat* pDecay;
public:
Parameters(AudioProcessor& ap)
:pTimeSec(new AudioParameterFloat("time", "time", 0.1f, 5.f, 1.f)),
pDecay(new AudioParameterFloat("decay", "decay", 0.1f, 0.9f, 0.01f))
{
ap.addParameter(pTimeSec);
ap.addParameter(pDecay);
};
float getTimeSec() { return pTimeSec->get(); };
float getDecay() { return pDecay->get(); };
};
class EchoMod {
Parameters& rParams;
int n = 0;
float dTimeSamp;
float decay;
const int totalNumEcho = 6;
static const int buffSize = 480000;
float delayBuff[buffSize] = { 0.f };
public:
EchoMod(Parameters& rP)
:rParams(rP) {};
void setParams(float fs) {
dTimeSamp = rParams.getTimeSec() * fs;
decay = rParams.getDecay();
};
void echoProcessing(float& hostBuff) {
delayBuff[n] = hostBuff;
n = (n + 1) % buffSize;
float sum = 0.f;
for (int m = 0; m < totalNumEcho; m++) {
int delay = n - m * dTimeSamp;
if (delay < 0) { delay = buffSize + delay; }
sum += powf(decay, m) * delayBuff[delay];
}
hostBuff = sum;
};
};
//ProcessBlockで走らせる
void doProcessing(EchoMod& echo, float* hostBuff, int buffSize, float fs);
}
//echoMod.cpp
#include "EchoMod.h"
void effect::doProcessing(EchoMod& echo, float* hostBuff, int buffSize, float fs) {
echo.setParams(fs);
for (int n = 0; n < buffSize; n++) { echo.echoProcessing(hostBuff[n]); }
};
view raw echo.h hosted with ❤ by GitHub
その差は一目瞭然ですね。。。なるほど。

・出音の確認が容易

 では、先に書いたFaustのコードの出音を確認してみます。 方法はいくつか存在するようですが、ここでは"FaustLive"というツールを使用してみました。 下記の画像のように、FaustLive上に先のdspファイルをドロップするだけで、すぐに出音の確認ができます。 f:id:aogiri_m2d:20170828224004j:plain  さらに、現在FaustLiveに読み込まれているソース (ここではecho.dsp)を修正・更新すると、すぐに変更が出音に反映されます。 いや、これすごい便利ですね。"ソースの変更⇔出音の確認"というサイクルを手軽に回すことができます。
 C++ & JUCEの場合だと、ソースコードの変更→VSTとしてビルド→DAWに読み込ませる→出音の確認という工程を踏まなければならないことを考えると、その差は大きいですね。

・信号の流れをブロック線図で確認できる

 Faustで書かれた処理は、下記のようなブロック線図で確認することができます。 f:id:aogiri_m2d:20170828225647j:plain f:id:aogiri_m2d:20170828225718j:plain  入力信号がそれぞれ異なる遅延時間・減衰係数を持つブロックに分配され、 処理後にマージされ1つの信号になって出力されるという流れがわかります。

おわりに

 以上、素人がFaustを少し触ってみて特に印象に残った部分についてざっくりと書いてみました。 また、今回の勉強会の主催・講師をされた松浦さん(@tomoya_nonymous)が、当日の資料を公開してくださってます。基本的な文法を含め一通りの解説がなされているので、はじめてFaust触るマンとして大変参考になります。

 また、Faustの環境構築については、Connpassにある第一回勉強会のページに記載されているものを参考にすればよいかと思います。 これらを参考にすれば、ひとまず、Fasutで遊ぶことができると思います。 こちらのFaust勉強会、次回は11/26あたりに第2回を開催予定とのことなので、ご興味を持たれた方はぜひ。