Web Audio Library XSound 2.4.0 / 2.4.1 Released

1. Overview

久々の Web Audio API ネタです. XSound 2.4.0 からノイズの生成に対応しました. 2.4.0 ではホワイトノイズ (白色雑音), 2.4.1 ではピンクノイズの生成が可能になりました.

2. What is Noise ?

そもそもノイズ (雑音) とは何か ? から解説します. 世の中に存在する音のほとんどは周期的な波形をしており, 基本周波数をもつ sin 波とその整数倍の周波数をもつ sin 波 (倍音) の合成によって構成されます (それを周波数視点で分解するのがフーリエ変換です). しかしながら, 非周期的な波形をもつ音も存在しており, その典型例がノイズと呼ばれる音になります. ノイズにはいくつか種類がありますが, 有名でよく利用されるホワイトノイズとピンクノイズの特徴と, それを Web Audio API で生成するための実装を紹介します.

3. White Noise

ホワイトノイズ (白色雑音) の命名の由来は, そのスペクトルが白色のスペクトルと同じ (どの帯域でも同じ振幅をとる) であることから名づけられました. ホワイトノイズの実装はとても簡単です. なぜなら, 乱数を生成するだけだからです (ただし, 振幅が -1 〜 1 に収まるように値を調整する必要はあります). JavaScript の Math.random メソッドは 0 以上 1 未満の値を返すので, -0.5 したあと, 2 倍にすることで, -1 〜 1 の値に収まるようにしています.

// processor は ScriptProcessorNode のインスタンス
processor.onaudioprocess = event => {
    const outputLs = event.outputBuffer.getChannelData(0);
    const outputRs = event.outputBuffer.getChannelData(1);

    // bufferSize は ScriptProcessorNode のバッファサイズ
    for (let i = 0; i < bufferSize; i++) {
        outputLs[i] = 2 * (Math.random() - 0.5);
        outputRs[i] = 2 * (Math.random() - 0.5);
    }
}

4. Pink Noise

ピンクノイズの命名の由来は, そのスペクトルがピンク色のスペクトルと同じ (高周波数ほど振幅が減衰する) であることから名づけられました. ピンクノイズの実装は少し複雑 (すみませんが, 私も完全に理解できていません …) なので, 実装のみを紹介します.

// processor は ScriptProcessorNode のインスタンス
processor.onaudioprocess = event => {
    const outputLs = event.outputBuffer.getChannelData(0);
    const outputRs = event.outputBuffer.getChannelData(1);

    let b0 = 0;
    let b1 = 0;
    let b2 = 0;
    let b3 = 0;
    let b4 = 0;
    let b5 = 0;
    let b6 = 0;

    // bufferSize は ScriptProcessorNode のバッファサイズ
    for (let i = 0; i < bufferSize; i++) {
        const white = (Math.random() * 2) - 1;

        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);

        outputLs[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + (white * 0.5362);
        outputRs[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + (white * 0.5362);

        outputLs[i] *= 0.11;
        outputRs[i] *= 0.11;

        b6 = white * 0.115926;
    }
}

う〜ん … 原理がよくわかりません w. 実は, ホワイトノイズに適切な Low-Pass Filter をかけることでも生成できるので, 原理がわからないと使いたくない場合は, その実装でもいいかもしれません.

5. References