LoginSignup
27
23

More than 5 years have passed since last update.

Mobile Safari, Chrome for Android での Web Audio API 覚え書き

Last updated at Posted at 2014-10-31

調査環境

  • iOS 8.1 + iPhone 5
  • Chrome for Android 38.0 + Xperia A

iOS タッチ制約

  • 初回の start() はユーザのタッチ操作を起点とした実行コンテキストで実行する必要がある
    • AudioContext のインスタンスごとに制約がかかっている
  • 実行コンテキスト
    • setTimeout は大丈夫
    • decodeAudioData はアウト。コールバック中で初回の start() を呼び出しても再生されない。

タッチ制約にハマる例

element.addEventListener('click', function() {
    context.decodeAudioData(buffer, function(buffer) {
        var src = ctx.createBufferSource();
        src.buffer = buffer;
        src.connect(context.destination);
        // タッチ制約により動作しない
        src.start(context.currentTime);
    });
}, false);

回避方法

次のようなコードを仕込んでおくとタッチ制約を回避できる。

context.createBufferSource().start(0);

デコード時間

decodeAudioData の所要時間を計測(ms)

iOS

iOS 8.1 + iPhone 5

  • HE-AAC
    • 441, 446, 448
  • AAC
    • 250, 252, 251

Chrome for Android

  • HE-AAC
    • 1915, 1902, 1789, 2223, 2059,
  • AAC
    • 2507, 2914, 2698, 2878, 2967,

DataRate ごとのデコード時間(Chrome)

decodeAudioData のコストが高すぎる為、bitrate ごとの値を取ってみる。
HE-AAC でそれぞれ DataRate を変更し、計測した数値が以下。

  • 56kbit/s: 2102, 1941, 1852, 1984, 2088
  • 48kbit/s: 1772, 2043, 2048, 2005, 1983
  • 32kbit/s: 1806, 1960, 1891, 1922, 1784
  • 24kbit/s: 1658, 1829, 1860, 1805, 1739

createBuffer を使う(iOS)

Safari では ArrayBuffer からオーディオデータへの変換に decodeAudioData に代えて createBuffer が使える

createBuffer は何故か変換コストを要しないため iOS ではこちらの方が高速に動作する。
但し標準ではないのでいつ切られてもおかしくなく、decodeAudioData の方が安心して使える。

CPU 使用率

iOS での AAC、HE-AAC それぞれのデコード所要時間は次の通り(com.apple.WebKit の CPU Usage)

AAC で 21〜25%、
HE-AAC で 35〜40%

ファイル記録

デコード時間の計測に利用したファイルはそれぞれ次の通り

HE-AAC

    Data format:     2 ch,  16000 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame
    Channel layout: Stereo (L R)
    estimated duration: 35.587750 sec
    audio bytes: 251859
    audio packets: 559
    bit rate: 56319 bits per second
    packet size upper bound: 796
    maximum packet size: 796
    audio data file offset: 4096
    optimized
    audio 569404 valid frames + 2112 priming + 900 remainder = 572416
    source bit depth: I16
    format list:
    [ 0] format:      2 ch,  32000 Hz, 'aach' (0x00000000) 0 bits/channel, 0 bytes/packet, 2048 frames/packet, 0 bytes/frame
    Channel layout: Stereo (L R)
    [ 1] format:      2 ch,  16000 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame
    Channel layout: Stereo (L R)
    info dictionary:
        approximate duration in seconds          35.588

AAC

    Data format:     2 ch,  32000 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame
    Channel layout: Stereo (L R)
    estimated duration: 35.587750 sec
    audio bytes: 290577
    audio packets: 1115
    bit rate: 65151 bits per second
    packet size upper bound: 359
    maximum packet size: 359
    audio data file offset: 8192
    optimized
    audio 1138808 valid frames + 2112 priming + 840 remainder = 1141760
    source bit depth: I16
    format list:
    [ 0] format:      2 ch,  32000 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame
    Channel layout: Stereo (L R)
    info dictionary:
        approximate duration in seconds          35.588

Chrome for Android 一部端末での問題

やはり端末間の差違がある。
音質やノイズの有無も端末によってかなり変わるため注意が必要。

ノイズが混ざる(処理遅延が生じる)

L-01F 等の一部端末で Web Audio API の再生結果に特定条件下でノイズが混ざることがある。

描画レート(描画 FPS)が下がるとノイズが混ざり始め、レートを上げると再生結果が正常になるというもので、オーディオ処理が描画スレッドに巻き込まれているような動作を見せる。

次のようなコードを入れて無理矢理 FPS を稼ぐことで上記問題は回避できる。

<div id="fps-slowdown-make-sound-noisy"></div>

 

#fps-slowdown-make-sound-noisy {
  width:0px;height:0px;
  position: absolute;
  -webkit-animation-name: anim-void;
  -webkit-animation-duration: 1s;
  -webkit-animation-iteration-count: infinite;
}
@-webkit-keyframes anim-void {
  from { top: 0px; }
  to   { top: 1px; }
}

API が無い

NEON 命令に対応していない端末では Web Audio API 自体が無効化されている(生えていない)。

iOS 7.x で decodeAudioData がキャンセルされる

(iOS 8.x では未検証)

iOS 7.1 で decodeAudioData に処理が入った瞬間にスクリーンを長押しする(スクロールを繰り返す)と decoeAudioData の処理がキャンセルされることがある(エラーやコールバックの発火もなく、ただ処理が消滅する)。

27
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
23