雨の音を合成してみる

本記事では「Designing Sound」[1]で紹介されている雨の音の合成を試してみようと思います。合成にはサウンドプログラミングツールの Pure Data を使用しました。

¥10,194 (2026/04/20 01:27時点 | Amazon調べ)
\楽天ポイント4倍セール!/
楽天市場
\商品券4%還元!/
Yahooショッピング

小雨

まず、小雨の音源合成を試してみます。小雨が「地面に当たったとき」と「窓に当たったとき」の音源合成方法について紹介します。

作り方の概要

「地面に当たった小雨」については下図のような放物線上のパルスを作ることで再現します。このパルスを加工することで、「窓に当たった小雨」も再現します。

図:小雨の波形
図:小雨の波形

地面に当たった小雨の実装

「地面に当たったとき」の小雨を合成するブロック図は以下です。

図:小雨の合成ブロック図
図:小雨の合成ブロック図

まず、ガウス雑音を生成して、それを 50Hz のBPFと 500Hz のLPFに通します。

次に周波数と振幅を別々の経路で決定します。左の経路で周波数、右の経路で振幅を決めます。

周波数については -0.3~0.3 くらいの信号を x80 → +40 して 16~64 にしたのち、「phasor~」に入力することで、16Hz~64Hz ののこぎり波を生成します。のこぎり波を「cos~」に入力することで 16Hz~64Hz に変動するサイン波を作ります。振幅については放物線状になるように信号を2乗して10を掛けることで決めていきます。

それら周波数と振幅を掛け合わせて、「max~ 0.35」と「-~ 0.35」で0.35以下の信号はゼロにすることで、放物線状のパルスとならないところは除去します。

最後に小雨の観測点が遠い位置では高域が支配的になるため、「hip~ 500」でHPFを掛けて低域を除去します。

上記の方法で合成した小雨が以下です。

Rain On Ground



0:00 / 0:00

せとち
ヘッドホンで聴くと多少違和感はあるけど、スピーカーで聴くとたしかに小雨っぽい。

補足:最初の雑音生成において、一様分布の乱数ではなくガウス分布の乱数を使用したのは、自然な音にするためです。自然界にはガウス分布の信号が多いため、そのほうが自然に聴こえるみたいです。

ガウス分布の乱数の生成にはBox-Muller法を使用しています。「gauss_noise」のブロック図は以下です。

図:「gauss_noise」のブロック図
図:「gauss_noise」のブロック図

Box-Muller法は以下の計算式で [0,1] の一様乱数\(\ U_{1}, U_{2}\ \)からガウス分布\(\ N(0,1)\ \)の乱数 \(N\ \)を生成する方法となります。

$$
N = \sqrt{-2 \log{U_{1}}} \cos{\left(2\pi U_{2}\right)}
$$

ブロック図を見ていくと、「noise~」については [-1,1] の乱数を生成するため、「max~」と「min~」で 範囲を [0,1] になるようにしています。

「sig~」を使って\(\ U_{1}\ \)の分布範囲を [1-$1,1] にしてそうですが、資料[1]に説明がないため、この意図についてはよくわからないです。$1 は振幅に関係するパラメータなので、これでガウス分布の標準偏差が変わるのかな?

\(\cos{\left(2\pi U_{2}\right)}\) の部分については「noise~」と「cos~」で計算しています。

窓にあたる小雨

「窓に当たったとき」の小雨を合成するブロック図は以下です。

図:窓にあたる小雨のブロック図
図:窓にあたる小雨のブロック図

「raindrops」については「地面にあたったときの小雨」をパッチ化したものです。引数1がBPFの通過帯域周波数、引数2がBPFのQ値、引数3がしきい値処理におけるしきい値となります。

「raindrops」で生成した音をHPFに通して、「laminar_model」で窓にあたったときの窓の振動をシミュレーションさせています。

「laminar_model」のブロック図は以下です。

図:「laminar_model」のブロック図
図:「laminar_model」のブロック図

