I was really excited to see iOS 6 supports the Web Audio API, since we make HTML5 games. However, I cannot get iOS 6 to play any sound at all using the Web Audio API with examples that work fine in desktop Chrome.
Here is a HTML5 game with touch controls and playing audio via the Web Audio API (if present - if not it will fall back to HTML5 audio):
http://www.scirra.com/labs/sbios6b/
Edit: @Srikumar suggested some workarounds. I applied them at the version below. It still does not work!
http://www.scirra.com/labs/sbios6f/
Everything plays just fine on desktop Chrome, but iOS 6 emits no sound at all. I'm having trouble debugging it because I only do Windows development, and iOS 6 replaced the debug mode with remote web inspector, which apparently is not available on Safari for Windows. Using a few alerts I did find it correctly identifies the Web Audio API, uses it, detects no Vorbis support so falls back to AAC audio, decodes a buffer and then plays it, and no errors are thrown, but I hear nothing. And, of course, I tried turning the volume up to max :)
There should not be a codec problem, because iOS 6 can play AAC just fine - you can browse to one of the .m4a's the game plays and it plays fine visited direct from Safari.
Looking at the Web Audio API examples here on iOS 6: http://chromium.googlecode.com/svn/trunk/samples/audio/samples.html - some of them work, and others don't. For example, the Chrome Audio Visualizer works, but Javascript Drone doesn't.
There must be some subtle incompatibility between Web Audio on iOS 6 and desktop Chrome. What am I missing?
Edit (November 2015): iOS 9 no longer allows audio to start in a touchstart
event, which breaks the solution below. However it works in a touchend
event. The original answer for iOS 6 is left intact below, but for iOS 9 support make sure you use touchend
.
Well, sorry to answer my own bounty question, but after hours of debugging I finally found the answer. Safari on iOS 6 effectively starts with the Web Audio API muted. It will not unmute until you attempt to play a sound in a user input event (create a buffer source, connect it to destination, and call noteOn()
). After this, it unmutes and audio plays unrestricted and as it ought to. This is an undocumented aspect of how the Web Audio API works on iOS 6 (Apple's doc is here, hopefully they update it with a mention of this soon!)
The user can be touching the screen a lot, engaged in the game. But it will remain muted. You have to play inside a user input event like touchstart
[edit: touchend
for iOS 9+], once, then all audio unmutes. After that you can play audio at any time (doesn't have to be in a user input event).
Note this is different to the restrictions on HTML5 audio: typically you can only start audio at all in a user input event, and only play one sound at a time; the Web Audio API fully unmutes after the first play-in-user-input, so that you can play sounds at any time, and then you can mix them polyphonically, process cool effects, etc.
This means many games already on the web using the Web Audio API will never play audio, because they do not happen to issue a noteOn in a touch event. You have to adjust it to wait for the first user input event.
There are a few ways to work around this: don't play your title music until the user touches the screen; have an initial 'touch to enable audio' screen and play a sound then begin the game when they touch; etc. Hopefully this will help anyone else having the same problem save some time trying to debug it!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With