Web Audio API

Firefoxではスリープから復帰後、このAPIが機能しなくなることがあります。web audio api is disabled with Firefox after resume from sleep / Applications & Desktop Environments / Arch Linux Forums

オーディオデータの入力

オーディオデータは、以下の方法によって入力できます。

  • オーディオ ノードから音を発生 … OscillatorNode
  • PCMデータから音を生成 … AudioContextのdecodeAudioData()メソッド
  • HTMLメディア要素から取得 … videoaudio要素
  • MediaStreamから取得 … Webカメラやマイク

音を発生 (OscillatorNode)

OscillatorNodeでは、波形や周波数を指定して音を生成できます。OscillatorNode - Web APIs | MDN

波形
周波数
var audioCtx = new AudioContext;

var oscillator = audioCtx.createOscillator();
oscillator.connect( audioCtx.destination );

oscillator.type = 'sine';
oscillator.frequency.value = 3000;

var soundLength = 0.5;
oscillator.start();
oscillator.stop( audioCtx.currentTime + soundLength );

stop()メソッドにより再生を停止した場合、再び再生するにはOscillatorNodeオブジェクトを生成し直さねばなりません。それをせずstart()を呼び出すと「InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable」や「InvalidStateError: Failed to execute 'start' on 'OscillatorNode': cannot call start more than once.」として例外が発生します。

プロパティ

プロパティ  
frequency  
detune  
type
  • sine
  • square
  • sawtooth
  • triangle
  • custom
PropertiesSection - OscillatorNode - Web APIs | MDN

PCMデータから音を生成

ローカルからの読み込み

ユーザーのローカル ファイルから読み込む場合を考えます。

<input type="file" id="sample" accept="audio/*" />
var file = document.getElementById( 'sample' );
file.onchange = function()
{
    var reader = new FileReader();
    reader.onload = function()
    {
        var audioData = this.result;

        var audioCtx = new AudioContext;
        audioCtx.decodeAudioData(
            audioData,
            function( decodedData )
            {
                var source = audioCtx.createBufferSource();
                source.buffer = decodedData;
                source.connect( audioCtx.destination );
                source.start();
            },
            function( e )
            {
                alert( e.err );
            } );
    };
    reader.readAsArrayBuffer( this.files[ 0 ] );
}
AudioContext.decodeAudioData()
audioCtx.decodeAudioData(
    audioData,
    function( decodedData )
    {
        // ここでデコードされたデータを使用する
    },
    function( e )
    {
        // デコードでエラー発生
        console.log( e.err );
    } );

Promiseを使う場合には、これは次のように記述します。

audioCtx.decodeAudioData( audioData ).then(
    function( decodedData )
    {
        // ここでデコードされたデータを使用する
    } );
AudioContext.decodeAudioData() - Web APIs | MDN

オーディオデータのサイズが大きいと、処理完了までに相応の時間がかかります。

AudioBufferSourceNodeインターフェイス
プロパティ 内容
AudioBuffer buffer  
PropertiesSection - AudioBufferSourceNode - Web APIs | MDN
メソッド 機能
start() バッファ内のオーディオ データの再生を予定するか、即座に再生する
MethodsSection - AudioBufferSourceNode - Web APIs | MDN

サーバーからの読み込み

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.responseType = 'arraybuffer';
xmlHttpRequest.onload = function()
{
    var audioData = this.response;

    var audioCtx = new AudioContext;
    audioCtx.decodeAudioData(
        audioData,
        function( decodedData )
        {
            // 後はローカルと同様
        } );
}
xmlHttpRequest.open( 'GET', 'sample.mp3', true );
xmlHttpRequest.send();

HTMLメディア要素から取得

new Audio()とコンストラクタを呼び出すことで、audio要素を生成できます。

mySound = new Audio( [URLString] );
Constructor - HTMLAudioElement - Web API Interfaces | MDN
var audio = new Audio( 'sample.mp3' );
audio.controls = true;

document.body.appendChild( audio );

var audioCtx = new AudioContext;
var source = audioCtx.createMediaElementSource( audio );

非対応ブラウザへの対応

audio要素に非対応のブラウザでmp3を再生するには、audio.jsが有効です。ただしこれはFlashでこの要素をエミュレートするため、それにすら対応しない場合には機能しません。

お使いのブラウザでのサポート状況
プロパティ、メソッド データ型 利用の可否

MediaError

audio要素で発生したエラーは、errorイベントで捕捉できます。そしてその原因は、HTMLMediaElement.errorからMediaErrorで取得できます。

codeの値
定数  
1 MediaError.MEDIA_ERR_ABORTED  
2 MediaError.MEDIA_ERR_NETWORK  
3 MediaError.MEDIA_ERR_DECODE  
4 MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED 指定されたメディア リソースを、使用できなかった
5 MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED 暗号化されたメディア ストリームを、再生できなかった
code property (Internet Explorer) | MSDN

