ディレイの実装例
ディレイは入力信号に数ミリ秒前の信号(ディレイ信号)を混ぜて出力するエフェクターです
パラメーターとして下記がよく利用されます。
パラメーター | 意味 | だいたいの範囲 |
---|---|---|
ディレイタイム | ディレイの時間 | 50ミリ秒~2秒程度 |
レベル | ディレイの効き具合(ディレイ信号の振幅) | 0~1の間 |
フィードバック | フィードバックの効き具合 | 0~1の範囲 |
実装は入力信号にディレイ信号を加えて出力します。ディレイ信号はリングバッファを使用して保存します。
リングバッファは「リングバッファについて」で作成したものを使用しています。
あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。
【実装イメージ】
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 |
void delay(float inL[], float inR[], float outL[], float outR[], int wavelength) { // inL[]、inR[]、outL[]、outR[]はそれぞれ入力信号と出力信号のバッファ(左右) // wavelenghtはバッファのサイズ、サンプリング周波数は44100Hzとする // エフェクターのパラメーター float time = 250.0f; // ディレイの時間。50~2000ミリ秒程度。 float level = 0.3f; // ディレイの効き具合。0~1の間。 float feedback = 0.5f; // フィードバック効き具合。0~1の間。 // 内部変数 CRingBuffur ringbufL, ringbufR; // リングバッファ(https://www.utsbox.com/?p=1505 より) //ディレイタイムをサンプル数に変換して設定 int delaysample = (int)(44100.0 * time / 1000.0); ringbufL.SetInterval(delaysample); ringbufR.SetInterval(delaysample); // 入力信号にディレイを掛ける for (int i = 0; i < wavelength; i++) { float tmpL, tmpR; // 入力信号にディレイ信号を加える tmpL = inL[i] + level * ringbufL.Read(); tmpR = inR[i] + level * ringbufR.Read(); // ディレイ信号として入力信号と今回のディレイ信号をリングバッファに書き込み ringbufL.Write(inL[i] + feedback * ringbufL.Read()); ringbufR.Write(inR[i] + feedback * ringbufR.Read()); // リングバッファの状態を更新する ringbufL.Update(); ringbufR.Update(); // 出力信号に書き込む outL[i] = tmpL; outR[i] = tmpR; } } |
上記はあくまで実装例です。
加えるディレイ信号やフィードバックで利用するディレイ信号を左右逆にしたり、フィルタをディレイ信号にかけてみるのも面白いかもしれません。
なお、for文の中やリアルタイム処理など音声処理中にディレイタイム(上記のtime変数)を変更するとクリップノイズのようなものが入る可能性があります。
変更時は一時的にディレイレベルを 0 にするか、ディレイタイムをゆっくり変更していく必要があります。
質問はコメント欄や掲示板、Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例
■掲示板
■Twitterアカウント:@vstcpp URL:https://twitter.com/vstcpp