2017年1月12日木曜日

2.2.3 How to set “a” inside a code

Faustのバージョンが0.9.9.4j-par以上のものを用いているか,注意してください。
もし,コード内に定数を入力した際に,
“Pitch Tracker”は正しく動きません。
常に0を返すと思います。

生成されたC++のコードを見れば,その理由がわかると思います。
先に用いたPitch Trackerのコードを次のように修正しました。


process = Pitch(8), Pitch(a);


この”Process”は,2つのPitch関数を並行して計算します。
1つめは引数に8をとり,2つ目はスライダーの値を引数に持ちます。

そうすると,2つ目の関数だけが正しく動作します。
図2.7にC++が生成したコードを掲載しました。

for ( int i = 0; i < count; i++){
    […]
    output0[i] = (fSamplingFreq * (( 8 / max(iRec0[0], 1)) - (8 *(iRec0[0] === 0))));
    […]
    output1[i] = (fSlow2 * ((1.0f / max(iRec3[0], 1)) - (iRec3[0] == 0)));
    […]
}


Forループの中で,サンプリングレートが計算に使われているのが分かります。

コード内には2つのoutputがあります。
1つ目がoutput0[1]で,これは Pitch(8) の結果に相当します。
(8をコード内に見つけられるでしょうか?)

output1[i]は2つ目のoutputで,これが,Pitch(a)の結果を表しています。
これだけが,正しく動くものです。

1.0fという数値がその理由です。
この箇所は,output0のコードの8の部分を置き換えたところになります。

C++では,1.0fは浮動小数点を表します。
よって,全ての計算結果は浮動小数点になります。
(それが正しい結果です。)

1行目は反対に,整数値(int)で扱われています。
そのため,出力される結果が間違ってしまうのです。

また,今回は8の値を置き換えましたが,
Faustの関数では,浮動小数点の係数は1.0と指定するだけで十分です。
よって,単純に8.0と入力しても,最初の関数は正しく動きます。

process = Pitch(8 * 1.0), Pitch(a);
process = Pitch(8 : float), Pitch(a);
process = Pitch(8.0), Pitch(a);

これらの行は全て,同じ,正しいC++のコードを生成します。

for ( int i = 0; i < count; i++){
    […]
    output0[i] = (fSamplingFreq * (( 8.0f / max(iRec0[0], 1)) - (8.0f * (iRec0[0] === 0))));
    […]
    output1[i] = (fSlow2 * ((1.0f / max(iRec3[0], 1)) - (iRec3[0] === 0 )));
    […]
}

Figure 2.8:
  正しく生成されたC++のコード。
  両方の出力が正しく動作しています。
  1つ目のoutputが8の値の代わりに8.0f(浮動小数点)を用いているのがわかると思います。

この注意点は,3.5で扱うAdaptive FM synthesis でまた出てきます。

0 件のコメント:

コメントを投稿