WebKit Audio distorts on iOS 6 (iPhone 5) first time after power cycling

拟墨画扇 提交于 2019-11-28 20:49:37

I have been having similar problems, even on iOS 9.2.

Even without a <video> tag, playback is distorted when first playing audio on the page after cold boot. After a reload, it works fine.

The initial AudioContext seems to default to 48 kHz, which is where distortion is happening (even with our audio at 48 kHz sample rate). When playback is working properly, the AudioContext has a sample rate of 44.1 kHz.

I did find a workaround: it is possible to re-create the AudioContext after playing an initial sound. The newly-created AudioContext seems to have the correct sample rate. To do this:

// inside the click/touch handler
var playInitSound = function playInitSound() {
    var source = context.createBufferSource();
    source.buffer = context.createBuffer(1, 1, 48000);
    source.connect(context.destination);
    if (source.start) {
        source.start(0);
    } else {
        source.noteOn(0);
    }
};

playInit();
if (context.sampleRate === 48000) {
    context = new AudioContext();
    playInit();
}

I found a related bug with HTML5 video and think I discovered the root of the problem.
I noticed that if you play a video using a <video> tag, it sets the context.sampleRate value to whatever the video's audio was encoded at. It seems as if iOS Safari has one global sampleRate that it uses for everything. To see this, try the following:

// Play a video with audio encoded at 44100 Hz
video.play();

// This will console log 44100
var ctx = new webkitAudioContext();
console.log(ctx.sampleRate);

// Play a video with audio encoded at 48000 Hz
video2.play();

// This will console log 48000
var ctx = new webkitAudioContext();
console.log(ctx.sampleRate);

This global sample rate appears to persist across page loads and is shared between tabs and browser instances. So, playing a youtube video in another tab could break all your decoded audio.

The audio becomes distorted when it is decoded at one sample rate and played at another one.

  1. Decode audio and store the buffer
  2. Do something to change the sample rate, such as playing a video or audio file
  3. Play buffer (distorted)

I don't know why it's happening after a cold start. If I had to guess, it's that Safari doesn't initialize this global sample rate until you try to use it.

The problem is still there on iOS 7, so I don't think a fix is coming anytime soon. We're stuck with hacks in the mean time like checking for a changed sample rate.

An npm package is online to fix this:

https://github.com/Jam3/ios-safe-audio-context

npm install ios-safe-audio-context
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!