I am unable to play any audio through Web Audio API on iPad. This is using the latest version of iOS (since 9.3.2 - currently 9.3.3).
Here is a bare-bones test I have set up (code below). None of the tests work on iPad for me. No problems on iPhone or other compatible browsers.
The Apple documentation makes it clear that audio must be initiated from a user action for Web Audio API to work. They state:
Note: On iOS, the Web Audio API requires sounds to be triggered from an explicit user action, such as a tap. Calling noteOn() from an onload event will not play sound.
There are a number of threads online about problems with this, the latest being autumn 2015 with iOS 9.0 to 9.2:
- Thread from HTML 5 Game Devs (autumn 2015 problems)
- William Malone (autumn 2015 problems)
- Paul Bakaus (unlocking techniques)
- Adrian Holovaty (autumn 2015 problems)
They suggest firing audio from a touchstart event to unlock iOS audio (or touchend while there were issues at that time). I have tried all of the suggested techniques and can't get touchstart, touchend or click to work. The audio is always muted on iPad.
There is another test page here (from William Malone). None of those sounds play on three iPads tried. Finally this game uses Web Audio API (thanks Derek) and is also muted.
Any insights or feedback would be much appreciated!
Here is the test code:
<!DOCTYPE html>
<html>
<head>
<title>Web Audio API - iPad Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./jquery-2.2.3.min.js"></script>
<style>
section { padding:10px; margin:0 0 10px; background:DarkSeaGreen }
a { cursor:pointer; display:block; background: DarkSeaGreen; padding:10px; margin:0 0 3px }
</style>
</head>
<body>
<script>
var app = {};
$(document).ready(function() {
// Do we have Web Audio API?
try {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
audioContext = new AudioContext();
} catch (e) {
alert('Web Audio API is not supported in this browser');
}
$('#loadClick').on('click',function(){load('./ipad_test.mp3')});
$('#playTouchEnd').on('touchend',play);
$('#playTouchStart').on('touchstart',play);
$('#playClick').on('click',play);
$('#unlockTouchEnd').on('touchend',unlock);
$('#unlockTouchStart').on('touchstart',unlock);
$('#unlockClick').on('click',unlock);
});
function unlock() {
// play empty buffer to unmute audio
var buffer = audioContext.createBuffer(1, 1, 22050);
var source = audioContext.createBufferSource();
source.audioContext = buffer;
source.connect(audioContext.destination);
source.start(0);
$('#messages').append('<p>Unlocked.</p>');
}
function load(file) {
if(app.loaded) {
$('#messages').append('<p>Already loaded.</p>');
return;
}
var request = new XMLHttpRequest();
request.open ('GET', file, true);
request.responseType = 'arraybuffer';
request.onload = function () {
audioContext.decodeAudioData(
request.response,
function (buffer) {
app.buffer = buffer;
$('#messages').append('<p>Loaded.</p>');
app.loaded = 1;
},
function(){alert('Load error.');}
)
};
request.send();
}
function play() {
if(!app.loaded) {
$('#messages').append('<p>Please load before playing.</p>');
return;
}
var sourceNode = audioContext.createBufferSource();
sourceNode.buffer = app.buffer;
sourceNode.connect (audioContext.destination);
sourceNode.start(0);
$('#messages').append('<p>Playing.</p>');
}
</script>
<h1>Web Audio API Test</h1>
<p>Unlock should not be needed at all, but offers an alternative way to try and get the audio going. Load and then play should be all any compatible device needs. Refresh to start again.</p>
<a id="unlockTouchEnd">Unlock (touchend)</a>
<a id="unlockTouchStart">Unlock (touchstart)</a>
<a id="unlockClick">Unlock (click)</a>
<a id="loadClick" style="background:#c0c0c0">Load (click)</a>
<a id="playTouchEnd">Play Audio (touchend)</a>
<a id="playTouchStart">Play Audio (touchstart)</a>
<a id="playClick">Play Audio (click)</a>
<section id="messages"></section>
</body>
</html>