2016年5月22日日曜日

2.2.2 Sinusoid Pitch Tracker - several periods measurement

先ほど作成したsinusoid pitch trackerには、問題があります。

周波数の計算に用いた M(xt)という関数ですが、
これはサンプルごとにカウントするもので、
Time Quantization(時間量子化)のために、
明らかないくつかのエラーが存在するということです。

解決方法として、いくつかに分けられたを範囲をカウントし、
その後、この結果を想定される間隔の数で割るというものです。


幸いなことに、
普通の音(ピッチ)では、音の高さはこの小さい間隔では変化がありません。
それでは、想定される間隔の数を a として、
この値をスライダーに割り当ててみましょう。


V 関数


先ほどは、N (x) 関数を用いて、
カウンターを  U(x) = 1 というイベントが起こるたびに、
(例えば、信号が上昇して0の値になるときに)
リセットしました。

そして、 今回は、N(x t)関数を、 a U(xt ) = 0 となる後のときだけ、
0にリセットしなければなりません。

もちろん、その U(x t) = 0 イベントのために、カウンターが必要です。

このカウンターを V (x t)と呼びます。
それでは、FAUST での定義を見てみましょう。


V(a, x) = +( U (x ) ) ~ % (int(a));


カウンターの基本形は次のようになります。


count = +(1) ~ _;


+(1)  の代わりに、 + U(x)) を用いています。
これは 0 の間 1 を返します。
よって、毎サンプルごとに1増加するカウンターの代わりに、
U(x t) = 0 となるごとに1増加するカウンターを用いています。

modulo 関数(%)は、int(a)の値になったときに、
0にリセットを行う関数です。

想定した間隔のサンプリング数である a という値は、すでに整数なので、
int(値を整数にして返す) 関数は、使う価値がないように思えますが、
しかしながら、コンパイラはこの背景を知らないので、
int (a ) とはっきり述べる必要があります。


V (a, x t )関数が毎 U(x t ) = 0 となるごとに1ずつ増加する関数だとすると、
a の値に達したときに値は再び0にもどります。



W 関数


さて、私たちは、N(x t)関数の部分を、書き換えていかなければなりません。
なぜなら、 a U(x t)= 1 かつ V(a, x t )=a という状態になるまで
値が上げ続けるのを止めないようにしないといけないからです。

例えば、信号が0の値をとる間、
最後の V (a, x t) 値がリセットさせるまで、
(N (x t) 値も同じです)
それらの0の a が正しく生成されなければなりません。

新しく作る関数 はシンプルなものです。
W(a, x t)と表し、この要求された2つの状態を表しています。




FAUST では次のように表されます。


W(a,x) = (U(x) == 1) & (V(a,x) == a);




FAUSTでは真は1、偽は0が返るために、簡略化したコードは次のようになります。


W(a,x) = U(x) & (V(a,x) == a);




最終調整


さて、それでは、U(x)関数をW(a, xt)関数を用いることで、
N(xt)関数を新しくしましょう。

N(a,x) = (+(1) : *(1 - W(a,x))) ~ _;



最後に、Pitch(a, x)関数にて、
a を M(a, xt)関数で除算し、また0の時にnullとなるようにもしておきましょう。


Pitch(a,x) = a * SR / max(M(a,x),1) - a * SR * (M == 0);


コードの全体は次のようになります。



  1 import("math.lib");
  2 
  3 SH(trig,x) = (*(1 - trig) + x * trig) ~ _;
  4 a = hslider("n cycles", 1, 1, 100, 1);
  5 
  6 Pitch(a,x)= a * SR / max(M,1) - a * SR * (M==0)
  7 with {
  8   U = (x' < 0) & (x>=0);
  9   V = +(U) ~ %(int(a));
 10   W = U & (V==a);
 11   N = (+(1) : *(1-W)) ~_;
 12   M = SH(N==0, N'+1);
 13   };
 14 process = Pitch(a);


a の値を高くすれば、正確さもより増していきます。
しかし、その分、解析にかかる時間にも遅れが生じることを忘れないでください。


SVGダイアグラム図



DSP ファイル実行 



0 件のコメント:

コメントを投稿