なんてこった、FirefoxのWebAudioAPIのオシレータ、サイン波以外だとDC除去フィルターがかかってる?LFO波形がちゃんと出ない...まあ、この辺いい始めるときりがないんだけど。
— g200kg (@g200kg) 2014, 11月 24
こういうツイートを見かけたので、波形ごとに 1Hz, 10Hz 441Hz, 882Hz それぞれの周波数で1周期分キャプチャしてみた。
WebKitのオシレーターの波形
Firefoxのオシレーターの波形
たしかに全然違う。
なぜ違うかというと波形を生成するアルゴリズムが違うからで、
- WebKit -> PeriodicWave (周波数情報のテーブルから生成)
- Firefox -> BLIT (bandlimited impulse train)
という方法で生成されている。どちらもエイリアスノイズがでない方法で、ゆえに Web Audio API のオシレーターは音が良いと言われるのだけど、LFOみたいに波形をコントロールする用途だと波形が異なると困ることがある。(それ以前にFirefoxの低周波域は全然仕事していない..)ちなみに SuperCollider だとノコギリ波を出すにも音響ソース用途の Saw と LFO用途の LFSaw みたいに2種類用意されている。
[追記 2015/02/20 16:30]
以下、いろいろ書いたけど全体的に雑いのでなし。
Firefox は 37 で WebKit と同じ方式になります。
1. カスタム波形を使う
http://the.mohayonao.com/web-audio-api/periodic-wave/
各波形を生成するアルゴリズム
https://github.com/mohayonao/the.mohayonao.com/blob/master/public/web-audio-api/periodic-wave/periodic-wave.js
Triangleの開始位相位置がおかしい気がしますが、それ以外はだいたいいけそう。ただし、LFO用途として考えると綺麗な波形とは言えません。
[追記 2014/12/15 17:00]
Firefox 34.0 時点では PeriodicWave にバグがあるっぽくてちゃんと動かないです。
→ 検証ページ
2. BufferSourceNodeを使う
サンプリングレートと同じサイズの AudioBuffer を作って、そこに波形を書き込んで利用すると、BufferSourceNode の playbackRate を周波数代わりに使えます。ただし、この方法には WebKit の playbackRate に AudioNode を接続しても反映されないという問題があって、LFOをLFOでモジュレーションするみたいなことができません。
3. 用途に応じてバリバリ書く
上記の方法で解決しなさそうな場合は頑張って書くしかなさそう。音作りのために試行錯誤するたびにバリバリ書き直すので辛いことになると思う。
- 上記よりも小さい BufferSourceNode を使う
- LFOのLFOを考慮した BufferSourceNode を使ってどうにかする
- AudioParam の setValueCurveAtTime を使ってどうにかする
- ScriptProcessorNode を使ってどうにかする