ノイズ生成
Noise Generation — Theory and Implementation
ノイズ(雑音)は、信号処理のテスト、音響測定、ディザリング、シミュレーションなど多くの場面で不可欠な信号である。 ここでは各種ノイズの数学的特性と生成手法を解説し、特にピンクノイズについては Paul Kellet の IIR フィルタ法と IFFT 法を詳しく分析する。
1. 色付きノイズの分類
ノイズはパワースペクトル密度 $S(f)$ の周波数依存性によって分類される。 一般に $S(f) \propto 1/f^\alpha$ と表され、指数 $\alpha$ によって「色」が決まる。
| 名称 | 指数 $\alpha$ | パワースペクトル密度 | 特徴 |
|---|---|---|---|
| ホワイトノイズ | $0$ | $S(f) = \text{const.}$ | 全帯域均一、理論解析の基準 |
| ピンクノイズ($1/f$) | $1$ | $S(f) \propto 1/f$ | オクターブ等エネルギー、音響測定 |
| ブラウンノイズ($1/f^2$) | $2$ | $S(f) \propto 1/f^2$ | ランダムウォーク、低周波成分優勢 |
| ブルーノイズ | $-1$ | $S(f) \propto f$ | 高周波成分優勢、ディザリング |
| バイオレットノイズ | $-2$ | $S(f) \propto f^2$ | ホワイトノイズの微分 |
2. ホワイトノイズ
ホワイトノイズは、パワースペクトル密度が全周波数にわたって一定である理想的な雑音である。 離散時間では各サンプル $x[n]$ が独立同分布 (i.i.d.) に従う系列として定義される。
統計的性質
- 自己相関関数: $R_{xx}[m] = \sigma^2 \delta[m]$
- パワースペクトル密度: $S_{xx}(e^{j\omega}) = \sigma^2$(一定)
- 確率分布: ガウス分布が最も一般的だが、一様分布なども使用される
生成方法
- 一様分布ホワイトノイズ — 疑似乱数生成器(メルセンヌ・ツイスタ、xoshiro など)を使用
- ガウスホワイトノイズ — Box-Muller 法や Ziggurat 法で一様乱数を正規分布に変換
Box-Muller 法
独立な一様乱数 $U_1, U_2 \sim \text{Uniform}(0,1)$ から、独立な標準正規乱数の組 $(Z_1, Z_2)$ を生成する:
$$Z_1 = \sqrt{-2\ln U_1}\,\cos(2\pi U_2), \quad Z_2 = \sqrt{-2\ln U_1}\,\sin(2\pi U_2)$$3. ピンクノイズ($1/f$ ノイズ)
ピンクノイズはパワースペクトル密度が周波数に反比例する雑音であり、 オクターブあたりのエネルギーが等しいという特徴を持つ。 音響測定、音楽制作、自然現象のモデリングに広く使われる。
主要な生成手法
| 手法 | 原理 | 精度 | 用途 |
|---|---|---|---|
| IIR フィルタ法 | ホワイトノイズに $1/\sqrt{f}$ 特性のフィルタを適用 | 近似(設計依存) | リアルタイム処理 |
| Voss-McCartney 法 | 異なる更新頻度の乱数列を加算 | 近似(段数依存) | 低コスト実装 |
| IFFT 法 | 周波数領域で $1/\sqrt{f}$ を設定し逆 FFT | 厳密 | オフライン生成 |
3.1 理想的なピンクノイズフィルタ
連続時間においてホワイトノイズをピンクノイズに変換するフィルタの伝達関数は:
$$H(s) \propto \frac{1}{\sqrt{s}} = s^{-1/2}$$これは分数階微積分(fractional calculus)の演算子であり、 有理関数では正確に表現できない。 したがって、有限次の IIR フィルタで近似する必要がある。
近似の基本方針は、$1/\sqrt{s}$ を1次項の部分分数に展開することである:
$$\frac{1}{\sqrt{s}} \approx \sum_{k=0}^{N-1} \frac{\beta_k}{s + p_k}$$極 $p_k$ を対数等間隔に配置し、留数 $\beta_k$ を調整すると $-3$ dB/oct($= -10$ dB/dec)のスロープを広帯域にわたって近似できる。 Oustaloup の再帰近似法はこの方針を体系化したものであり、 極と零点を厳密に対数等間隔に配置する。
3.2 Paul Kellet の IIR フィルタ
Paul Kellet が musicdsp.org で公開したフィルタは、6段の1次 IIR フィルタを並列に合成して $-3$ dB/oct 特性を近似する。 係数は理論的な最適化ではなく、Visual Basic のプログラムで インパルス応答をプロットしながら手動で調整されたものである。
3段階の精度のバリエーションがあり、ここでは最高精度の Refined(Instrumentation grade)版を分析する。
差分方程式
ホワイトノイズ $x[n]$ を入力とし、各段のフィルタ状態 $b_k[n]$ を以下で更新する:
$$b_k[n] = \alpha_k \cdot b_k[n-1] + \beta_k \cdot x[n] \quad (k = 0, 1, \ldots, 5)$$加えて1サンプル遅延の項 $b_6$ があり、出力は:
$$y[n] = \sum_{k=0}^{5} b_k[n] + b_6[n] + 0.5362 \cdot x[n]$$ここで $b_6[n] = 0.115926 \cdot x[n-1]$($b_6$ は出力に加算された後に更新される)。
フィルタ係数
| 段 | $\alpha_k$(極) | $\beta_k$(ゲイン) | 極周波数 @44.1kHz |
|---|---|---|---|
| $b_0$ | $0.99886$ | $0.0555179$ | $\approx 8\;\text{Hz}$ |
| $b_1$ | $0.99332$ | $0.0750759$ | $\approx 47\;\text{Hz}$ |
| $b_2$ | $0.96900$ | $0.1538520$ | $\approx 218\;\text{Hz}$ |
| $b_3$ | $0.86650$ | $0.3104856$ | $\approx 937\;\text{Hz}$ |
| $b_4$ | $0.55000$ | $0.5329522$ | $\approx 3160\;\text{Hz}$ |
| $b_5$ | $-0.7616$ | $-0.0168980$ | $\approx 12360\;\text{Hz}$ |
極周波数の概算値は $f_p \approx f_s(1 - |\alpha_k|) / (2\pi)$ で得られる。 隣接する極の周波数比は $\times 5.9$, $\times 4.6$, $\times 4.3$, $\times 3.4$ であり、 概ね対数等間隔だが一定ではない。これは手動チューニングの痕跡である。
C++ 実装例
// Paul Kellet pink noise filter (Refined / Instrumentation grade)
// 入力: white — ホワイトノイズサンプル ([-1, +1])
// 状態: b0〜b6 は呼び出し間で保持する (初期値 0)
double white = rng.nextDouble() * 2.0 - 1.0; // 一様乱数
b0 = 0.99886 * b0 + white * 0.0555179;
b1 = 0.99332 * b1 + white * 0.0750759;
b2 = 0.96900 * b2 + white * 0.1538520;
b3 = 0.86650 * b3 + white * 0.3104856;
b4 = 0.55000 * b4 + white * 0.5329522;
b5 = -0.7616 * b5 - white * 0.0168980;
double pink = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
b6 = white * 0.115926;
// pink を出力として使用(必要に応じて正規化)
3.3 伝達関数 $H(z)$ の導出
各段の伝達関数
差分方程式 $b_k[n] = \alpha_k \cdot b_k[n-1] + \beta_k \cdot x[n]$ の Z 変換を取ると:
$$B_k(z) = \alpha_k z^{-1} B_k(z) + \beta_k X(z)$$ $$B_k(z)(1 - \alpha_k z^{-1}) = \beta_k X(z)$$したがって各段の伝達関数は:
$$H_k(z) = \frac{B_k(z)}{X(z)} = \frac{\beta_k}{1 - \alpha_k z^{-1}} \quad (k = 0, 1, \ldots, 5)$$$b_6$ の伝達関数
$b_6$ は出力の加算に使用された後に $x[n]$ で更新される。 すなわち、加算時点での $b_6$ の値は前サンプルの $x[n-1]$ に基づく:
$$H_6(z) = 0.115926\,z^{-1}$$全体の伝達関数
出力 $y[n] = \sum_{k=0}^{5} b_k[n] + b_6[n] + 0.5362 \cdot x[n]$ より:
$$\boxed{H(z) = \sum_{k=0}^{5} \frac{\beta_k}{1 - \alpha_k z^{-1}} + 0.115926\,z^{-1} + 0.5362}$$各項を展開すると:
$$H(z) = \frac{0.0555179}{1 - 0.99886\,z^{-1}} + \frac{0.0750759}{1 - 0.99332\,z^{-1}} + \frac{0.1538520}{1 - 0.96900\,z^{-1}}$$ $$\quad + \frac{0.3104856}{1 - 0.86650\,z^{-1}} + \frac{0.5329522}{1 - 0.55000\,z^{-1}} - \frac{0.0168980}{1 + 0.7616\,z^{-1}}$$ $$\quad + 0.115926\,z^{-1} + 0.5362$$構造の特徴: これは全極型フィルタ + FIR 項の並列合成である。 Oustaloup の近似法と異なり零点を持たず、直達項 $0.5362$ と 1サンプル遅延項 $0.115926\,z^{-1}$ が高域の応答を補正している。
3.4 周波数特性 $H(\omega)$ の導出
$z = e^{j\omega}$ を代入する。各 IIR 段の分母は:
$$1 - \alpha_k e^{-j\omega} = (1 - \alpha_k \cos\omega) + j\,\alpha_k \sin\omega$$各段の実部・虚部
$H_k(e^{j\omega}) = \frac{\beta_k}{1 - \alpha_k e^{-j\omega}}$ の実部と虚部を分離すると:
$$\operatorname{Re}_k(\omega) = \frac{\beta_k(1 - \alpha_k \cos\omega)}{1 - 2\alpha_k\cos\omega + \alpha_k^2}$$ $$\operatorname{Im}_k(\omega) = \frac{\beta_k\,\alpha_k \sin\omega}{1 - 2\alpha_k\cos\omega + \alpha_k^2}$$$b_6$ + 直達項
$$\operatorname{Re}_{6+d}(\omega) = 0.115926\cos\omega + 0.5362$$ $$\operatorname{Im}_{6+d}(\omega) = -0.115926\sin\omega$$全体の応答
$$\operatorname{Re}(\omega) = \sum_{k=0}^{5} \operatorname{Re}_k(\omega) + \operatorname{Re}_{6+d}(\omega)$$ $$\operatorname{Im}(\omega) = \sum_{k=0}^{5} \operatorname{Im}_k(\omega) + \operatorname{Im}_{6+d}(\omega)$$振幅特性・位相特性
$$|H(\omega)| = \sqrt{\operatorname{Re}(\omega)^2 + \operatorname{Im}(\omega)^2}$$ $$\angle H(\omega) = \arctan\!\left(\frac{\operatorname{Im}(\omega)}{\operatorname{Re}(\omega)}\right)$$ここで $\omega = 2\pi f / f_s$($f_s$: サンプリング周波数)。
各段の振幅応答
個々の IIR 段の振幅応答は以下の閉じた形で表される:
$$|H_k(\omega)| = \frac{|\beta_k|}{\sqrt{1 - 2\alpha_k \cos\omega + \alpha_k^2}}$$ただし全体の振幅応答は各段の振幅の単純な和ではない。 位相の異なる複素数の和であるため、実部と虚部を別々に合算してから 絶対値を取る必要がある。
周波数特性のプロット
$f_s = 44100\;\text{Hz}$ における Kellet フィルタの振幅特性と、理想的な $-3$ dB/oct からの偏差を以下に示す。
- 10 Hz – 4 kHz: 偏差 $\pm 0.1$ dB 以内 — ほぼ完璧な近似
- 4 kHz – 10 kHz: 最大 $-1$ dB 程度 — わずかに減衰が大きい
- 10 kHz 以上: Nyquist に向かって急落(IIR の限界)
6つの1次フィルタのみで可聴帯域のほぼ全域をカバーしている、非常に優れた近似である。
3.5 サンプリング周波数依存性
Kellet フィルタの係数は固定であるため、 サンプリング周波数 $f_s$ が変わると極周波数がすべてシフトし、 近似の精度が変化する。 極周波数は $f_p \approx f_s(1 - |\alpha_k|) / (2\pi)$ に比例するため:
| 段 | 22.05 kHz | 44.1 kHz | 96 kHz | 192 kHz |
|---|---|---|---|---|
| $b_0$ | 4 Hz | 8 Hz | 17 Hz | 35 Hz |
| $b_1$ | 23 Hz | 47 Hz | 102 Hz | 205 Hz |
| $b_2$ | 109 Hz | 218 Hz | 475 Hz | 950 Hz |
| $b_3$ | 469 Hz | 937 Hz | 2039 Hz | 4078 Hz |
| $b_4$ | 1580 Hz | 3160 Hz | 6878 Hz | 13756 Hz |
| $b_5$ | 6180 Hz | 12360 Hz | 26900 Hz | 53800 Hz |
注意: $f_s = 96\;\text{kHz}$ や $192\;\text{kHz}$ では、 極が高域にシフトし $-3$ dB/oct の近似が大きく劣化する。 Kellet 本人は 44.1 kHz 用の1セットしか示しておらず、 他のサンプルレート用の係数は提供していない。
Lubomir によるサンプルレート別係数(2009年)
musicdsp.org の同ページに Lubomir が投稿した拡張版では、
各段の目標極周波数 $f_k$ をサンプルレート帯域ごとに定義し、
$\alpha_k = e^{-2\pi f_k / f_s}$ で極係数を算出する方式が示されている。
ただしゲイン係数 $\beta_k$ は提供されておらず、
出力は各段の単純な加算 b0+b1+b2+b3+b4+b5+white-b6 となっている。
Kellet のような精密なゲイン調整が行われていないため、
スペクトルの平坦性は Kellet オリジナルより劣る可能性がある。
| $f_s$ 帯域 | $f_0$ | $f_1$ | $f_2$ | $f_3$ | $f_4$ | $f_5$ | $f_6$ |
|---|---|---|---|---|---|---|---|
| $\leq 48.1\;\text{kHz}$ | 4753 | 4031 | 2785 | 1538 | 358 | 70 | 30 |
| $44.8\text{k}$–$96\;\text{kHz}$ | 8227 | 8227 | 6389 | 3303 | 479 | 151 | 54 |
| $96\text{k}$–$192\;\text{kHz}$ | 9212 | 8621 | 8555 | 8293 | 518 | 164 | 240 |
| $\geq 192\;\text{kHz}$ | 10000 | 10000 | 10000 | 10000 | 545 | 142 | 212 |
高サンプルレートほど極周波数が密集しており、Lubomir 自身も 「高サンプルレートではフィルタの品質が劣化する」と指摘している。 これは 6 段の IIR フィルタという構造的な限界に起因するものであり、 極の数を増やさない限り本質的な改善は難しい。
対策の選択肢
- 係数テーブル切替: 上記の Lubomir 方式で $f_s$ 帯域ごとに係数を切り替える
- 動的係数計算: 目標極周波数を固定し、$\alpha_k = e^{-2\pi f_k / f_s}$ で任意の $f_s$ に対応する
- IFFT 法: 周波数領域で直接スペクトルを構成し、$f_s$ 依存性を完全に回避する(次節で解説)
3.6 IFFT 法 — サンプリング周波数非依存の生成
IIR フィルタのサンプリング周波数依存性を完全に回避する方法として、 周波数領域でスペクトルを直接構成し、逆 FFT する手法がある。
原理
パワースペクトル密度 $S(f) \propto 1/f$ を持つ信号の振幅スペクトルは $|X(f)| \propto 1/\sqrt{f}$ である。 ここに一様ランダムな位相 $\theta_k \in [0, 2\pi)$ を与え、逆 FFT すると 理想的なピンクノイズが得られる:
$$X[k] = \begin{cases} 0 & (k = 0) \\[4pt] \dfrac{1}{\sqrt{k}} \cdot e^{j\theta_k} & (k = 1, 2, \ldots, N/2 - 1) \\[4pt] \dfrac{1}{\sqrt{N/2}} & (k = N/2,\; \text{Nyquist}) \\[4pt] X^*[N-k] & (k = N/2+1, \ldots, N-1,\; \text{共役対称}) \end{cases}$$ $$x[n] = \text{IFFT}\{X[k]\}$$共役対称の意味: $X[N-k] = X^*[k]$ を設定することで、逆 FFT の出力 $x[n]$ が実数となる。 DC ($k=0$) は 0 に設定し(ピンクノイズは直流成分を持たない)、 Nyquist ($k = N/2$) は実数とする。
周期性と必要な長さ
IFFT で生成された信号は周期 $N$ の周期信号であるため、 ループ再生しても接続点で不連続が生じない。 ただし人間の聴覚は雑音の繰り返しに対して意外と敏感であり、 周期が短いと周期性を知覚する可能性がある。
| $N$ | 周期 | メモリ(float) | 周期性の知覚 |
|---|---|---|---|
| $2^{17}$ | $\approx 3.0\;\text{sec}$ | 0.5 MB | 気づく人がいる |
| $2^{19}$ | $\approx 11.9\;\text{sec}$ | 2 MB | ほぼ気づかない |
| $2^{20}$ | $\approx 23.8\;\text{sec}$ | 4 MB | 安全 |
$N = 2^{20}$(約24秒)で 4 MB — 現代のシステムでは問題にならないサイズである。
IIR フィルタ法との比較
| 項目 | Kellet IIR フィルタ | IFFT 法 |
|---|---|---|
| スペクトル精度 | 近似($\pm 0.1$ dB @44.1kHz) | 厳密($-3$ dB/oct) |
| $f_s$ 依存性 | あり(係数が $f_s$ 固定) | なし |
| メモリ使用量 | $O(1)$(状態変数7個) | $O(N)$(バッファ全体) |
| 初期化コスト | なし | $O(N \log N)$(FFT 1回) |
| サンプルあたりのコスト | 乗算14回 + 加算8回 | テーブル参照1回 |
| 非周期性 | 非周期(毎サンプル新たな乱数を入力) | 周期的($N$ サンプルで繰り返す) |
| リアルタイム適性 | 高い | 高い(テーブル参照のみ) |
C++ 実装例(IFFT 法)
// IFFT 法によるピンクノイズバッファ生成
const int N = 1 << 20; // 2^20 ≈ 24秒 @44.1kHz
std::vector<std::complex<double>> spectrum(N);
std::mt19937 rng(42); // シード固定で再現性確保
std::uniform_real_distribution<double> dist(0.0, 2.0 * M_PI);
// DC = 0
spectrum[0] = 0.0;
// 正の周波数: 振幅 1/√k, ランダム位相
for (int k = 1; k < N / 2; ++k) {
double amp = 1.0 / std::sqrt((double)k);
double phase = dist(rng);
spectrum[k] = std::polar(amp, phase);
}
// Nyquist (実数)
spectrum[N / 2] = 1.0 / std::sqrt((double)(N / 2));
// 共役対称 → 実数出力を保証
for (int k = 1; k < N / 2; ++k)
spectrum[N - k] = std::conj(spectrum[k]);
// 逆 FFT → 時間領域信号
std::vector<double> buffer(N);
ifft(spectrum.data(), buffer.data(), N);
// ピーク正規化
double peak = *std::max_element(buffer.begin(), buffer.end(),
[](double a, double b){ return std::abs(a) < std::abs(b); });
double norm = 1.0 / std::abs(peak);
for (auto& s : buffer) s *= norm;
// 使用時: buffer[n % N] でループ再生
FFT ライブラリ:
上記の ifft() は標準ライブラリには含まれない。
実装には FFTW、
KissFFT、
または各フレームワーク付属の FFT(JUCE の juce::dsp::FFT など)を使用する。
任意の色ノイズへの拡張
IFFT 法の大きな利点は、振幅スペクトルを $|X[k]| \propto 1/k^{\alpha/2}$ とするだけで 任意の $\alpha$ を持つ色付きノイズを同一の手法で生成できることである。 ピンク ($\alpha = 1$)、ブラウン ($\alpha = 2$)、ブルー ($\alpha = -1$)、 バイオレット ($\alpha = -2$) のいずれも統一的に扱える。
4. ブラウンノイズ($1/f^2$ ノイズ)
ブラウンノイズ(ブラウニアンノイズ、レッドノイズとも呼ばれる)は、 ホワイトノイズの累積和(ランダムウォーク)として生成される。 ロバート・ブラウンのブラウン運動に由来する。
- 生成: $x[n] = x[n-1] + w[n]$($w[n]$: ホワイトノイズ)
- パワースペクトル密度: $S(f) \propto 1/f^2$($-6$ dB/oct)
- 用途: 地震波モデリング、リラクゼーション音源
IFFT 法で生成する場合は、振幅スペクトルを $|X[k]| \propto 1/k$ に設定すればよい (パワースペクトル密度が $1/k^2$ に対応する)。
5. 疑似乱数生成器
ディジタルノイズの品質は疑似乱数生成器(PRNG)の性能に依存する。 高品質な PRNG はノイズ生成の基盤となる。
| アルゴリズム | 周期 | 特徴 |
|---|---|---|
| メルセンヌ・ツイスタ (MT19937) | $2^{19937}-1$ | 長周期、623次元均等分布 |
| xoshiro256** | $2^{256}-1$ | 高速、良好な統計特性 |
| 線形合同法 (LCG) | $2^{32}$ 程度 | 単純高速、品質は低い |
| LFSR | $2^n - 1$ | ハードウェア実装向き |
実装上の注意:
C 標準ライブラリの rand() は LCG ベースでスレッドセーフでなく、
品質も低い。オーディオ用途では std::mt19937 や
JUCE の juce::Random を推奨する。
6. 応用
- 音響測定 — ピンクノイズによるスピーカー・ルームの周波数応答測定
- ディザリング — 量子化歪みの分散にブルーノイズやホワイトノイズを使用
- シミュレーション — モンテカルロ法における確率的モデリング
- 通信 — チャネルノイズのシミュレーション(AWGN チャネル)
- 音楽・サウンドデザイン — シンセサイザーの音源としてのノイズ波形
- インパルス応答測定 — TSP(時間引き伸ばしパルス)と組み合わせた室内音響計測
7. 参考資料
- Paul Kellet, "Pink noise filter" — musicdsp.org(Kellet フィルタの原典)
- Phil Burke, "DSP Generation of Pink Noise" — firstpr.com.au(各手法の包括的解説)
- "1st and 2nd order pink noise filters" — musicdsp.org
- Colors of noise — Wikipedia
- Pink noise — Wikipedia
- White noise — Wikipedia
- Brownian noise — Wikipedia
- Box–Muller transform — Wikipedia