0

Ok, my new website has just gone live, delivered through Google Apps. On a lark, I decided to include a javascript / HTML5 Lunar Lander clone (Martian Lander) which I wrote as an exercise a while back. The game works fine when I open it locally, but when it's delivered through GAE, the sounds don't seem to load on every system. In mobile safari, none of them load. In safari on the desktop, they all load reliably on my computer, but not on some other computers. In Chrome (on the desktop) it seems to work, but in Chrome in iOS, only one sound loads. On the desktop, it always seems to be the same sound which fails to load (explode1.mp3), which is the smallest of the sounds I'm loading. As you can see, if you click that link, the sound downloads fine from the server...

At first the problem seemed to be related to case sensitivity, so I switched the case in the filename, but that fix didn't keep working. This is a problem, as my loading bar is directly tied to how many resources have loaded, so it just sits there waiting for a GET request with no reply... Has anyone experienced anything like this, where a GET receives no reply on a specific resource, but loading the resource directly works fine?

I should say that I'm very new to most of these technologies, so it seems quite likely to me that I just made some novice mistake. Unfortunately, I'm not sure what those novice mistakes would be, seeing as I'm a novice!

Here's the code I use to load the sounds:

function loadSound(soundName) {
    var newElement = document.createElement("audio");
    newElement.addEventListener("canplaythrough", assetLoaded, false);
    document.body.appendChild(newElement);

    var audioType = supportedAudioFormat(newElement);
    if (audioType == "") {
        alert("no audio support");
        return;
    }
    newElement.setAttribute("src", "lander/sounds/" + soundName + "." + audioType);

    console.log("loading sound " + newElement.src + "...");

    return newElement;
}

and...

function assetLoaded() {
    var assetName = this.src;

    numAssetsLoaded++;

    console.log("loaded asset " + numAssetsLoaded + " (" + assetName + ")");

    if (numAssetsLoaded >= numAssetsToLoad) {
        shipSpriteSheet.removeEventListener("load", assetLoaded, false);
        pointImage.removeEventListener("load", assetLoaded, false);

        thrustAudioElement.removeEventListener("canplaythrough", assetLoaded, false);
        explosionAudioElement.removeEventListener("canplaythrough", assetLoaded, false);
        victoryAudioElement.removeEventListener("canplaythrough", assetLoaded, false);
        musicTrackElement.removeEventListener("canplaythrough", assetLoaded, false);

        gameState = GAME_STATE_INIT;
    }
}

If you take a look at the console output, you'll see that all of the sounds begin loading (particularly explode1.mp3) but don't necessarily finish and call assetLoaded...

UPDATE:
It seems to be the consensus is that I should not be using mp3 (incidentally, I'm already using mp3, AAC, AND ogg, but defaulting to mp3), and also that I should use the Web Audio API. These are both welcome pieces of input, and I will make the necessary changes. However, I still don't have an answer to the original question, which is, "Why does one particular sound not load reliably on desktop while the others load with no problem?" Anybody wanna take a crack at that one? Or is the answer going to be something like, "These things are highly unpredictable, and there's no way to fix it except by switching to a more dependable methodology, like Web Audio API"?

UDATE:
Here's an excerpt from my app.yaml file, which, I gather, helps GAE setup the server.

- url: /(.*\.(mp3|ogg|wav))
  static_files: \1
  upload: (.*\.(mp3|ogg|wav))
samson
  • 1,152
  • 11
  • 23
  • As to why none of the sounds work on mobile Safari, Apple doesn't allow audio to start playing automatically. See http://developer.apple.com/library/safari/#documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4 – Joshua Dwire Nov 10 '12 at 22:56
  • Yikes. How do HTML5 games usually handle this? This sound is FX, triggered by game state. I'm not going to expose a player window to the user just so I can load my sound effects... – samson Nov 10 '12 at 23:02
  • In any case, that doesn't address the behavior on Safari on other desktop machines, which is my main concern. – samson Nov 10 '12 at 23:02
  • Right it doesn't explain the desktop issues. The only workaround I've seen for mobile Safari is to make the user click a button first - *one for each audio element* - and then call the `load` function in the click handler. I've had to deal with that before, but I just found this: http://stackoverflow.com/a/13167871/1721527 – Joshua Dwire Nov 10 '12 at 23:16

2 Answers2

1

Some things to be aware of:

  • You shouldn't use MP3 for HTML5 games.
  • You will need to dual-encode all your sounds to both AAC (.m4a) and Ogg Vorbis (.ogg) to ensure they can be played everywhere, since there is no one format which can be played everywhere.
  • You must ensure your server has the correct MIME types for the audio files. Some browsers will happily play audio if the server says it has the wrong MIME type; others will fail silently. For AAC and Ogg Vorbis the types are audio/mp4 and audio/ogg respectively.
  • Most mobile devices can only play one sound at a time, and iOS generally doesn't let you play audio unless it's in a user-initiated input event (such as touchstart).
  • You'll probably want to use the Web Audio API where supported (Chrome and iOS 6+) since playback is more reliable and polyphonic even on iOS - but note iOS still mutes the Web Audio API until a user input event.
bersling
  • 17,851
  • 9
  • 60
  • 74
AshleysBrain
  • 22,335
  • 15
  • 88
  • 124
  • Very useful, thanks. I had no idea that mp3 was proprietary! I'll look into the MIME types, though I'm pretty sure I handled this correctly. I'll edit my post to that effect later in the day. Also, looks like Web Audio API is definitely the way to go. No theories about the actual question, though? – samson Nov 11 '12 at 18:19
  • I implicitly meant it could be any of the above, so it's a list of things to check through really. Usually server misconfiguration or browser limitations on mobile are the most common problems. Some mobile browsers also are much more fussy about which specific formats, or sub-formats of supported formats, they can play. – AshleysBrain Nov 11 '12 at 19:30
  • Ok, short of switching away from mp3 and switching to Web Audio API (both of which I'll do on my next deploy), and mobile browsers notwithstanding, I'm looking at the MIME type... I've updated my question with an excerpt from my `app.yaml` file, is that where I should add MIME types? Are they not implicit from the file extension? Again, sorry if the answers to these questions should be obvious to me, I'm just getting started with these technologies! – samson Nov 11 '12 at 22:38
0

This is not a direct answer to your question why sound is not being played, but more like what you should do with your game sound effects.

For game sound effects I suggest you use HTML5 Web Audio API which gives more control over how sounds are played (pitch of the sound effect, less delay in playback, etc):

http://www.html5rocks.com/en/tutorials/webaudio/intro/

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • Thanks! I'm learning Web Audio API now and will switch over to using it for my next version of the website. Is this pretty standard practice? Are there other APIs out there, or is this the only viable one? – samson Nov 11 '12 at 22:39
  • In past people have been using Flash wrappers for audio (Angry Birds for Chrome for example), but nowadays I believe game developers are moving toward Web audio API – Mikko Ohtamaa Nov 11 '12 at 23:35
  • Cool. I'll go with Web Audio API, I think. – samson Nov 12 '12 at 00:18