LoginSignup
15
17

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-04-02

WebAudio API で音が歪む

歪んだり歪まなかったりするしよくわかんねー!
ってなってましたが、なんか回避できたので、書いておきます。

再現方法

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

ちなみに、Safariで音を再生するには、touchend等のユーザアクションで音を再生しないといけません。(一回再生すれば、そのAudioContextでは再生できるようになる)
あと、なぜか、iOS9からtouchstartがユーザアクションとして判定されなくなりました。

音の再生サンプル

回避の方法

一回音を再生してから、サンプルレートが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);

};


参考

15
17
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
15
17