I\'ve been struggling with an elusive audio distortion bug using webkitAudioContext in HTML5 under iOS 6. It can happen in other circumstances, but the only way I can get 1
An npm package is online to fix this:
https://github.com/Jam3/ios-safe-audio-context
npm install ios-safe-audio-context
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.
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.