phaserjs / phaser-ce

Phaser CE is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
http://phaser.io
MIT License
1.34k stars 491 forks source link

Phaser does not handle WebAudio interrupted state #667

Closed SBCGames closed 4 years ago

SBCGames commented 4 years ago

A bug in the API: all versions

Currently Phaser does not handle "interrupted" state of WebAudio context. At least on iOS it is easy to get into it - just interrupt running game with incoming call (I used Skype to simulate it on iPad). After return into game audio is not playing and debug.sound says, that Wab Audio is interrupted.

I found, that I can simply resume context like this in SoundManager.update():

    update: function () {
        :
        :

        if (this.usingWebAudio && !this._interruptHandlingOn && this.context.state === 'interrupted')
        {
            this._interruptHandlingOn = true;
            var self = this;
            this.context.resume().then(function() {
                self._interruptHandlingOn = false;
            });
        }

        :
        :

I do not know, whether context state is changed immediatley, so I am using _interruptHandlingOn variable as lock to prevent calling resume multiple times. Lock is reset on Promise .then(). As it works with Promise returned by context.resume(), it may be problem if Promise is not supported.

There is possibility to use context.onstatechange instead of Promise, it looks like this:

        if (this.usingWebAudio && !this._interruptHandlingOn && this.context.state === 'interrupted')
        {
            this._interruptHandlingOn = true;
            var self = this;

            this.context.onstatechange = function() {
                self._interruptHandlingOn = false;            
                self.context.onstatechange = null;            
            }

            this.context.resume();
        }
samme commented 4 years ago

I think I can just resume the audio context for every game "focus" event.

samme commented 4 years ago

I can also add a SoundManager#onStateChange signal, but I'm not sure it would be super useful by itself.

samme commented 4 years ago

Here is a try at automatic resume: phaser-test.js.zip

SBCGames commented 4 years ago

Yes, this seems to work. Audio is resumed when returning from incoming call. Thanks 🥇 !