2016年5月20日金曜日

1.4 Computational overview

処理コストについて


最後のセクションでは、完全に動作するパンを作成しました。

Fig1.6 は、それぞれのパンでの出力帯域について表しています。

最初の3つのパンは。
これまでに作成したものと同じ命令処理のものになります。

他にプロットされているパンについては、
このあとの章で述べます。

出力帯域が大きいパンは、
パソコンの負荷が少ないパンということになります。

---

Fig.1.6

それぞれの出力帯域の計算は、Pentium4 2.66GHzでおこなっています。
イタリックで書かれている値は、それぞれの比率になります。

用いた.dspファイルは、
単純に入力した値を2つの出力に振り分けたもので、
値は予測値ではなく、最小値を同じ演算処理を経て取得したものです。

最大出力帯域は、PCの読み書き速度に影響されます。
今回、その値は約3282MB/s です。

---

グラフをみると、音強度を考慮した Pan は、
わずかながら、最初の Pan よりも負荷がかかることがわかります。

それはもちろん、`sqrt` 関数を取り入れたからです。

しかし、3つ目に作成した、
値の間を補完する、改良型 Pan に比べればわずかな差です。

これに比べて改良型 Pan  は、
なんと1つ目、2つ目のパンに比べて、
13倍ものコストがかかります。

この理由を知るために、FAUSTが生成するC++のコードを見てみましょう。

このコードはコマンドラインで`faust`を実行し、
引数に.dspファイルをとると、
取得することができます。

---

・最初に作成したPan

入力した音を、加工なしに左右のチャンネルに振り分けるPan

/-----------------------------------------------------
//
// Code generated with Faust 0.9.73 (http://faust.grame.fr)
//-----------------------------------------------------
/* link with  */
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif  


#ifndef FAUSTCLASS 
#define FAUSTCLASS mydsp
#endif

class mydsp : public dsp {
  private:
FAUSTFLOAT fslider0;
  public:
static void metadata(Meta* m)
}

virtual int getNumInputs() { return 1; }
virtual int getNumOutputs() { return 2; }
static void classInit(int samplingFreq) {
}
virtual void instanceInit(int samplingFreq) {
fSamplingFreq = samplingFreq;
fslider0 = 0.5f;
}
virtual void init(int samplingFreq) {
classInit(samplingFreq);
instanceInit(samplingFreq);
}
virtual void buildUserInterface(UI* interface) {
interface->openVerticalBox("0x00");
interface->addHorizontalSlider("pan", &fslider0, 0.5f, 0.0f, 1.0f, 0.01f);
interface->closeBox();
}
virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) {
float fSlow0 = float(fslider0);
float fSlow1 = (1 - fSlow0);
FAUSTFLOAT* input0 = input[0];
FAUSTFLOAT* output0 = output[0];
FAUSTFLOAT* output1 = output[1];
for (int i=0; i<count; i++) {
float fTemp0 = (float)input0[i];
output0[i] = (FAUSTFLOAT)(fSlow1 * fTemp0);
output1[i] = (FAUSTFLOAT)(fSlow0 * fTemp0);
}
}
};


---

・2つ目に作成したPan

音強度を考慮したもの


//-----------------------------------------------------

//
// Code generated with Faust 0.9.73 (http://faust.grame.fr)
//-----------------------------------------------------
/* link with  */
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif  


#ifndef FAUSTCLASS 
#define FAUSTCLASS mydsp
#endif

class mydsp : public dsp {
  private:
FAUSTFLOAT fslider0;
  public:
static void metadata(Meta* m)
}

virtual int getNumInputs() { return 1; }
virtual int getNumOutputs() { return 2; }
static void classInit(int samplingFreq) {
}
virtual void instanceInit(int samplingFreq) {
fSamplingFreq = samplingFreq;
fslider0 = 0.5f;
}
virtual void init(int samplingFreq) {
classInit(samplingFreq);
instanceInit(samplingFreq);
}
virtual void buildUserInterface(UI* interface) {
interface->openVerticalBox("0x00");
interface->addHorizontalSlider("pan", &fslider0, 0.5f, 0.0f, 1.0f, 0.01f);
interface->closeBox();
}
virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) {
float fSlow0 = float(fslider0);
float fSlow1 = sqrtf((1 - fSlow0));
float fSlow2 = sqrtf(fSlow0);
FAUSTFLOAT* input0 = input[0];
FAUSTFLOAT* output0 = output[0];
FAUSTFLOAT* output1 = output[1];
for (int i=0; i<count; i++) {
float fTemp0 = (float)input0[i];
output0[i] = (FAUSTFLOAT)(fSlow1 * fTemp0);
output1[i] = (FAUSTFLOAT)(fSlow2 * fTemp0);
}
}
};



