エンベロープの回 で、サイン波は「具のないスープ」だと書きました。音量の輪郭をどれだけ作り込んでも、中身がサイン波のままでは、ピアノらしい鳴り方の系統までしか近づけない。本物の太い響きを出すには倍音たっぷりの波形が要る、という宿題を残したままでした。今回はその宿題の回収です。倍音とは何で、どうすれば「倍音たっぷりの波形」を自分の手で作れるのかを、音の出るデモと一緒に見ていきます。

音の高さが同じでも、音色が違うのはなぜか

ピアノの「ラ」とフルートの「ラ」は、同じ高さなのにまるで違う音に聞こえます。マイクで録って波形を見比べると、違いは一目瞭然です。どちらも同じ間隔で同じパターンをくり返しているのに、そのくり返される「波の形」が違うのです。

同じ高さのラでも、サイン波・ノコギリ波・矩形波では波の形が違い、別の音色に聞こえるという比較図

コンピューターの中では、音は「スピーカーの膜をその瞬間どれだけ押し出すか」を表す数の列として、1秒あたり44100個の速さで流れています。波が1秒に何回くり返すか(周期の細かさ)が音の高さを決め、1回ぶんの波がどんな形をしているかが音色を決めます。上の図の3つは、くり返しの速さがそろっているのでどれも同じ高さの「ラ」ですが、聞こえ方は別物です。サイン波は音叉のような澄んだ音、ノコギリ波は弦や金管のような張りのある音、矩形波は昔のゲーム機のようなピコピコした音がします。

そうなると次の疑問は、この「波の形」をプログラムでどう作るかです。ノコギリの歯のような折れ線を数式で直接書いてもよさそうなものですが、サウンドプログラミングの世界には、もっと見通しのよい考え方があります。それが今回の主役、倍音です。

どんな波も、サイン波の足し算でできている

19世紀フランスの数学者フーリエは、のちの信号処理をまるごと支えることになる事実を見つけました。どんなに複雑な形の波でも、周期的にくり返ってさえいれば、それは必ず「基本のサイン波と、その整数倍の速さのサイン波たち」の足し算に分解できる、というものです(フーリエ級数と呼ばれます)。

音の言葉に翻訳するとこうなります。いちばん低い、音の高さを決めているサイン波を基音と呼び、その2倍、3倍、4倍……の速さで揺れるサイン波たちを倍音と呼びます。ピアノのラも、フルートのラも、分解すればどちらも「220Hzの基音+440Hzの倍音+660Hzの倍音+……」という同じ品目のリストになる。違うのは、それぞれの倍音がどれだけの量で入っているかという配合比だけです。音色の正体は、この配合比なのです。

分解できるということは、逆に組み立てることもできるはずです。ここが今回の核心で、実際にサイン波を1本ずつ足していくと、目の前で波形が「育って」いきます。

基音に2倍・3倍の速さのサイン波を1/2、1/3の振幅で足していくと、波形が段々とノコギリ波の形に育っていく過程図

レシピは拍子抜けするほど単純で、$n$ 倍の速さの波を $1/n$ の量で、ぜんぶ足すだけ。基音1本ではただのサイン波だったのが、2倍の波を半分の量で足すと波が傾きはじめ、3倍の波を1/3で足すとギザギザの気配が出てきて、8倍まで足せばもう、はっきりノコギリ波の姿になります。足しているのは終始、角のまるいサイン波だけです。それなのに、足せば足すほど鋭い角が立ち上がってくる。初めて見ると、ちょっとした手品のようです。

倍音ごとの量を棒グラフに並べたものが、いわば音色の配合表です。そして配合表を少し書き換えるだけで、できあがる波形はがらりと変わります。

ノコギリ波は全倍音を1/nで、矩形波は奇数倍音だけを1/nで混ぜるという配合表と、できあがる波形の比較図

全部の倍音を $1/n$ で混ぜればノコギリ波。偶数番目を抜いて、奇数の倍音だけを $1/n$ で混ぜれば矩形波。ゲーム機のあのピコピコ音は、「偶数の倍音が入っていない」という配合の音だったわけです。このようにサイン波を積み上げて音色を作る方式は加算合成と呼ばれ、シンセサイザーの最も古典的な作り方のひとつです。パイプオルガンは、長さの違うパイプ(それぞれがほぼサイン波を出します)を同時に鳴らして音色を作るので、いわば物理装置による加算合成です。

