「大車輪」と名付けたその響き
そこで僕(と恐らく世界中の多くのDSPオタクども)が考えたのは、「トレモロ(振幅変調)をかけることによって、音量(フィードバック量)が0のポイントを作り、そのポイントでディレイタイムをサクッと変更する」 という技です。
当然音量の変化があるのですが、ディレイタップは複数あるわけで、それらを同一周期で、しかも位相をずらすことにより、サミダレ式に音量0のポイントがやってくるようにすれば、全体として「ほとんどトレモロがかかっているようには聴こえまい。この粉飾は99.9%バレない!」というように考えたわけです。図にすると次のようになります。

僕はこのスキームを「大車輪」と名付けました。それは今を遡ること昔、20世紀の終わり頃のことです。ちょうどその頃、僕は筋肉少女帯の同名のアルバムを良く聴いていて、何となく車輪状のトレモロ波形にディレイタップが等間隔で張り付いていて、地面に接するところでディレイタイムがサクサクっと変わっていく、ということをイメージしました。そんなイメージと、この言葉が妙にマッチしていたわけです。
しかし、これを器用に扱った結果としてプログラムを実際に書いたのは、つい今しがたのことです。閑話休題 。
仮にディレイタップ数を30として、トレモロの周期を4Hzとすると、ディレイタイムの変更は、毎秒120回も行われることになります。しかし個々のディレイタップのトレモロ周期を見れば4Hz程度なので目立った倍音も発生しないものと思われます。
しかし、思いついたことをそのまま実行に移しましたところ、想定外の自体に発展してしまいました。というのも、僕がコントロールしているのは只の音量ではなくフィードバック量だったからです。
ディレイエフェクトのフィードバック量を調整してみたことがある人なら分かると思うのですが、50%→51%と、98%→99%だと全然違うというか、前者はディレイ成分の減衰の速さにほとんど差は感じられないのですが、後者だと大きく違って聴こえると思います。
要するにフィードバック量に対して、ディレイ成分の減衰時間は指数関数的に対応づいているというのか、フィードバック量が多い時と少ない時で、残響量がまるで違っていて、先ほどのようにトレモロの波形に「DC(直流)オフセットのかかったサイン波(0~最大音量)」を使ったりすると、最大音量付近のタイミングでしかほとんど響かないことが判明したのです。
つまり、残響量という観点から考えてみると、

のつもりが、実は

だったわけです。
ディレイタップは残響を作り出すために存在する希少なリソースなわけですから、トレモロ波形としてDCオフセットのかかったサイン波では、全然厚みが生まれないし、まさにずさんな手口であり不適格ということが分かってしまいました。
更に言うと、このトレモロ波形では(詳しくは後に述べますが)フィードバック量の概算も難しいのです。最大フィードバック量をある一定の値に設定した時に、ディレイタップがトータルでどの程度の残響を作り出しているのか、見当が付かないのです。
そこで考えてみたトレモロ波形が、次のものです。

コード例で示すとこんな感じです。ちなみにphaseは0から1の範囲を、例えば4Hzくらいの周期で延々と繰り返す変数です。phase自体の波形は右肩上がりのノコギリ波(/|/|/|/|)ということになろうかと思います。
phase=0のところで、トレモロ波形の音量がちょうど0になるようになってます。
//0.0~0.1、0.9~1.0だけをcosでフェードアウトさせる if (phase < 0.1) { trem = (0.5 - cos(phase * 5 * GN_PI2) * 0.5); } else if (phase > 0.9) { phase = 1.0 - phase; trem = (0.5 - cos(phase * 5 * GN_PI2) * 0.5); } else { trem = 1.0; //最大振幅を維持 }
要するに、「ディレイタイムを変更するタイミングだけフェードアウトして、それ以外の時間は、最大のフィードバック量に固定しておく」というわけです。こうすれば、トレモロ周期の中で残響を作り出す時間も十分に取れますし、フィードバック量を概算するにも、フェードアウトする区間は例外というのか、誤差の範囲と考えることができます。
フィードバック量の概算
さて、リバーブ設計の1つの肝として重要なのは、フィードバック量の概算です。少ないディレイタップで重厚な響きを作り出すには、フィードバックに頼らざるを得ず、しかも複数のディレイタイムがランダムで存在するので、残響時間の見積もりは至難の業です。リバーブタイムが上手く定まらず、場合によってはハウリングというのか、音量が無限大方面へ発散してしまう自体に発展しかねない訳です。
でも、躊躇していては始まらないので、とりあえず1つのディレイタップだけだということにして、考え始めてみましょう。
まず、「リバーブタイム(残響時間)」とは何かというと、実はこれには業界標準の定義があります。つまり、
入力波形が途絶えてから、60dB減衰するまでの時間
です。60dB減衰とは、(音圧が)1000分の1に減衰と言い換えることもできます。これを保証するには、ディレイタイムとリバーブタイムとの比で考えることが重要です。
例えばディレイタイムが100ミリ秒で、リバーブタイムが1000ミリ秒だとしましょう。この場合、最初にインパルスが入力されてから、リバーブタイムである1000ミリ秒後に到達するまでの間に、10回のヤマビコが発生していることになります。また、ヤマビコはある一定の比率(フィードバック量)で指数関数的に減衰していくため、10回目のヤマビコは、フィードバック量を10回掛け合わせた結果の音量になっていることになります。90%のフィードバック量だったら0.9の10乗で、0.3486784401という数字になります。これは1000分の1(0.001)よりも大きな値ですから、0.9というフィードバック量では大き過ぎることになります。
ぶっちゃけ、この課題をクリアするには以下の数式を使うことになっています。
フィードバック量=0.001^(ディレイタイム÷リバーブタイム)
(^はべき乗を表わす)
今回の場合だったら、
フィードバック量=0.001^(100÷1000) = 0.001^0.1 = 約0.5012
となります。ちなみにべき乗はC言語の標準ライブライリなんかだと、pow(底,指数)という関数が用意されているようです。
あとは、ディレイタップ数がフィードバック量にどう影響するかを考えないと行けません。でもこれは、僕には荷が重過ぎます。なので、ディレイタップ数を色々と変えてみて、実験を繰り返しつつ、適当に勘でやってみたところ、「ディレイタップ数の平方根で割ってみる」と大体上手くいくようです。合わせると、次のようになりました。
フィードバック量=(0.001^(ディレイタイム÷リバーブタイム))÷sqrt(ディレイタップ数)
(sqrt()は平方根を表わす)
あと、フィードバックの位相にも注意が必要です。プラスばかりのフィードバックだと、基本的に直流成分が優勢になるというのか、本質的にはローパスフィルタしか作れないことになっていたりして、波形が上や下にへばりついてしまいます。
逆にマイナスの位相ばかりだと、今度は、低音から削れてしまうという悩みを抱えることになります。なので、フィードバックの位相はプラスとマイナスで偏りがないように、交互に設定するなどの対応が必要となります。
