Web Audio APIについて(1)「音楽を取得して出力する」

最近、Device関連のHTML5 APIが盛り上がっています。
今回から何回かにわけてWeb Audio APIについて書いていこうかと思います。

頑張ると、このくらいスゴいコトもできてしまうWeb Audio API
最終的にHTML5 Advent Calendar向けにまとめますので、まとめて読みたい方は12/7までお待ちください。

とりあえずデモ

とりあえず、一番簡単な「音楽を取得して出力する」デモです。
下部のPlayボタンを押したあとに、startボタンを押すとSVG女子のテーマソングが流れます。(webkitのみ)

これはなに?

Web Audio APIで音楽を出力しています。基本的な流れは以下のようになります。

  1. URLにアクセスして音源(たとえばoggファイル)を取得する
  2. 取得した音源をAudioContextを用いてデコードし、AudioBufferNodeを生成する
  3. AudioContextからAudioBufferSourceNodeを生成し、AudioBufferNodeや再生オプションを設定する
  4. AudioDestinationNodeにAudioBufferSourceNodeを接続し、音楽を出力(nodeOn())する

以下、各工程についてざっくりと説明します。

1.URLにアクセスして音源(たとえばoggファイル)を取得する
  XMLHttpRequestを使用して音源を取得します。
  jQueryの$.ajax()はレスポンスのデータタイプ ArrayBuffer に対応していないので現状ではXHR一択です。

var request = new HttpXMLRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.send();

2.取得した音源をAudioContextを用いてデコードし、AudioBufferNodeを生成する
  requestのonLoadイベントで取得した音源をデコードします。
  デコードに用いるAudioContextはWeb Audio APIの肝の部分ですが、現状ではベンダープレフィックスが必要です。
  今回はWebkit向けの実装をしていますので、webkitAudioContextを使います。

//with vendor prefix
var context = new webkitAudioContext();
request.onload = function(){
    //decode
    context.decodeAudioData(request.response, function(buffer){
        //生成されたAudioBufferNodeを適当に処理する
        bufferList[0] = buffer;
        //do hogehoge
    });
}

3.AudioContextからAudioBufferSourceNodeを生成し、AudioBufferNodeや再生オプションを設定する
  音声出力の最小単位はAudioBufferSourceNodeとAudioDestinationNodeの接続です。
  AudioBufferSourceNodeはAudioContextから生成することができ、音源としてAudioBufferNodeを渡すことができます。
  また、その他の再生設定や音声を出力する命令もAudioBufferSourceNodeに対して行います。

var source = context.createBufferSource();
//音源
source.buffer = bufferList[0] //AudioBufferNode
//繰り返し再生する
source.loop = true;

  AudioBufferSourceNodeのその他のオプションについてはW3Cのページを参照してください。

4.AudioDestinationNodeにAudioBufferSourceNodeを接続し、音楽を出力(nodeOn())する
  音楽を出力するには最終的にAudioBufferSourceNodeをAudioDestinationNodeに接続し、出力命令をする必要があります。

//connect to AudioDestinationNode
source.connect(context.destination);
source.noteOn(0);

  これで音楽を出力することができます。
  また、AudioBufferSourceNodeでnoteOff()を実行することで音楽の出力を停止することができます。

  ちなみに、AudioBufferSourceNodeは使い捨てのため、noteOff()したあとに再度noteOn()しても音楽は出力されません。
  かならず新しいAudioBufferSourceNodeを生成する必要がありますので注意してください。

上のサンプルで使っているBufferLoaderクラスはHTML5 Rocksというサイトで公開*1されています。

今回はこれでお終いです。次回は音声を解析して周波数データをCanvasに描画するなどをしてみたいと思います。
ではまた!

*1:Apache 2.0 License