---

・3つ目に作成した改良型Pan

smooth 関数を使い、値の間を補完しクリックノイズを防いだもの


//-----------------------------------------------------

//
// Code generated with Faust 0.9.73 (http://faust.grame.fr)
//-----------------------------------------------------
/* link with  */
#include <math.h>
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif  


#ifndef FAUSTCLASS 
#define FAUSTCLASS mydsp
#endif

class mydsp : public dsp {
  private:
float fConst0;
FAUSTFLOAT fslider0;
FAUSTFLOAT fslider1;
float fRec0[2];
  public:
static void metadata(Meta* m)
m->declare("filter.lib/name", "Faust Filter Library");
m->declare("filter.lib/author", "Julius O. Smith (jos at ccrma.stanford.edu)");
m->declare("filter.lib/copyright", "Julius O. Smith III");
m->declare("filter.lib/version", "1.29");
m->declare("filter.lib/license", "STK-4.3");
m->declare("filter.lib/reference", "https://ccrma.stanford.edu/~jos/filters/");
m->declare("music.lib/name", "Music Library");
m->declare("music.lib/author", "GRAME");
m->declare("music.lib/copyright", "GRAME");
m->declare("music.lib/version", "1.0");
m->declare("music.lib/license", "LGPL with exception");
m->declare("math.lib/name", "Math Library");
m->declare("math.lib/author", "GRAME");
m->declare("math.lib/copyright", "GRAME");
m->declare("math.lib/version", "1.0");
m->declare("math.lib/license", "LGPL with exception");
}

virtual int getNumInputs() { return 1; }
virtual int getNumOutputs() { return 2; }
static void classInit(int samplingFreq) {
}
virtual void instanceInit(int samplingFreq) {
fSamplingFreq = samplingFreq;
fConst0 = (1.0f / float(min(192000, max(1, fSamplingFreq))));
fslider0 = 0.001f;
fslider1 = 0.5f;
for (int i=0; i<2; i++) fRec0[i] = 0;
}
virtual void init(int samplingFreq) {
classInit(samplingFreq);
instanceInit(samplingFreq);
}
virtual void buildUserInterface(UI* interface) {
interface->openVerticalBox("0x00");
interface->addHorizontalSlider("interpolation time", &fslider0, 0.001f, 0.0f, 0.01f, 0.0001f);
interface->addHorizontalSlider("pan", &fslider1, 0.5f, 0.0f, 1.0f, 0.01f);
interface->closeBox();
}
virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) {
float fSlow0 = expf((0 - (fConst0 / float(fslider0))));
float fSlow1 = (float(fslider1) * (1.0f - fSlow0));
FAUSTFLOAT* input0 = input[0];
FAUSTFLOAT* output0 = output[0];
FAUSTFLOAT* output1 = output[1];
for (int i=0; i<count; i++) {
float fTemp0 = (float)input0[i];
fRec0[0] = ((fSlow0 * fRec0[1]) + fSlow1);
output0[i] = (FAUSTFLOAT)(fTemp0 * sqrtf((1 - fRec0[0])));
output1[i] = (FAUSTFLOAT)(fTemp0 * sqrtf(fRec0[0]));
// post processing
fRec0[1] = fRec0[0];
}
}
};

---

それぞれのコードは、`faust` を実行する環境で、少し異なります。

白字に抜いた箇所と、
黄色で表した for ループの部分
 `sqrt` 関数の影響している箇所です。

`sqrt` 関数は、Panを作成する際に使用した関数です。
for ループはサンプリングレートごとの演算を行っている箇所です。

前のコードで、 control rate と表したことがあります。
control rate は、(環境に影響される)サンプリングレートの約数です。

よって、`sqrt`関数は、2つ目のパンでは、
nサンプルごとに演算が行われるのに対し、
3つ目の改良したパンでは、
サンプルごとに演算が行われます。

これが、2つ目のパンと3つ目のパンとで、
負荷が大きく変わってくる原因です。

0 件のコメント:

コメントを投稿