地図/信号/ノイズとゆらぎ

1/f ゆらぎ — 自然が心地よい理由

1/f のゆらぎは自然界のあちこちに顔を出す。小川のせせらぎ、ろうそくの炎の揺れ、人の心拍の間隔、名演奏のテンポの揺れ。スペクトルが周波数に反比例して下る傾きを持ち、白すぎず茶すぎない中間にある。

1/f ゆらぎ。スペクトル密度が周波数 f に反比例する(傾き -1)信号。全周波数が均等な白色ノイズ(傾き 0)と、低音に強く偏ったブラウンノイズ(傾き -2)のちょうど中間にあたる。武者利光が音楽や生体信号で調べ、白すぎると無機質で落ち着かず、1/f² すぎると単調で退屈、その間の 1/f を人は心地よく感じると論じた。生成の手軽な近似が Voss-McCartney 法で、更新周期を倍々にずらした複数の乱数源を足し合わせる。

Voss-McCartney 法は、何本かのサイコロをそれぞれ違う周期でだけ振り直して全部を足し合わせる。速く振り直すサイコロが高音、ゆっくりのが低音を受け持つ。

その部品はサイコロ1個。新しい値を拾ったら、次に振り直すまで同じ値を水平に保つ。更新の瞬間だけ縦に飛んで、また平らに伸びる。下は周期8でだけ振り直す1個を描いたもの。

値を拾った列でだけ縦に飛び、間は前の値を引きずって水平に伸びる。モジュラーシンセのサンプル&ホールド(乱数を拾って次まで保持する)と同じ階段になる。

この階段を周期の違うサイコロで何本も並べて足す。どの列でどのサイコロを振り直すかは、列番号 i の末尾ビットで決める。下位ビットが立つたびに速いサイコロ、上のビットが立つたびに遅いサイコロが更新される。末尾の連続する0ビットの数が、その列で振り直す最上位のサイコロになる。

// i 列目で「どこまで振り直すか」を末尾ビットで決める
let bit = 0
while (bit < rows - 1 && ((i >> bit) & 1) === 0) bit++
values[bit] = Math.random() // bit 番目のサイコロを更新、下位はそのまま保持

values は各サイコロの現在値で、振り直されなかったサイコロは前の値を保持し続ける(階段の水平部分)。下は6本ぶん。上に個別の階段、いちばん下にその全部を足した 1/f。速い段は細かく、遅い段はゆったり踏み替える。

上の段々はどれも単なる階段(サンプル&ホールド)。それを6本、更新周期を倍々にずらして足すと、下の太い線のような自然なゆらぎになる。速いサイコロが高音の小刻みを、遅いサイコロが低音の大きなうねりを担当する。rows を増やすほど低音側のうねりが伸び、減らすと細かい段ばかりが残る。乱数をどんな周期で振り直してどう重ねるかだけで、ゆらぎの傾きが決まる。