Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop forcing single-channel audio in ig.Music? #42

Open
Joncom opened this issue Jul 24, 2019 · 3 comments
Open

Stop forcing single-channel audio in ig.Music? #42

Joncom opened this issue Jul 24, 2019 · 3 comments

Comments

@Joncom
Copy link
Collaborator

Joncom commented Jul 24, 2019

Impact/lib/impact/sound.js

Lines 239 to 249 in 3b6d3b5

// Did we get a WebAudio Source? This is suboptimal; Music should be loaded
// as HTML5 Audio so it can be streamed
if( track instanceof ig.Sound.WebAudioSource ) {
// Since this error will likely occour at game start, we stop the game
// to not produce any more errors.
ig.system.stopRunLoop();
throw(
"Sound '"+path+"' loaded as Multichannel but used for Music. " +
"Set the multiChannel param to false when loading, e.g.: new ig.Sound(path, false)"
);
}

As the above snippet mentions, an advantage to using "HTML5 Audio" for music, is that it the audio can be streamed. And Impact enforces this preference by throwing an error.

However, I can think of at least one advantage to allowing "Web Audio" to be used...

Getting sounds to play at all in mobile browsers is a bit finicky:

To prevent annoying ads during mobile web browsing, all sounds are always disabled by default (on iOS Safari at least), until at least one sound has been played in the actual callback of a touchend event, which can only triggered by the user himself.

With "Web Audio", the solution is easy:

In the case of "Web Audio", playing a single sound in this callback will enable all other and future "Web Audio" playback. Playing one sound enables all the others.

However, with "HTML Audio", it's more cumbersome:

Each and every individual sound file must be played in this callback, to enable each one for future playback.

Here is the basic solution to get audio enabled on mobile browsers:

ig.system.canvas.addEventListener('touchend', function() {
    if( !ig.game.mobileAudioEnabled ) {
    
        // Playing a single "Web Audio" source will enable all others
        ig.game.silent.play();
        ig.game.silent.stop();

        // Each "HTML5 Audio" source much be enabled invididually
        for(var i=0; i<ig.game.tracks.length; i++) {
            ig.game.tracks[i].play();
            ig.game.tracks[i].stop();
        }

        ig.game.mobileAudioEnabled = true;
    }
}, false);

Although this works to enable all sounds, it has 2 issues:

  1. Brief laggy moment when sounds first enable (noticeable FPS jitter)
  2. The tracks in ig.game.tracks can be heard for a split second

If ig.Music were modified to allow tracks to be "Web Audio" instead of "HTML5 Audio", I think issues 1 and 2 would both be resolved.

ig.system.canvas.addEventListener('touchend', function() {
    if( !ig.game.mobileAudioEnabled ) {
        ig.game.silent.play();
        ig.game.silent.stop();
        ig.game.mobileAudioEnabled = true;
    }
}, false);

Just thinking out loud here... Maybe it would be an idea to allow both types of audio for music, so that if streaming is important, that works, and if streaming is not important but support for mobile audio is, that option works a bit nicer too.

Edit:

Hmm. I just noticed there's actually already some audio unlock logic in sound.js:

document.addEventListener('touchstart', this.boundWebAudioUnlock, false);
}
},
unlockWebAudio: function() {
document.removeEventListener('touchstart', this.boundWebAudioUnlock, false);
// create empty buffer
var buffer = this.audioContext.createBuffer(1, 1, 22050);
var source = this.audioContext.createBufferSource();
source.buffer = buffer;
source.connect(this.audioContext.destination);
source.start(0);
},

However, this logic does not work, which is why I came up with my own unlock logic in the first place.

But the follow patch fixes it:

diff --git a/lib/impact/sound.js b/lib/impact/sound.js
index 50d74be..afcc7a4 100644
--- a/lib/impact/sound.js
+++ b/lib/impact/sound.js
@@ -34,13 +34,13 @@ ig.SoundManager = ig.Class.extend({
                if( ig.Sound.enabled && ig.Sound.useWebAudio ) {
                        this.audioContext = new AudioContext();
                        this.boundWebAudioUnlock = this.unlockWebAudio.bind(this);
-                       document.addEventListener('touchstart', this.boundWebAudioUnlock, false);
+                       ig.system.canvas.addEventListener('touchstart', this.boundWebAudioUnlock, false);

                }
        },

        unlockWebAudio: function() {
-               document.removeEventListener('touchstart', this.boundWebAudioUnlock, false);
+               ig.system.canvas.removeEventListener('touchstart', this.boundWebAudioUnlock, false);

                // create empty buffer
                var buffer = this.audioContext.createBuffer(1, 1, 22050);

As far as I can tell though, Impact still has no "audio unlock" for HTML5 audio...

@swashvirus
Copy link

its 9days any new solution on this issue 😃
failed to execute 'play' on 'htmlmediaelement'

@Joncom
Copy link
Collaborator Author

Joncom commented Aug 3, 2019

Fixed the broken Web Audio unlocking: 1425a04

However, HTML5 Audio still does not get unlocked automatically, and still faces the problem of causing a moment of FPS lag and/or making audible nose for brief moment while unlocking, so not sure about how to fix that yet...

Thinking the best way forward might be to make Web Audio the default for music, with fallback/optional support for HTML5 for people who need the audio streaming feature...

@Joncom
Copy link
Collaborator Author

Joncom commented Aug 27, 2019

On a related note, I'm seeing an audio error at https://playbiolab.com/ before the game even starts.

Screen Shot 2019-08-27 at 11 40 44 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants