フェイザーの実装例
フェイザーとはオールパスフィルターを使って音を揺らすエフェクターです。
パラメーターとして下記がよく利用されます。
パラメーター | 意味 | だいたいの範囲 |
---|---|---|
干渉 | フェイザーのかかり具合 | 0.0~1.0の間 |
レート | 揺らぎの間隔・周期 | 0Hz~16Hz程度 |
深さ | 揺らぎの深さ | 0~5程度 |
周波数 | オールパスフィルターの周波数 | 200~1kHz程度 |
実装はまず、カットオフ周波数を一定周期で揺らしたオールパスフィルターを入力信号にかけます。
次に元の入力信号とオールパスフィルタをかけた入力信号を混ぜ合わせて出力します。
フィルタは「簡単なデジタルフィルタのサンプルコード」を使用しています。
あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。
【実装イメージ】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
void phaser(float inL[], float inR[], float outL[], float outR[], int wavelength) { // inL[]、inR[]、outL[]、outR[]はそれぞれ入力信号と出力信号のバッファ(左右) // wavelenghtはバッファのサイズ、サンプリング周波数は44100Hzとする // エフェクターのパラメーター float mix = 0.3f; // フェイザーのかかり具合。0.0~1.0の間 float rate = 1.4f; // 揺らぎの間隔。0Hz~16Hz程度 float depth = 3.5f; // 揺らぎの深さ。0.0~5.0程度 float freq = 800.0f; // オールパスフィルタの周波数。200Hz~1kHz程度 // 内部変数 CMyFilter allL1, allR1; // フィルタークラス(https://www.utsbox.com/?page_id=728 より) CMyFilter allL2, allR2; // フィルタークラスが1つでは効きが弱いので2つ用意 float theta = 0; // オールパスフィルタの周波数を揺らすためのsin関数の角度 θ。初期値は0 float speed = (2.0f * 3.14159265f * rate) / 44100.0f; // 揺らぎのスピード。角速度ωと同じ。 // 入力信号にエフェクトをかける for (int i = 0; i < wavelength; i++) { // 角度θに角速度を加える theta += speed; // sin関数の結果を0~1の間にする float a = (sin(theta) * 0.5f) + 0.5f; // オールパスフィルタのカットオフ周波数を計算 float tmpfreq = freq * (1.0f + a * depth); // オールパスフィルタ設定(左右分) allL1.AllPass(tmpfreq, 1.0f); allL2.AllPass(tmpfreq, 1.0f); allR1.AllPass(tmpfreq, 1.0f); allR2.AllPass(tmpfreq, 1.0f); // 入力信号にフィルタをかけた信号を用意 float tmpL = allL2.Process(allL1.Process(inL[i])); float tmpR = allR2.Process(allR1.Process(inR[i])); // 入力信号とフィルタ適用済み信号を混ぜて出力信号に outL[i] = (1.0f - mix) * inL[i] + mix * tmpL; outR[i] = (1.0f - mix) * inR[i] + mix * tmpR; } } |
上記はあくまで実装例ですので、オールパスフィルタの数や揺らし方等を工夫する余地があります。
また、フィードバックとしてtmpL/RやoutL/Rを次の入力信号に加算させることで音も変わります。
質問はコメント欄や掲示板、Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例
■掲示板
■Twitterアカウント:@vstcpp URL:https://twitter.com/vstcpp