Web Audio APIを使ってオーディオビジュアライザを作る このエントリをはてなブックマークに登録

2014年10月20日

takurutakuru

HTML5のJavaScript APIにWebAudio APIというものがあります。
これは、mp3やwavなどの音声データを扱い、エフェクトをかけたり他の音声データと合成したりと、かなり高度なことができるAPIとなる予定です。

このWebAudio APIを利用して、ファイルフォームにセットした音声ファイルの再生と同時に周波数データを取得し、棒グラフに描画してみるサンプルを作ったので解説していきます。

サンプル

作ったものを下に表示しています。
2014年10月現在、IEではWebAudio APIに対応していないので動作しません。
mp3やwavファイルを選択すると、再生と同時に棒グラフが描画されます。

別タブで開く
http://kray.jp/projects/webaudio/index.html

HTML

index.htmlを用意しました。
ここには、ファイルのinput要素と、canvas要素があるだけです。

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Audio Visualizer</title>
    <script><!-- 下記のJavaScriptコード --></script>
  </head>
  <body>
    <input id="file" type="file"><br />
    <canvas id="visualizer" height="255"></canvas>
  </body>
</html>

JavaScript

index.htmlにある「下記のJavaScriptコード」という部分に入るコードです。
プラグインは何も使っていません。
2014年10月現在のSafariで動作させる場合はAudioContextのかわりにwebkitAudioContextを使用してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
window.onload = function(){
  var source, animationId;
  var audioContext = new AudioContext;
  var fileReader   = new FileReader;
 
  var analyser = audioContext.createAnalyser();
  analyser.fftSize = 128;
  analyser.connect(audioContext.destination);
 
  var canvas        = document.getElementById('visualizer');
  var canvasContext = canvas.getContext('2d');
  canvas.setAttribute('width', analyser.frequencyBinCount * 10);
 
  fileReader.onload = function(){
    audioContext.decodeAudioData(fileReader.result, function(buffer){
      if(source) {
        source.stop();
        cancelAnimationFrame(animationId);
      }
 
      source = audioContext.createBufferSource();
 
      source.buffer = buffer;
      source.connect(analyser);
      source.start(0);
 
      animationId = requestAnimationFrame(render);
    });
  };
 
  document.getElementById('file').addEventListener('change', function(e){
    fileReader.readAsArrayBuffer(e.target.files[0]);
  });
 
  render = function(){
    var spectrums = new Uint8Array(analyser.frequencyBinCount);
    analyser.getByteFrequencyData(spectrums);
 
    canvasContext.clearRect(0, 0, canvas.width, canvas.height);
    for(var i=0, len=spectrums.length; i<len; i++){
      canvasContext.fillRect(i*10, 0, 5, spectrums[i]);
    }
 
    animationId = requestAnimationFrame(render);
  };
};

JavaScript解説

順番に見ていきます。

変数宣言

2
3
4
  var source, animationId;
  var audioContext = new AudioContext;
  var fileReader   = new FileReader;

sourceは後ほどAudioBufferSourceNodeを格納します。
再生とリアルタイムに処理をするので、OfflineAudioContextではなくAudioContextを使います。
FileReaderはHTML5にあるFile APIの機能です。ローカルのファイルを読み取ることができます。

アナライザ設定

6
7
8
  var analyser = audioContext.createAnalyser();
  analyser.fftSize = 128;
  analyser.connect(audioContext.destination);

高速フーリエ変換の分割サイズであるfftSizeには2の累乗の数値のみ設定することができます。
これはデフォルト2048になっていますが、2048だと取得できるデータ量が多すぎてリアルタイム処理がやり難いので適度に減らしています。

canvas初期化

10
11
12
  var canvas        = document.getElementById('visualizer');
  var canvasContext = canvas.getContext('2d');
  canvas.setAttribute('width', analyser.frequencyBinCount * 10);

canvasの横幅を設定している部分で使っているfrequencyBinCountは、fftSizeの1/2の値が取得できます。

ローカルの音声ファイルを読み込んだ時の処理

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  fileReader.onload = function(){
    audioContext.decodeAudioData(fileReader.result, function(buffer){
      if(source) {
        source.stop();
        cancelAnimationFrame(animationId);
      }
 
      source = audioContext.createBufferSource();
 
      source.buffer = buffer;
      source.connect(analyser);
      source.start(0);
 
      animationId = requestAnimationFrame(render);
    });
  };

fileReaderでファイルの読み込みが終わった時のコールバックです。
読み込んだファイルは、そのままの状態ではWebAudio APIでは扱えないので、decodeAudioDataを使ってデコードしています。このメソッドは第3引数にデコードエラー時のコールバックを設定することも可能ですが、今回は省いています。
デコードしたデータをsourceにセットし、source.start(0)によって、0秒後に音声の再生を開始します。

音声ファイルを変更したときに、レンダリングと音声を止めておかないとまずいことになるので16行目で対応しています。

フォームからファイルの読み込み

31
32
33
  document.getElementById('file').addEventListener('change', function(e){
    fileReader.readAsArrayBuffer(e.target.files[0]);
  });

フォームにセットされたファイルをバイナリファイルとして読み込んでいるだけです。
読み込み後にfileReaderのonloadが発火します。

棒グラフの描画

35
36
37
38
39
40
41
42
43
44
45
  render = function(){
    var spectrums = new Uint8Array(analyser.frequencyBinCount);
    analyser.getByteFrequencyData(spectrums);
 
    canvasContext.clearRect(0, 0, canvas.width, canvas.height);
    for(var i=0, len=spectrums.length; i<len; i++){
      canvasContext.fillRect(i*10, 0, 5, spectrums[i]);
    }
 
    animationId = requestAnimationFrame(render);
  };

spectrumsの変更がないように思えますが、getByteFrequencyDataはspectrumsを直接書き換えています。
canvasへの描画は、spectrumsの値をそのまま棒グラフの長さとしているので単純です。

以上で周波数データを棒グラフで描画することができます。

おわりに

WebAudio API ではかなり高度な操作ができるので、ゲーム関係やサウンドビジュアル関係など、その道のコアな人たちにとっては夢の広がるAPIなのではないでしょうか。
W3Cのサンプルを見るだけでも夢が広がります。

クレイについてもっと知りたい方は…

  1. クレイの3つの強みを見てみる。
  2. WEBシステムのことなら何でもご相談ください。

「いいね!」で応援よろしくお願いします!

このエントリーに対するコメント

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


トラックバック
  1. Electron を試す 4 – 簡易音楽プレーヤー 2 | アカベコマイリ2016/02/21, 2:50 PM

    […] KRAY Inc Web Audio APIを使ってオーディオビジュアライザを作る […]

we use!!Ruby on RailsAmazon Web Services

このページの先頭へ