JavaScript
HTML5
WebAudioAPI

[WebAudio API] iOS9で音が歪む、遅い、低い、割れる等の回避方法

More than 1 year has passed since last update.


WebAudio API で音が歪む

歪んだり歪まなかったりするしよくわかんねー!

ってなってましたが、なんか回避できたので、書いておきます。


再現方法

iOS 9.2.1 iPhone6 Plus

イヤホンを挿してない状態で SafariでWebAudioの再生してるページを開いて、Safariを再起動します。

ちなみに、Safariで音を再生するには、touchend等のユーザアクションで音を再生しないといけません。(一回再生すれば、そのAudioContextでは再生できるようになる)

あと、なぜか、iOS9からtouchstartがユーザアクションとして判定されなくなりました。


音の再生サンプル

http://goo.gl/UEpbeP


回避の方法

一回音を再生してから、サンプルレートが44100じゃない時に、AudioContextを再度生成することで回避できます。


サンプル

http://goo.gl/jWZDwD

dirtyという関数内で回避しています。


バグ回避のメインのコード

function playDummy(){
var source = createBufferSource();
source.buffer = context.createBuffer(1,1,context.sampleRate);
source.connect(context.destination);
source.start(0);
}

function checkSampleRateBug(){
if(context.sampleRate !== 44100){
context.close();
context = getAudioContextInstance();
return true;
}
return false;
}

function dirty(){
playDummy();
if(checkSampleRateBug())playDummy();
}

body.addEventListener('touchend',dirty);
body.addEventListener('mouseup',dirty);


コード全体

function getAudioContextInstance(){
try{
return new (
window.AudioContext ||
window.webkitAudioContext ||
window.mozAudioContext
)();
}catch(e){
console.error(e);
return null;
}
}

onload = function(){
var body = document.body;
var context = getAudioContextInstance();

if(context === null){
alert('WebAudio 未対応です');
return;
}

var sampleRate = 44100;
// 半音上下
var rate = Math.pow(2.0, 1.0/12.0);
var temp = rate;
var rates = [
rate,
temp*=rate*rate,
temp*=rate*rate,
temp*=rate,
temp*=rate*rate,
temp*=rate*rate,
temp*=rate*rate,
temp*=rate,
];

function playDoremifasorasido(){
var source = createBufferSource();
source.buffer = context.createBuffer( 1, sampleRate*1, sampleRate);
var channel = source.buffer.getChannelData(0);

for( var i=0; i < channel.length; i++ ){
channel[i] = Math.sin(i/(sampleRate/440)*rate*rate*rate * Math.PI * rates[(i/(sampleRate/8)|0)%rates.length]);
}

source.connect(context.destination);
source.start(0);
}

function createBufferSource(){
var source = context.createBufferSource();
source.start = source.start || source.noteOn;
return source;
}

function playDummy(){
var source = createBufferSource();
source.buffer = context.createBuffer(1,1,context.sampleRate);
source.connect(context.destination);
source.start = source.start || source.noteOn;
source.start(0);
}

function checkSampleRateBug(){
if(context.sampleRate !== 44100){
context.close();
context = getAudioContextInstance();
return true;
}
return false;
}

function dirty(){
playDummy();
if(checkSampleRateBug())playDummy();
}

body.addEventListener('touchend',dirty);
body.addEventListener('mouseup',dirty);

body.addEventListener('touchend',playDoremifasorasido);
body.addEventListener('mouseup',playDoremifasorasido);

};


参考

http://stackoverflow.com/a/34501159