Web Audio APIを利用してオーディオビジュアライザを作成する ~その1 音声データを読み込んで音を出す~


Web Audio APIを利用してオーディオビジュアライザを制作したので、それに関する備忘録です。
まとめて書くと内容が長くなり、複雑で解りにくなりそうなので分けて書いています。

その1は簡単な概要と音声データを読み込んで音を出すところまでです。

# Web Audio APIとは

- Audioを扱うAPI。
- **AudioNode**を接続して、音(信号)に対して様々な操作ができる。

## AudioNodeとは
音量の調整、周波数の解析、フィルタをかけたりと音(信号)に対して様々な操作ができるノード。(モジュールのようなもの)
AudioNodeはいくつでも接続することができ、最終的には`AudioDestinationNode`(出力)に接続して音を出す。
現実世界で言うとマイク(入力)、エフェクタ(フィルタ)、スピーカー(出力)をコードで繋げていくのと同じ。

# とりあえず音を出す
[デモ](https://soarflat-prototype.github.io/web-audio/demo/index.html)**(ページを開くと音が流れるので音量注意)**

以下のノードを接続して音を出す。

#### OscillatorNode (入力)
指定した周波数、波形の音(音源)を生成するノード

#### GainNode (フィルタ)
音量を調整するノード

#### AudioDestinationNode (出力)
音の出力先(スピーカー)となるノード

## ディレクトリ構成

```lang:
.
├── index.html
└── audio.js
```

## index.html

```html:index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>とりあえず音を出す</title>
</head>
<body>
<script src="audio.js"></script>
</body>
</html>
```

## audio.js

```js:audio.js
// AudioNodeを管理するAudioContextの生成
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

var oscillatorNode = audioCtx.createOscillator();  // OscillatorNode(入力、音源)を作成
var gainNode = audioCtx.createGain();              // GainNode(フィルタ)を作成
gainNode.gain.value = 0.5;                         // 音量を小さくする
oscillatorNode.connect(gainNode);                  // oscillatorNodeをgainNodeに接続
gainNode.connect(audioCtx.destination);            // gainNodeをAudioDestinationNode(出力)に接続
oscillatorNode.start(0);                           // 再生開始
```

`GainNode`を介しているので、本来より音量が小さくなった音がでる。

#音声データを読み込んで音を出す
[デモ](https://soarflat-prototype.github.io/web-audio/demo2/index.html)**(ページを開くと音が流れるので音量注意)**

音声データを読み込み、以下のノードを接続して音を出す。

#### AudioBufferSourceNode (入力)
指定したバッファ(音声データ)を音源に設定するノード

#### AudioDestinationNode (出力)
音の出力先(スピーカー)となるノード

## ディレクトリ構成

```lang:
.
├── index.html
├── audio.js
└── sample.mp3
```

## index.html

```html:index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>音声データを読み込んで音を出す</title>
</head>
<body>
<script src="audio.js"></script>
</body>
</html>
```

## audio.js

`audio.js`は以下のような処理になる。

- [XMLHttpRequest](http://www.html5rocks.com/ja/tutorials/file/xhr2/)を利用して音声データ(バッファ)を読み込む。
- 読み込み完了後、取得したデータをデコードし、それを`AudioBufferSourceNode`で音源に設定する。
- `AudioBufferSourceNode`を`AudioDestinationNode`に接続し、再生する。

```js:audio.js
// AudioNodeを管理するAudioContextの生成
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

var Loader = function(url) {
  this.url = url;  // 読み込む音声データのURL
};

// XMLHttpRequestを利用して音声データ(バッファ)を読み込む。
Loader.prototype.loadBuffer = function() {
  var loader, request;
  loader = this;
  request = new XMLHttpRequest();
  request.open('GET', this.url, true);
  request.responseType = 'arraybuffer';

  request.onload = function() {
    // 取得したデータをデコードする。
    audioCtx.decodeAudioData(this.response, function(buffer) {
      if (!buffer) {
        console.log('error');
        return;
      }
      loader.playSound(buffer);  // デコードされたデータを再生する。
    }, function(error) {
      console.log('decodeAudioData error');
    });
  };

  request.onerror = function() {
    console.log('Loader: XHR error');
  };

  request.send();
};

// 読み込んだ音声データ(バッファ)を再生する。
Loader.prototype.playSound = function(buffer) {
  var sourceNode = audioCtx.createBufferSource(); // AudioBufferSourceNode(入力)を作成
  sourceNode.buffer = buffer;                     // 取得した音声データ(バッファ)を音源に設定
  sourceNode.connect(audioCtx.destination);       // AudioBufferSourceNodeをAudioDestinationNode(出力)に接続
  sourceNode.start(0);                            // 再生開始
};

var loader = new Loader('sample.mp3');
loader.loadBuffer();
```

# 終わり
[その2](http://qiita.com/soarflat/items/4aa001dac115a4af6dbe)では再生中の音から波形データを取得してcanvasに描画してみます。
理解が曖昧な気もするため、認識が間違っている場合、ご指摘ください。

# 関連

- [Web Audio APIを利用してオーディオビジュアライザを作成する ~その2 再生中の音から波形データを取得して描画する~](http://qiita.com/soarflat/items/4aa001dac115a4af6dbe)

# 参考
- [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)
- [Web Audio API - W3C](https://www.w3.org/TR/webaudio/)
- [Web Audio APIの基礎](http://www.html5rocks.com/ja/tutorials/webaudio/intro/)