まず、入力信号を「delwrite~」でディレイライン(300ms 分のバッファ)に追加して、「delread~」でそれを読み出します。遅延時間[ms]については「delread~」の引数2で指定します。これで、音が窓の端で反射して往復する様子を再現します。

つぎに、「*~ $11」で信号を減衰させたのち、BPFで共鳴周波数を強調させるようにします。

「osc~」でサイン波を掛け算してAM変調を行います。このAM変調によって、音が窓を伝わる速度が周波数によってバラバラになる(分散効果)を表現するみたいです(ChatGPT情報)。正直言ってよくわかっていないです。

最後に「delread~ $0-a」で取り出した音を「throw~ $0-b」で「catch $0-b」に送ります。これで左進行波が反射して右進行波になるのを表現します。「delread~ $0-b」で取り出した音も同じようにループさせます。「delread~ $0-a」で取り出した音を「throw~ $0-a」に送って自己フィードバックしている理由はわからないです。なぜなんだろう?

上記の方法で合成した小雨が以下です。

Rain On Window



0:00 / 0:00

せとち
窓というより、トタン板に当たった雨の音に聴こえますね

AM変調:元の信号の周波数を\(\ f_{c}\ \)、「osc~」の周波数を\(\ f_{m}\ \)とすると、AM変調(振幅変調)によってその和(\(\ f_{c}+f_{m}\ \))と差(\(\ f_{c}-f_{m}\ \))の成分(サイドバンド)が生まれます。

このことは、以下の三角関数の積和の公式でもわかると思います。

$$
\cos{\alpha}\cos{\beta} = \frac{1}{2}\{\cos{(\alpha+\beta)}+\cos{(\alpha-\beta)}\}
$$

このサイドバンドが分散効果のように聞こえるらしいです。

本降りの雨

作り方の概要

本降りの雨を作る場合、個々の雨粒から作成するのは非効率です。そのため、ノイズに対して BPF 処理、クリップ処理、しきい値処理、4乗処理をすることで合成を行います。

フリーハンドですみませんが、下図のようなイメージです。

図:本降りの雨の合成方法の概要
図:本降りの雨の合成方法の概要

BPF で 7Hz くらいの帯域を抽出して、それを [0,1] にクリップさせます。

クリップさせた信号をしきい値処理でノイズ除去を行い、4乗処理することで本降りの雨を合成します、

実装方法

本降りの雨の実装方法は以下のようになります。

図:本降りの雨のブロック図
図:本降りの雨のブロック図

「drops」で信号を作成して、「hip~」に通すことで本降りの雨を合成します。また、「drops」のBPFのQ値をスライダー操作することで、観測点と雨の距離を変えられます。

「drops」のブロック図は以下です。

図:「drops」のブロック図
図:「drops」のブロック図

まず、「noise~」で一様分布の乱数を作成して、それをBPFに通し、[0,1] の範囲にクリップさせます。

その後、「max~」でしきい値処理をすることで、スパイク状の大きい信号だけを残し、最後に信号を4乗することでパルス状の信号にしていきます。

上記の方法で合成した雨が以下です。

General Ambient Rain Noise



0:00 / 0:00

せとち
これについてもヘッドホンで聴くとノイズっぽいけど、スピーカーで聴くとたしかに雨っぽいかも。

おわりに

本記事では、「Designing Sound」の雨の音の合成を試してみました。雨の音だけでもいろいろな合成方法があり、結構驚いています。ちなみに記事に載せた雨の合成方法は一部です。資料[1]には他にも雨の合成方法があるので、気になる方は試してみてください。

ところで、「Designing Sound」のサンプルコードは以下のサイトにあります。

■「Designing Sound」のサンプルコード(Rain)
https://aspress.co.uk/sd/practical15.html

このサイトで試聴できる雨の音を聴いてみたのですが、かなりリアルで衝撃的でした。自分でもリアルな雨の音を実装しようと試行錯誤したのですが、なかなか同じような音になりません。実装方法について何かわかる方がいれば、コメントしていただければ幸いです。

■参考文献
[1] A.Farnell,  Designing Sound,  MIT Press,  2010.