Web Audio APIの応用
モータ音シミュレータはWeb Audio APIにより、モータ音のシミュレートやシミュレートされたモータ音をスペクトログラム表示することを実現しています。この記事では、Web Audio APIのどの機能をモータ音シミュレータで使用しているかを説明します。
Web Audio APIとは
現代的なブラウザに実装されている、Web上で音声を扱うための仕組みです。残念ながらIEは非対応です。audio要素では不可能な、厳密な再生タイミング制御や幅広い範囲でのピッチ変更を行うことが可能になります。注意点として、Web Audio APIで波形データを取り扱うためには、メモリ上にデコードした生の波形データを保持しておく必要があるため、長時間の音声データの取扱いには不適です。
Web Audio APIでは、オーディオノードと呼ばれる部品を組み合わせることにより、音声再生機構を構築していきます。音声データの再生は、オーディオノードの出力をオーディオコンテキストのdestinationに接続することで実現されます。
モータ音の再現
モータ音シミュレータでの使用箇所
BVEでのモータ音の再現は、列車速度に応じて各モータ音や走行音のサンプリング音源を、ピッチと音量を変更しながら再生することにより実現されています。これと同様の再現機構をWeb Audio APIで実現するには、各々のサンプリング音源トラックに対し、サンプリング音源の波形データを出力し、再生速度の変更によるピッチ変化の機能も有するAudioBufferSourceNodeと、音量調節を司るGainNodeを用意します。それぞれのAudioBufferSourceNodeは、それと関連するGainNodeに接続されます。また、それぞれのGainNodeは、ある1つの出力先(オーディオコンテキストのdestinationなど)にまとめて接続されます。
AudioBufferSourceNodeのplaybackRate値の変更により、ピッチの調節が実現できます。また、GainNodeのgain値の変更により、音量調節が実現できます。そして、フレーム更新の度に各々のトラックに対してこの二つの値を変更していくことにより、モータ音のシミュレーションが実現されます。
AudioBufferSourceNodeは、startメソッドで再生を開始した後の任意のタイミングへのシークが不可能であり、またstopメソッドで再生を停止した後に再び再生を開始することもできない、という仕様があります。このため、トラックの無音が解除されたときに音源の頭出しが行われるという、BVEでのモータ音の再現仕様を再現するためには工夫が必要となります。モータ音シミュレータでは、トラックが無音になった時にAudioBufferSourceNodeのstopメソッドを呼び出し、無音解除時に都度AudioBufferSourceNodeを作り直すという実装になっています。
Online Drive Train Calcでの使用箇所
AudioBufferSourceNodeのかわりにOscillatorNodeを使用し、正弦波を発生させています。複数のOscillatorNodeを組み合わせて、モーター音シンセサイザーを構成しています。OscillatorNodeのfrequencyを変更すると、周波数を変更できます。
スペクトログラム
モータ音シミュレータなどに搭載しているスペクトログラムは、AnalyserNodeの機能により実現しています。
AnalyserNodeを音声波形データの流れの途中に挿入すると、そこを通過している波形データやそのフーリエ変換後の周波数データを任意のタイミングで取り出すことが可能になります。
スペクトログラム描画の肝となる周波数データは、AnalyserNodeのgetByteFrequencyDataメソッドより取得しています。このメソッドは、0から255の範囲内に正規化された周波数強度データを取得します。プロパティmaxDecibelsとminDecibelsより正規化の範囲を指定します。
類似のメソッドとしてgetFloatFrequencyDataメソッドがあり、こちらは周波数強度データをデシベル値で取得します。このメソッドを用いて取得したデータでスペクトログラムを描画するためには、JavaScriptサイドで正規化処理を行わなければならず、計算コストが高くなるため使用していません。
スペクトログラムの描画処理は、フレーム更新の度に周波数データを取得し、左に1ピクセル前フレームのスペクトログラム画像を動かした後、右端に取得した周波数データをその強度に応じた色に変換して描き込むものとなっています。そのため、一般的には秒速60ピクセルでスペクトログラムは移動していきます。
モーター音シミュレータでの実装において、各々のモータ音トラック出力をアナライザーとdestinationの二つに接続したところ、Chromeでは正常に動きませんでした。各々のモータ音トラック出力をアナライザーの入力に集約して接続し、アナライザーの出力をdestinationに接続すると動作しました。