オーディオの制御 (HTMLAudioElement)

 
時間 0:00/0:00
音量 ?

プロパティ

プロパティ 内容
audioTracks AudioTrackオブジェクトの目録であるAudioTrackListオブジェクト
autoplay trueならば、自動再生する
buffered  
controller  
controls  
crossOrigin  
currentSrc  
currentTime 再生中の位置を表す、倍精度の秒数。これに設定すると新しい位置にシークされる
defaultMuted 既定でミュート状態ならば、true
defaultPlaybackRate 既定の再生速度
disableRemotePlayback  
duration メディアの長さを表す秒数。有効なメディアがなければ0
ended  
error  
loop  
mediaGroup  
mediaKeys  
muted ミュート状態ならば、true
networkState  
paused 一時停止しているならば、true
playbackRate 再生速度
played ブラウザが再生したメディア ソースの範囲を含むTimeRangesオブジェクトがあるならば、それを返す
preload  
readyState  
seekable ユーザーがシークできる時間範囲を含むTimeRangesオブジェクトがあるならば、それを返す
seeking シーク中ならば、true
sinkId  
src メディアリソースのURL。src属性の値を反映
srcObject  
textTracks  
videoTracks  
volume メディアが再生されるときの音量。0.0から1.0の間の数値を取る。
Properties - HTMLMediaElement - Web APIs | MDN

メソッド

メソッド 機能
addTextTrack( kind, label, language )  
canPlayType( tytpe )  
fastSeek( time ) 指定秒数にシークする。currentTimeプロパティでも代用可能
load()  
pause() 一時停止させる
play()  
Methods - HTMLMediaElement - Web APIs | MDN 4.8.10 Media elements

イベント

イベント イベントの発生状況
loadstart メディアの読み込みが開始されたとき
loadeddata 最初のフレームが読み込まれたとき
canplay 再生可能となる、少なくとも2フレームのデータが用意できたとき
canplaythrough メディア全体を中断なく再生可能となるデータの用意ができたとき
durationchange メディアの長さを表すメタデータが読み込まれたとき
loadedmetadata すべてのメタデータが読み込まれたとき
stalled メディア データを取得できなかったとき
progress メディアのダウンロード時に周期的に呼ばれる
play play()またはautoplayにより一時停止状態ではなくなったとき
playing 再生を開始するのに十分なデータがあるとき
pause  一時停止したとき
ended 再生が完了したとき
waiting シークなどによって要求された操作が待たされるとき
emptied メディアが空となったとき。たとえばメディアがすでに読み込まれている状態で、それを再読み込みするためにload()メソッドを呼んだ場合
seeking シークが開始されたとき
seeked シークが完了したとき
timeupdate currentTime属性が変更され、時間が表示されるとき
volumechange 音量またはミュートの状態が変更されたとき
ratechange 再生速度が変更されたとき
suspend メディアの読み込みが一時停止したとき
error エラーが発生したとき
interruptbegin Firefox OSにおいて、割り込みによって再生が停止するとき
interruptend Firefox OSにおいて、割り込みによって停止した再生が再開するとき
Media events - Developer guides | MDN
イベントハンドラ  
onencrypted  
onwaitingforkey  
Event handlers - HTMLMediaElement - Web APIs | MDN

オーディオデータの視覚化

再生中のデータを視覚化するならばAnalyserNodeで、再生前のデータならばAudioBufferを用います。

AnalyserNode

出力されているストリームの情報を取得できます。AnalyserNode - Web APIs | MDN

つづりはAnalyzerではなく、Analyserです。

var audioCtx = new AudioContext;

var analyser = audioCtx.createAnalyser();
analyser.connect( audioCtx.destination ); // Analyserをデバイスに接続
analyser.fftSize = 2048;

var oscillator = audioCtx.createOscillator();
oscillator.connect( analyser ); // OscillatorをAnalyserに接続
oscillator.type = 'sine';
oscillator.frequency.value = 3000;

oscillator.start(); // 再生を開始
window.setTimeout( function()
    {
        var dataArray = new Uint8Array( analyser.frequencyBinCount );
        analyser.getByteTimeDomainData( dataArray ); // 現在の波形データを配列へコピー

        // dataArrayの情報をグラフに描画

        oscillator.stop(); // 再生を停止
    }, 100 );

AudioBuffer

AudioContext.decodeAudioData()のコールバックに渡されるAudioBufferオブジェクトから、波形データを取得できます。AudioBuffer - Web APIs | MDN

audioCtx.decodeAudioData(
    audioData,
    function( decodedData )
    {
        var pcmData = decodedData.getChannelData( 0 );

        // pcmDataの情報をグラフに描画
    } );
JavaScriptのドキュメントから検索