Jump to content

iOS 9 webAudio issues


KyleNau
 Share

Recommended Posts

About 2 weeks ago I had to add code under iOS 8+ to trigger audio on an initial touch event In Safari and Chrome on a modern iPad Air.  Used this touch-test fiddle to see what was actually happening on touch events: http://jsfiddle.net/cpUsA/4/

 

Code worked just fine when reduced to just listening for touchstart on all touch devices (Android / iOS), but after upgrading to iOS9 even listening to 'touchEnd' no longer works for me. Using soundjs currently but, as mentioned above, even howler is affected.  Anyone else continuing to have issues, even with KyleNau's fix?

 

My event listener snippet:

var domElem = js.Browser.document;if ( domElem.addEventListener ){   // at first I didn't really know *where* in time the touch event is registered, so I   // just check 'em all.  there is a window of 300-500 ms to listen to.  -jimm 15.09   // looks like touchstart and click will do.  checking all of them slows   // the simulator down -jimm 16.09   // iOS 9 update:  nothing triggers audio now    -jimm 22.09   domElem.addEventListener( "touchstart", touch_me, false );   domElem.addEventListener( "touchend", touch_me, false );   domElem.addEventListener( "mousedown", touch_me, false );   domElem.addEventListener( "mouseup", touch_me, false );   domElem.addEventListener( "click", touch_me, false );} else {   domElem.attachEvent( "onclick", touch_me, false );}

!#$% Apple!

Link to comment
Share on other sites

This is terrible. iOS 9 appears to basically break all existing content using Web Audio. I found an existing WebKit bug for this and posted more information in it including test cases:

 

https://bugs.webkit.org/show_bug.cgi?id=149367

 

Please vote/comment on it to raise awareness!

 

I found a workaround (which will be integrated in to the next Construct 2 release). Unblocking the Web Audio API has typically been done in touchstart like this:

document.addEventListener("touchstart", function (){	if (had_touch)		return;		// play empty buffer to unmute audio	var buffer = context.createBuffer(1, 1, 22050);	var source = context.createBufferSource();	source.buffer = buffer;	source.connect(context.destination);	source.start(0);	had_touch = true;});

Now you need to do that in a touchend event instead, and it works again. However, all content ever published using this technique needs to be updated! Safari should definitely be fixed.

Link to comment
Share on other sites

Found this out recently. For all those GameMaker Studio users out there, I went ahead and submitted a bug report.

Add this code in your index.html - It belongs right before the script that runs your game.js file for a quick fix:

<!-- Run the game code --><script type="text/javascript">window.addEventListener("touchend", ios_unlock_sound, false);function ios_unlock_sound(event) {    var buffer = g_WebAudioContext.createBuffer(1, 1, 22050);    var source = g_WebAudioContext.createBufferSource();    source.buffer = buffer;    source.connect(g_WebAudioContext.destination);    source.noteOn(0);    window.removeEventListener("touchend", ios_unlock_sound, false);}</script>
Link to comment
Share on other sites

Has anyone tried the 'touchend' solution with swipes or long touches rather than quick taps? Here:

 


 

It's mentioned that the 'touchend' solution doesn't work in those cases. This is what I'm seeing as well.

 

My current solution is to listen for the source 'onended' event to determine when the silent 'unlock' sound has actually played, and to keep trying to unlock on 'touchend' until the audio is actually unlocked. I'm curious as to whether other people have run into the problem of 'touchend' not always working and what solutions people are using.

 

Does anyone have any suggestions on how to handle this in a reliable way?

Link to comment
Share on other sites

  • 2 weeks later...

The above workarounds mentioned above for Construct 2 and GameMaker Studio have made their way into the Howler.js library too.  From their docs on GitHub: "The default behavior of howler.js is to attempt to silently unlock audio playback by playing an empty buffer on the first touchend event." https://github.com/goldfire/howler.js/

 

Seems to work as advertised on various Android/iOS tablets I have at hand.  But do notice, under iOS 9.1 beta at least, that I still need to play an empty sound (in my case a 0.2 second silent mp3) *before* I play sounds elsewhere in the code just to trigger the touchend unblocking.  If I do not do this, on a second touch event both the first and second touch triggered sounds play together.  Afterwards it behaves as expected.  Cheap work around, but I can live with it for now.

Link to comment
Share on other sites

You can generate the silent sound dynamically rather than using an audio file

// create empty buffervar buffer = this.context.createBuffer(1, 1, 22050);var source = this.context.createBufferSource();source.buffer = buffer;// connect to output (your speakers)source.connect(this.context.destination);// play the soundif(source.play){    source.play(0);} else if(source.noteOn){    source.noteOn(0);}
Link to comment
Share on other sites

  • 2 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...