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?
The API appears to be broken on iOS 6.1, or at least, has a breaking change that means no sites currently work with it.
Okay I like AshleysBrain answer, it helped me to solve the problem. But I found a bit more general solution.
Before you had to initiate the play sound from a user event, now they force you to do it via a user input event, (sounds strange) What I did was just read a input field before I played the sound.
So
playSoundFile is whatever you use to create the buffer source.
Update: iOS still requires a user input to play sound (No sound on iOS 6 Web Audio API)
I was previously stuck with web audio on iOS web. And to make things worse, it needs to work on android and other desktop platform. This post is one of those posts that I read and found no immediate answers.
Until I found howler.js.
This is the solution for cross-platform web audio solution:
So, I think I've figured it out.
It's a issue of Apple requiring an user action before sound can be allowed to play. It turns out, at least for me, that you shouldn't create the audio context at all except when the user calls for it. It's not enough to create the context when the page loads and then use createGainNode or similar on an user action.
In your case I'd create the context when the user clicks the "Touch to begin" button.
I have come across the audio restrictions with HTML5 Audio on iOS and worked around the problem by:
1) Creating an Audio Element with a silent audio file and playing it initially with a touch event (e.g. 'begin game' button) and then immidietly pausing it.
2) Building a sound-switcher function which switches the Audio src and then plays the Audio element after a short timeout.
3) Calling the sound-switcher function on any events (doesn't need to be a touch event).
This works because the Audio Element is un-muted on first touch, with the silent audio file, and remains un-muted, so the source can be switched on-the-fly.
Edit (November 2015): iOS 9 no longer allows audio to start in a
touchstart
event, which breaks the solution below. However it works in atouchend
event. The original answer for iOS 6 is left intact below, but for iOS 9 support make sure you usetouchend
.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!