エフェクターの簡単な実装例 – ピッチシフター

ピッチシフターの実装例

ピッチシフターは入力信号に音程を高くしたり、低くしたりするエフェクターです。

パラメーターとして下記がよく利用されます。

パラメーター 意味 だいたいの範囲
ミックスレベル ピッチシフターのかかり具合 0~1の間
ピッチ どれだけ音を高く(低く)するか -12~12半音(-1~1オクターブ)程度

実装は読み込み速度を速めたディレイ信号を入力信号に加えて出力します。
ディレイ信号の読み込み速度を速めることで音程が変わります。

ディレイ信号はリングバッファを使用して保存します。リングバッファは「リングバッファについて」で作成したものを使用しています。
また、読み込み速度を変更した際、整数値にならない場合があるためサンプルとサンプルの間の位置の値を線形補間などを用いて割り出す必要があります。
線形補間の詳細は省略いたします。

あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。

【実装イメージ】
■線形補間の実装

■エフェクターの実装

上記はあくまで実装例です。
読み込み位置(上記の変数pos)が0になる時(42行目)に音声信号が不連続となりノイズが入ります。
クロスフェード等を利用して音声信号を滑らかにつなぐことでノイズは改善することができます。

質問はコメント欄や掲示板Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例

掲示板
■Twitterアカウント:@vstcpp   URL:https://twitter.com/vstcpp

エフェクターの簡単な実装例 – コンプレッサー

コンプレッサーの実装例

コンプレッサーとは入力音声の音圧に応じて音量を調整するエフェクターです。

パラメーターとして下記がよく利用されます。

パラメーター 意味 だいたいの範囲
スレッショルド 圧縮が始まる音圧 0.1~1.0程度(dBで計算する場合もある)
レシオ 圧縮する割合 2.0~10.0程度(例えば2.0の場合、圧縮比率2:1でスレッショルドを超えた分が1/2になる。)/td>
音量 最終的な音量 1.0~3.0倍程度(dBで計算する場合もある)

実装では下記のような処理を行います。

  1. 入力信号に応じた音圧を検知。
  2. 検知した音圧に応じて音量(ゲイン)を計算。
  3. 入力信号に計算した音量(ゲイン)を

音圧を検知は「入力信号の絶対値をとったものにローパスフィルタを通す」ことでできます。
(他の方法もありますが、ここではこの方法を利用しています。)

フィルタは「簡単なデジタルフィルタのサンプルコード」を使用しています。
あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。

【実装イメージ】

上記はあくまで実装例です。
今回は急激に音量(ゲイン)が変化しないようにローパスフィルタを使用していますが、アタックやリリースを持ったエンベロープを使用することもあります。
また、音圧検知にRMS(二乗平均平方根)を使用することもあります。

質問はコメント欄や掲示板Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例

掲示板
■Twitterアカウント:@vstcpp   URL:https://twitter.com/vstcpp

エフェクターの簡単な実装例 – コーラス・フランジャー

コーラス・フランジャーの実装例

コーラス・フランジャーは入力信号に音程をずらした音を混ぜて音に厚みを持たせるエフェクターです。
コーラス・フランジャーの違いは明確になく、音程のずれの大きさで呼び方が変わります。
コーラスは音程のずれが少なく入力信号に厚みを持たせる程度のもで、フランジャーは音程のずれが大きく入力信号にジェットサウンドを加えたようなものになります。

パラメーターとして下記がよく利用されます。

パラメーター 意味 だいたいの範囲
ミックスレベル コーラス・フランジャーのかかり具合 0~1の間
レート 揺らぎの間隔(ディレイ信号の読み込み位置を揺らす速度) 0Hz~16Hz程度
深さ 揺らぎの深さ(ディレイ信号の読み込み位置を揺らす幅) 5.0~200.0サンプル程度
フィードバック フィードバックの効き具合 0~1の範囲

実装は入力信号に読み込み位置を周期的にずらした(揺らした)ディレイ信号を加えて出力します。
ディレイ信号の読み込み位置を周期的に揺らすことで、音程が数Hz~数十Hz程度変わります。この揺らしたディレイ信号を入力信号に加えることで音に厚みを持たせることができます。

ディレイ信号はリングバッファを使用して保存します。リングバッファは「リングバッファについて」で作成したものを使用しています。
また、読み込み位置を揺らした際、整数値にならない場合があるためサンプルとサンプルの間の位置の値を線形補間などを用いて割り出す必要があります。
線形補間の詳細は省略いたします。

あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。

【実装イメージ】
■線形補間の実装

■エフェクターの実装

上記はあくまで実装例です。
読み込み位置を揺らす関数をSin関数以外にしたり、リングバッファを複数用意することで音の揺れ方や厚みが変わります。
リングバッファに保存する信号やフィードバック信号を左右逆にしたり、フィルタをディレイ信号にかけてみるのも面白いかもしれません。

質問はコメント欄や掲示板Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例

掲示板
■Twitterアカウント:@vstcpp   URL:https://twitter.com/vstcpp

エフェクターの簡単な実装例 – グラフィックイコライザー

グラフィックイコライザーの実装例

グラフィックイコライザーとは入力音声の各周波の数帯域を増減させ、音を整えるエフェクターです。

パラメーターとしては各周波数ごとの増幅量(ゲイン)が利用されます。
各周波数の割り当ては100Hzあたりから、オクターブごとに割り当ててるものが多いです。

パラメーター 意味 だいたいの範囲
100Hzゲイン 100hz付近の増幅量 -15~15dB
200Hzゲイン 200hz付近の増幅量 -15~15dB
400Hzゲイン 400hz付近の増幅量 -15~15dB
800Hzゲイン 800hz付近の増幅量 -15~15dB
1,600Hzゲイン 1,600hz付近の増幅量 -15~15dB
3,200Hzゲイン 3,200hz付近の増幅量 -15~15dB
6,400Hzゲイン 6,400hz付近の増幅量 -15~15dB
12,800Hzゲイン 12,800hz付近の増幅量 -15~15dB

実装は入力信号をピーキングフィルタを順番に通すだけです。

フィルタは「簡単なデジタルフィルタのサンプルコード」を使用しています。
あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。

【実装イメージ】

上記はあくまで実装例です。

質問はコメント欄や掲示板Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例

掲示板
■Twitterアカウント:@vstcpp   URL:https://twitter.com/vstcpp

エフェクターの簡単な実装例 – ディレイ

ディレイの実装例

ディレイは入力信号に数ミリ秒前の信号(ディレイ信号)を混ぜて出力するエフェクターです

パラメーターとして下記がよく利用されます。

パラメーター 意味 だいたいの範囲
ディレイタイム ディレイの時間 50ミリ秒~2秒程度
レベル ディレイの効き具合(ディレイ信号の振幅) 0~1の間
フィードバック フィードバックの効き具合 0~1の範囲

実装は入力信号にディレイ信号を加えて出力します。ディレイ信号はリングバッファを使用して保存します。
リングバッファは「リングバッファについて」で作成したものを使用しています。
あくまで実装例ですのでいい音質のものがほしい場合は、ご自身で試行錯誤いただくようお願いします。

【実装イメージ】

上記はあくまで実装例です。
加えるディレイ信号やフィードバックで利用するディレイ信号を左右逆にしたり、フィルタをディレイ信号にかけてみるのも面白いかもしれません。
なお、for文の中やリアルタイム処理など音声処理中にディレイタイム(上記のtime変数)を変更するとクリップノイズのようなものが入る可能性があります。
変更時は一時的にディレイレベルを 0 にするか、ディレイタイムをゆっくり変更していく必要があります。

質問はコメント欄や掲示板Twitterでいただけばとおもいます。
他のエフェクター実装例はこちらにもあります。 → エフェクターの簡単な実装例

掲示板
■Twitterアカウント:@vstcpp   URL:https://twitter.com/vstcpp

リングバッファについて

リングバッファとは

ここではディレイやコーラスなどのエフェクターで利用されるリングバッファについて簡単に説明いたします。

リングバッファとはデータ確保領域が環状に配置されたエンドレスなバッファです。

リング状のバッファため通常の配列とは違って「先頭から○○番目のデータ」のような指定はできず、「読み込み位置から○○番目のデータ」と指定します。
そのため、リングバッファは内部的に読み取りと書き込みを行うバッファの位置の情報を持ちます。この読み取り位置・書き込み位置を動かす(進める)ことで必要なデータの読み取り・書き込みをします。

【リングバッファのイメージ】

実装に当たっては下記の図のように、1次元のバッファを用意し、読み取り位置や書き込み位置がバッファの大きさを超えるとバッファ先頭へ戻るという処理を行えば実装できます。
もっと見る