ついでに自作アプリの話を少しだけ。筆者が個人開発している音感トレーニングアプリ Harmonize でも、オルガン・フルート・尺八といった音色は、まさにこの正弦倍音の重ね(加算合成)で鳴らしています。配合表を楽器ごとに変えているだけ、と言ってしまえるのがこの方式の気持ちよさです。

触ってみる

ここまでの話を、実際に手で混ぜられるデモを用意しました。スライダー8本がそのまま倍音の配合表です。まず「🌱 1本ずつ足して育てる」を押してみてください。基音だけのサイン波に倍音が1本ずつ加わって、澄んだ「ポー」という音がだんだん張りのあるブラスのような音に変わり、波形にノコギリの歯が立っていきます。さきほどの図が、音付きで動く様子を見られます。

うまく表示されないときは、デモを別タブで開く

鳴らしたまま、ノコギリ波と矩形波のプリセットを切り替えてみると、「偶数の倍音を抜く」だけで音の性格が変わるのがわかります。それから、どのスライダーをどう動かしても、音の高さそのものは変わらないことにも注目してください。高さを握っているのはくり返しの速さ、つまり基音の周波数で、倍音の配合は音色だけを受け持っています。むしろ基音のスライダーを0にしてしまっても、耳にはほぼ同じ高さに聞こえ続けるはずです。倍音の並びの「間隔」から、耳が勝手に基音を補ってしまうからで、この不思議は鳴らしていない低音が聞こえる話 として以前に取り上げました。

どう実現するか

デモの中身は、レシピをそのまま数式にしたものです。基音の周波数を $f_0$ として、ノコギリ波は

$$x(t) = \frac{2}{\pi} \sum_{n=1}^{N} \frac{1}{n} \sin(2\pi n f_0 t)$$

と書けます。$n$ 倍の速さのサイン波を $1/n$ の量で足し合わせる、あの図のとおりの式です(先頭の $2/\pi$ は、全体の高さを $\pm1$ にそろえるための定数です)。矩形波なら、和を奇数の $n$ だけに限って係数を $4/\pi$ にすれば得られます。プログラムにするなら、二重ループが1つあれば足ります。

/* ノコギリ波を倍音の足し算で作る(C風の擬似コード) */
for (i = 0; i < length; i++) {
    double t = (double)i / fs;              /* いまの時刻(秒) */
    double v = 0;
    for (n = 1; n <= 8; n++)                /* 倍音を8本 */
        v += sin(2.0 * M_PI * n * f0 * t) / n;   /* n倍の波を 1/n で足す */
    output[i] = (2.0 / M_PI) * v;
}

ブラウザの Web Audio API なら、サイン波を1本鳴らす部品(OscillatorNode)を8個作って、それぞれの音量を $1/n$ にしてつなぐだけです。足し算はどこにも書いていませんが、複数の音源を同じ出力へつなぐと自動的に混ざる、つまり配線そのものが足し算になっています。

for (let n = 1; n <= 8; n++) {
  const osc = ctx.createOscillator();   // サイン波が1本鳴るだけの部品
  osc.frequency.value = f0 * n;         // n倍の高さで
  const gain = ctx.createGain();
  gain.gain.value = 1 / n;              // 1/n の量にして
  osc.connect(gain).connect(master);    // 混ぜる(つなぐ=足し算)
  osc.start();
}

ひとつだけ実務上の注意を添えると、倍音は好きなだけ高くまで足せるわけではありません。デジタル音声にはサンプリング周波数の半分(44100Hzなら22050Hz)という天井があって、それを超える倍音を足すと音が濁ります。今回のデモは8倍音(最高1760Hz)までなので余裕がありますが、低い音でノコギリ波を精密に作ろうとすると、この天井との付き合い方が問題になってきます。これはこれで面白い話なので、いずれ回をあらためて取り上げるつもりです。

足して作るか、削って作るか

今回の加算合成は、フィルタの回 でやったことのちょうど裏返しです。あのときは、すでに倍音を含んでいる音からフィルタで高い成分を削って、音色を丸くこもらせました。今回は逆に、何も持たないサイン波に倍音を1本ずつ足して、音色に張りを与えました。じつはアナログシンセサイザーの王道は「倍音たっぷりのノコギリ波をまず鳴らし、フィルタで削って整える」という減算方式で、足し算で作ったノコギリ波は、こんどは削られる側の素材として主役になります。倍音という物差しを一本持つと、音作りの道具たちが「足すか、削るか」というひとつの地図の上に並んで見えてくるはずです。

参考文献

サイン波と足し算だけで、ノコギリの歯が立つ。まずはデモの「1本ずつ足して育てる」で、波形が育つ瞬間を見てみてください。