SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

少ないディレイタップ数で厚みのある残響音を作るテクニック

リバーブサウンド(残響音)生成アルゴリズム一考

「大車輪」と名付けたその響き

 そこで僕(と恐らく世界中の多くの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()は平方根を表わす)

 あと、フィードバックの位相にも注意が必要です。プラスばかりのフィードバックだと、基本的に直流成分が優勢になるというのか、本質的にはローパスフィルタしか作れないことになっていたりして、波形が上や下にへばりついてしまいます。

 逆にマイナスの位相ばかりだと、今度は、低音から削れてしまうという悩みを抱えることになります。なので、フィードバックの位相はプラスとマイナスで偏りがないように、交互に設定するなどの対応が必要となります。

次のページ
確率密度は蜜の味

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

鼻クローン(ハナクローン)

アルゴリズムオタクです。今は信号処理、統計処理などを頑張って勉強してます。勉強!自分の仕事とあまり関係していないことが玉に傷ですが。。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/315 2006/02/21 19:15

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー