周波数指定のホワイトノイズ

2018-09-15

WebAuidoの AudioContext.createScriptProcessor() というメソッドを使うと自分で好きに加工した波形を鳴らせるということで、試しにホワイトノイズを鳴らしてみた。

デモ

Frequency: Hz

ScriptProcessorNode

createScriptProcessorでScriptProcessorNodeが作成され、その onaudioprocess メソッドが時間経過とともに呼び出されるので、event.outputBuffer.getChannelData()で取得できるバッファにサンプルレートに従って鳴らす音圧データを書き込んでやれば鳴ってくれる:

// コンテキスト作成
const context = new AudioContext()

const BUFFER_SIZE = 4096
let node = context.createScriptProcessor(BUFFER_SIZE, 1, 1)
node.onaudioprocess = (e) => {
const output = e.outputBuffer.getChannelData(0)
const len = output.length
for (let i = 0; i < len; ++i)
output[i] = Math.random() * 2 - 1
}
node.connect(context.destination)

ホワイトノイズはすべての周波数ということで、毎サンプル(output[i])でランダムな値を生成してやればよい。

asm.jsアノテーション

ホワイトノイズでも周波数を制限してみようかと乱数の生成を毎回じゃなく指定の周波数に合うように何回かに1回にしてみると、まあ処理が重くなってしまいまともに音が鳴らない。 ifで分岐するからなのか毎回乱数を生成するより重くなってしまうというのが意外。

これじゃ使い物にならない…と思いつつ苦し紛れに計算式にasm.jsのアノテーション的に|0で整数ですよーと示してやると、処理落ちがなくなりきれいに鳴るようになった。 ちゃんとそういう最適化が図られているとは、JSエンジンすごい。 流石に今の時代でも数万回の計算は浮動小数点数だと辛いのだなぁ。