Showing posts with label OGG. Show all posts
Showing posts with label OGG. Show all posts

Friday, December 20, 2013

Adding Music to Your Game (Game Programming)

The last several posts have been all about audio in Firefox OS. I've learned a lot about what works, and what doesn't work, on my trusty little ZTE Open. Go back and read: HTML5 Audio, HTML5 Audio Followup, Son of HTML5 Audio Followup, and HTML5 Audio Triumphant. Whew! There were surprises for me and technical blind alleys, but now no one has any excuse for not adding music and sound effects to their HTML5 Firefox OS game! And this post will show you how!


What I did is to add two sound effects and one background song to the SVG Collision Detection example.  That example had an innocent ball, a hungry box, and impending doom for the ball. But the ball can jump out of the way, and the point there was to show you how SVG has built-in collision detection, but there's just enough of a game in it to justify adding music and SFX (sound effects).

Here's the game screen:


Here's the code (and you can go to the SVG Collision Detection post for details on how the non-audio code works. You may also want to refer to my previous audio posts for reasons why I chose the way I do audio in this post.

<!DOCTYPE HTML>
<html>  
  <head>
      <meta charset="utf-8"> 
    <title>
    Game Sounds
    </title>

    <script>
       
          // Global variables
      var boardWidth = 320;
      var boardHeight = 460;
      var bwPixels = boardWidth + "px";
      var bhPixels = boardHeight + "px";
        var redBallHor = 60;
      var redBallVer = 160;
      var redBallRad = 10;
      var howFast = 3;
        var blueBoxHor = 270;
      var blueBoxVer = 150;
      var audMove;
      var audJump;
      var audEnd;
      var flagJump = 0;
      var flagEnd = 0;
   
          // Namespace for SVG.
          svgNS = "http://www.w3.org/2000/svg";
     
      // Covers all bases for various browser support.
        var requestAnimationFrame =
          window.requestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.msRequestAnimationFrame; 

      // Event listeners
      // Page load event listener
      window.addEventListener("load", getLoaded, false);
      // Mouse down event listener
      window.addEventListener(
          "mousedown", redBallJump, false);
         
      // Run this when the page loads.
      function getLoaded(){

        // Make sure we are loaded.
        console.log("Page loaded!");    
       
        // Load audio.
        audMove = new Audio("move.ogg");
        audJump = new Audio("jump.ogg");
        audEnd = new Audio("end.ogg");
       
        // Set up audio event listeners.
        audMove.addEventListener("canplaythrough",
          moveAudioOK, false);
        audJump.addEventListener("canplaythrough",
          jumpAudioOK, false); 
        audEnd.addEventListener("canplaythrough",
          endAudioOK, false);        
    
        // Create SVG parent element.
        myBoard = document.createElementNS(svgNS, "svg");
        myBoard.style.setProperty("width",bwPixels);
        myBoard.style.setProperty("height",bhPixels);
        myBoard.style.setProperty("top","0px");
        myBoard.style.setProperty("left","0px");
        myBoard.style.setProperty("position","absolute");
        
        // You must append the board to the body.
        document.getElementById("pageBody").
             appendChild(myBoard);
            
        // Create blue box.
        blueBox =
          document.createElementNS(svgNS, "rect");
         
        // Width,  height, radius, and color of box.
        blueBox.x.baseVal.valueAsString =
          blueBoxHor + "px";
        blueBox.y.baseVal.valueAsString =
          blueBoxVer + "px";
        blueBox.width.baseVal.valueAsString =
          "20px";
        blueBox.height.baseVal.valueAsString =
          "20px";       
        blueBox.style.
          setProperty("fill","blue","");
         
        // Attach the box to the game board.
        myBoard.appendChild(blueBox);

        // Create red ball.
        redBall =
          document.createElementNS(svgNS, "circle");
         
        // Width,  height, radius, and color of ball.
        redBall.cx.baseVal.valueAsString =
          redBallHor + "px";
        redBall.cy.baseVal.valueAsString =
          redBallVer + "px";
        redBall.r.baseVal.valueAsString =
          redBallRad + "px";
        redBall.style.
          setProperty("fill","red","");
         
        // Attach the ball to the game board.
        myBoard.appendChild(redBall);
       
        // Create ground.
        myGround =
          document.createElementNS(svgNS, "rect");
         
        // Width,  height, radius, and color of box.
        myGround.x.baseVal.valueAsString =
          "0px";
        myGround.y.baseVal.valueAsString =
          "170px";
        myGround.width.baseVal.valueAsString =
          "320px";
        myGround.height.baseVal.valueAsString =
          "230px";       
        myGround.style.
          setProperty("fill","chocolate","");
         
        // Attach the box to the game board.
        myBoard.appendChild(myGround);

        // Start the main loop.
        doMainLoop();
      }

      // Game loop
      function doMainLoop() {
               
        // Loop within the loop.
        // Outer loop
        // Runs every second.
            loopTimer = setTimeout(function() {
       
          // Inner loop
          // Runs as fast as it can.
          animTimer = requestAnimationFrame(doMainLoop);         
      
          // Drawing code goes here
              console.log("Moving the box.");
         
              // Move the box
              moveBlueBox();
         
        }, 1000 / howFast); // Delay / how fast     
      }
           
      // Move the blue box here.
      function moveBlueBox() {
     
          // Subtract 10 from box horizontal value.
          blueBoxHor = blueBoxHor - 10;
     
      // Draw the new blue box.
      blueBox.x.baseVal.valueAsString =
          blueBoxHor + "px";
             
          // If the blue box hits the left edge, restart.
          if (blueBoxHor < 10) blueBoxHor = 270;   

          // Get bounding box of box.
      bbBox = blueBox.getBBox();
      console.log(bbBox.x);

      // Get bounding box of ball.
      bbBall = redBall.getBBox();
      console.log(bbBall.x);

      // Is there an x collision?
      if (bbBall.x + 20 == bbBox.x) {
     
        // Is there a y collision?
        if (bbBall.y == bbBox.y) {
       
          // Collision!
          blueBoxHor = 270;
         
          // Make the end sound.
          if(flagEnd == 1) {
       
            // Play the end sound.
            audEnd.play();    
          }

          alert("Bang");
        }
      }  
      }

    // Make the red ball jump up.
    function redBallJump() {

      // Calculate red ball jump and move it.
      redBallVer = redBallVer - 50;  

      // Draw the new red ball.
      redBall.cy.baseVal.valueAsString =
          redBallVer + "px"; 

      // Make the jump sound.
      if(flagJump == 1) {
       
        // Play the jump sound.
        audJump.play();    
      }
 
      console.log("Ball up.");
   
      // Make the red ball fall after one second.
      redBallTimer = setTimeout(redBallFall, 1000);     
    } 

    // Make the red ball fall down.
    function redBallFall() {
   
      // Calculate the redBox fall and move it.
      redBallVer = redBallVer + 50; 
     
      // Draw the new red box.
      redBall.cy.baseVal.valueAsString =
          redBallVer + "px";    
      console.log("Ball down.");  
    }
   
    // Process the move audio loaded event.
    function moveAudioOK() {
   
      console.log("Move sound loaded.");
     
      // Loop and play the audio.
      audMove.loop = true;
      audMove.play(); 
    }
   
    // Process the jump audio loaded event.
    function jumpAudioOK() {
   
      console.log("Jump sound loaded.");
     
      // Set the jump audio flag.
      flagJump = 1;    
    }

    // Process the end audio loaded event.
    function endAudioOK() {
   
      console.log("End sound loaded.");
     
      // Set the end audio flag.
      flagEnd = 1;      
    }

    </script>
  </head>
   
  <body id="pageBody">
  </body>

</html>


I use three OGG audio files for this example:

     move.ogg - plays a song in the background

     jump.ogg - plays a sound effect when the ball jumps

     end.ogg - plays an explosion when the box and ball collide

If you want to play along at home, you can get these song files from my page on SoundCloud.

     move.ogg - https://soundcloud.com/thulfram/move

     jump.ogg -  https://soundcloud.com/thulfram/jump

     end.ogg - https://soundcloud.com/thulfram/end

SoundCloud is simply wonderful for musicians (and me).

Adding the Music and Sound Effects to your Game Code

I've evolved a fairly simple and fool-proof way to work with HTML5 Audio in Firefox OS. Here's what I have found works.

  1. Create a global name for every different sound. This makes sure that the sound will be available in every function. (But don't tell Douglas Crockford. He hates globals). Just put in placeholders. You will attach them later.
  2. After you make sure the page is loaded (with an event listener for the page load event), create a unique audio object for every sound you want to use. Use the new Audio() command and specify the name of the song when you do so. This will load the audio file. All your audio files should be in the OGG file format.
  3. Create an event listener for every audio object and use the canplaythrough event (not the canplay event). Audio files may take a while to load. With JavaScript, you can never assume that anything will load instantly, and sometimes code will run faster than things that you load. This applies to audio files for music and image files for canvas. Remember: trust no one! Especially not things you load into a web page.
  4. The event listener you created for each audio object should point to a unique function. In that function, you can do different things. One might be to kick off a song that plays in the background constantly. But another use would be for a specific sound effect that you don't want to play right away, but play later when something happens. If this is the case, use the unique function for that audio object to set a flag. Flags also should be global (so they can be used in any function anywhere) and are initially set to 0 (zero). When the audio object is loaded in its unique function, set the flag to 1.
     
  5. Then, when you want a sound to play, for example, when the red ball jumps, you first check to see if the flag is set (equal to 1). If it is, you play the song. But maybe the song is still loading, so if the flag is not set, don't try to play it. Sometimes code runs faster than loading (memorize this: code is faster than load).
     
  6. You can mute sounds using the flag. First kill the onplaythrough event, then call the pause() method of that sound, and finally,  set the flag to 0 (zero).
A little complicated, but following these steps will make sure you can play music and sound when you want to. And you want to, because music and sound can make a good game great!

Here's the lines that were added to the original code of the SVG Collision Detection file.

Setting the Global Audio Object Placeholders

These were put in the Globals section.

      var audMove;
      var audJump;
      var audEnd;


Creating the Audio Objects

These were put in the function that is called when the page loads.

        audMove = new Audio("move.ogg");
        audJump = new Audio("jump.ogg");
        audEnd = new Audio("end.ogg");


These create a new audio element with a specific name and use a specific audio file. OGG is your friend.

Setting Up Event Listeners for Each Audio Object

Just creating an audio object doesn't guarantee it will happen instantly, or at all. You don't want your game to crash, trying to call a non-existent file you forgot to load. Here are the event listeners.

        audMove.addEventListener("canplaythrough",
          moveAudioOK, false);
        audJump.addEventListener("canplaythrough",
          jumpAudioOK, false); 
        audEnd.addEventListener("canplaythrough",
          endAudioOK, false);   
     

They create an event listener for each audio object and use the canplaythrough event. A unique function is created that will be called when the canplaythrough event is triggered.

Filling in the Functions that will be Called by the Audio Events

If you use flags, specify them first in the Globals section. Here are the two flags I used for jumping and ending the game.

      var flagJump = 0;
      var flagEnd = 0;


Here is the function that is called when the canplaythrough event is triggered on the jump audio object.

   function jumpAudioOK() {
   
      console.log("Jump sound loaded.");
     
      // Set the jump audio flag.
      flagJump = 1;    
    }


It's always a good idea to have a console.log for loading. Then you can look in the console and see if your audio actually loaded. Beats an alert every time! Next, for this sound, you only set the jump flag to 1. That's it. The end audio object is the same, with only the names changed to protect the guilty.

For the background music move audio object, you don't need no stinkin' flags, you just want to play the music. So the function looks like this:

    function moveAudioOK() {
   
      console.log("Move sound loaded.");
     
      // Loop and play the audio.
      audMove.loop = true;
      audMove.play(); 
    }


You first set the audio move object so that it loops, and then you play it! How cool is that?

Playing Sound Effects

If it's not background music, you only want to play a sound effect when some event happens, like the ball jumping or the game ending.

For the ball jumping, I just inserted these lines in the code where the ball actually jumps, right after the ball is drawn.

      // Make the jump sound.
      if(flagJump == 1) {
       
        // Play the jump sound.
        audJump.play();    
      }


Here's where the flag earns its dinner. You want to test to see if the flag has been set. If the flag is 1, you know that it is fully loaded and can play. Once you've determined this, you just ... play it!

For the explosion sound when the box and ball collide, I just added these lines right after the code determines that the ball and box have collided and the box has moved out of the way.

          if(flagEnd == 1) {
       
            // Play the end sound.
            audEnd.play();    
          }


Again, I make sure that the sound is loaded and can play, and then I play it. Boom!

That's all there is to it:
  1. Global placeholders.
  2. Create the Audio after the page is loaded.
  3. Make sure the Audio is loaded by using the canplaythrough event.
  4. Process the Audio when loaded by playing (if background music).
  5. Use flags to make sure you can play Audio at a particular time.
  6. Use OGG.
  7. Have fun!
How did I Make this Music?

If you're a programmer or artist, making music can be hard. But there are lots of people who can make music and are eager to put it in your game. Ask around on Twitter or go to a Game Jam!

Speaking of Game Jams, as I've been learning about gaming in Firefox OS, I've been seeing a lot of talk about Game Jams. There are lots of them and people take part to ee if they can make a game in 48 hours. It reminds me of science fiction conventions, small groups of people, high energy, no sleep!

So I went to Kindle and read two books:

Game Jam Survival Guide by Christer Kaitila 
 Global Game Jam - 48 hours of Persistence, Programming, and Pizza at Scottish Game Jam by Jon Brady.
Both books were fascinating and I recommend them, for different reasons.

The first is a good guide to what goes on and how to survive one. If you're going to one and wonder how they work and what you need to think about before you go, get it!

The second was a long but entertaining ramble on how a game jam feels from the inside. Definitely gives the flavor of a game jam, and reminds me of Hunter S. Thompson (minus the drugs and sex).

But tbe Game Jam Survival Guide, as well as being entertaining, had some resources that were very helpful to this post.

Christer mentioned something called SFXR that was used in game jams a lot. I looked it up and it is a cool tool for making quick sound effects. Here's what it looks like:


You click on the buttons on the left until you get a sound you like (for example, a Jump sound). You can click on the button in the middle to modify the sounds, and there are even two buttons on the bottom left to mutate and randomize.  When you get something you like, click on Export .WAV and you've got a WAV file. Then use Audacity (or some other audio software) to convert it to OGG and use it in your game. Get it at http://www.drpetter.se/project_sfxr.html.

Kotaku also had a great article about using a tracker called Pulseboy that makes it easy to create chiptune music like the old 8-bit computers. Read the article here http://kotaku.com/5949117/make-chiptunes-in-your-browser-with-this-awesome-simple-sequencer. And get Pulseboy here: http://www.pulseboy.com/. Trackers are an old-school way to make music that have been replaced by Digital Audio Workstations (Sonar, Acid, Reason, Cubase, Logic Pro, FL Studio, etc.) which are big and expensive. I use FL Studio (formerly known as Fruity Loops until the cereal company made them stop) and Acid. The only tracker I used was Octamed and I don't like trackers because they are more complicated. If you want to know more about trackers, start here: http://woolyss.com/tracking-trackers.php.

Pulseboy is cool because it recreates the sounds of the Gameboy and looks like one too!


Pulseboy consists of 16 tracks, running vertically. You click on a square on the track and supply note information. When Pulseboy runs, it plays all 16 tracks and music comes out. Primitive, but at the same time simple. If you want chip music, use Pulseboy. Get it at: http://www.pulseboy.com/. It's pretty easy to learn and simple.

Between Pulseboy and SFXR, you can make your own music. Chip tunes belong with pixel art and both are very cool, so you don't have to be an artist or musician to make great game art and music.

As usual, all of this was tested and run on a Firefox OS ZTE Open phone.

Now back to games!


Thursday, December 12, 2013

HTML5 Audio Followup (Game Programming)

I'm still deep into HTML5 Audio programming as it relates to Firefox OS. I ran into some interesting problems and filed bug 949129 to make sure I'm not crazy. I'll be working on some work-arounds for the problems I'm seeing so you can still use audio in your games.













This post will cover a few things more I've found, in random order.

Audio Codecs

André Jaenisch pointed out that I didn't explain that MP3 and OGG are not lossless. This means that when the audio file is created, some of the bits are removed so that the file size is smaller. A popular format for lossless audio is FLAC. But this blog is all about Firefox OS gaming and right now, FLAC is not supported. As a matter of fact, MP3 is not supported either.

The original non-lossy formats were WAV (Windows) and AIFF (Apple). There might be an original Unix/Linux format (AU?)  but I've not used it. WMA (Windows), AAC (Apple), and MP3 (Fraunhofer) all use compression to make file sizes smaller, but still sound pretty good. Somewhere in the middle is the open-source FLAC, which uses compression but doesn't lose any quality and is considered lossless.

MP3 is an interesting issue for Firefox. For a long time, Firefox didn't support MP3 directly unless your operating system had already set up support. Because of this, when programming audio for the Firefox browser, you had to make two files, one MP3 and the other OGG. And for other browsers, you might have to add in an Apple codec (but we don't speak Apple here). You can read about Firefox support at https://developer.mozilla.org/en-US/docs/HTML/Supported_media_formats, but keep in mind that this is a moving target.

Very recently, Mozilla announced that they will support MP3 and pay the fee. MP3 costs money right now, OGG is free! The good news is that the MP3 patents will expire in a year or two.

Why does all this matter? If you have your music in MP3 and you convert it to OGG, the lossy audio will become more lossy. Right now, the music I download onto my ZTE Open will play even if it is MP3, but if I want to write a program in HTML5, my best bet is OGG. Firefox will let you program a WAV file, but the WAV file size is larger than OGG or MP3, and for a phone, you always want the smallest of everything.

So the point is, if you are making music for the Firefox OS, create your original file in WAV format (or one of the Apple formats), but at some point, convert it to OGG. But save your original file (lossless) so you can convert it later if you want to program with MP3.

My own personal guess is that OGG will be supported in Firefox OS for a long time, so its a safe bet. WAV is supported, but large file sizes will make it a poor option for phones and tablets. MP3 support will be soon, and I wouldn't be surprised to see in the future support for Apple's AAC, which is catching on fast (because it has smaller file sizes and better fidelity than MP3).

And don't forget, OGG is open source and very cool!

So if you think HTML5 audio is confusing, wait until you get to HTML5 video! But the answer is to start working with Web Audio (not the same as HTML5 Audio) which is supported. I'll be poking into that soon, but there's more pressing matters.

Oh, and I misspelled the cool audio workstation Ardour. Sorry, guys. Get it at http://ardour.org/

Globals

According to many wise JavaScript gurus, you should avoid globals. However, I find that I need them to make things simple for small game demos. So in the recent HTML5 Audio post at http://firefoxosgaming.blogspot.com/2013/12/html5-audio-game-programming_10.html,  I had this global definition:

      // Global variables
      var myAudio;


I don't assign it anything yet, because I need to wait until the page loads. This variable is used for the audio object and gets created in the audio constructor here, but only after the page loads:

      myAudio = new Audio("oggsong.ogg");

When working with objects and loading things, you always want to make sure that you know something is loaded before you use it. But also, in this case, if you don't make myAudio global, the function processMyAudio won't know where to find it.

And as part of the making sure, processMyAudio doesn't get called until canplaythrough tells us that the audio is now loaded and ready to go!

If you do these things without some of the safeguards, things might work or they might not. But you want to be sure. But if you don't make myAudio global, the music won't play. Using JavaScript functions is cool, but you want to make sure that everything inside the function can be used.

You can rewrite this program to avoid globals and pass things through function calls, but for now, I want to keep everything as simple as possible. If you want to know more about why globals are evil, check out JavaScript, the Good Parts. The book is difficult but worth reading several times, and I don't always agree with the author, but he clearly knows what he's talking about.

Here's a great picture of the two best books on JavaScript:


The thin book on the left is Crockford's JavaScript: The Good Parts. The thick book on the right is called JavaScript: The Definitive Guide by David Flanagan. Read both and you'll know most of what you need to know. Make sure you get the latest edition of Flanagan, because it gets updated every few years. Note the size difference of the two books, but there's lots of good parts in the bigger book also.

Firefox OS Simulator

The Firefox OS simulator (available to your Firefox browser as a plug-in) is really valuable for debugging audio. Something that runs just fine in the desktop browser may not work on the phone. Why do I bring this up?

If you use MP3 in the Firefox desktop browser, all works well. But not on the phone. If you use OGG, your audio works in the simulator. Before audio, I barely looked at the simulator unless there was a sizing issue, but for audio, it's crucial that the sound works at the simulator level.

What Might Not Be Working

I was surprised to see that two of the audio object's properties, duration and currentTime didn't work in Firefox OS when they work just fine in desktop Firefox. I haven't read all the browser source code yet, but I filed a bug 949129. You can check it out at https://bugzilla.mozilla.org/show_bug.cgi?id=949129. You can read my test code there.

By the way, if you find any kind of bug, make sure you can reproduce it, and file it at Bugzilla. Remember, YOU are Mozilla. Make it better and bang on it today. Especially with Firefox OS, which is still young and growing.

I'll keep you posted.

Next

I'm working on a work-around for the lack of currentTime. I'll also do some short code samples for loop and controls. And there's a sample game I want to get on to next, and maybe some game engines, and oh, yes, more game reviews. And vibration and tilt and oh, the list goes on forever!

Tuesday, December 10, 2013

HTML5 Audio (Game Programming)

HTML5 Audio has been around forever, or at least as long as HTML5. There's something new called WebAudio that has a lot more features, but HTML5 Audio lets you play a tune for your game. I'm exploring HTML5 Audio and I'll share what I find as I confirm what works in Firefox OS.


There are a lot of twists and turns in the audio field. You have to create your music somehow and then make sure it's in the right format. Some of this is changing in Firefox, but here's what seems to work best. Encode your audio in OGG.

What the heck is OGG? Well, you probably have heard of MP3 music and OGG is like MP3 but is open source and not proprietary. Both MP3 and OGG compress your music to make it smaller without losing any of the quality of the sound. OGG lives at http://www.vorbis.com/. You don't need to understand OGG, you just need to save an audio file to OGG if you are creating it, and convert music files to OGG if you have it in some other format like MP3, WAV, or WMA. A great open source tool for converting audio is Audacity, which lives at http://audacity.sourceforge.net/ Audacity has been around forever and is really a great piece of open source free software.

I'll be working with audio as part of my blog, so I'll just say the tools I like. I've used a lot of audio tools over the years, but right now here is my tool chain.

  1. Create audio in EnergyXT. This is an inexpensive audio workstation that I like. You can create music pretty easily with it and there's lots of help and tutorials. Find it at http://www.energy-xt.com/. It is on sale for €39. Available for Windows, Mac, Linux, and iOS.
  2. Right now I'm having fun with Chip Tune Music and my favorite software instrument is ChipSounds at http://www.plogue.com/products/chipsounds/. Not cheap at $95, but there are lots of open source and/or free chip tune instruments. The basic idea is that you add instruments or pre-made loops together to make a song using a workstation like EnergyXT. There are plenty of other workstatons and tons of instruments and loops. For more info on creating music through software, check out http://www.kvraudio.com/. And while you're at it, read Computer Music magazine at http://www.musicradar.com/computermusic/. Music software makes it easy to create music because you can create music bits and combine them together.
  3. Sometimes I like to combine bits of music I've created in a program that let's me work with several tracks. I like Adobe Audition because I've used it a long time and I use an old version, so you might want to look around. The new Audition is expensive. But I use the old one. I've been meaning to look at Ardor, which is a very cool open source alternative. http://ardour.org/
  4. And as a final step, I run all the combined tracks through Audacity to tweak and convert. My old copy of Audition doesn't know about OGG. But if you want to work with Firefox OS, you'll want to make OGG your new BFF.
So enough about making music. Make it OGG and be proud of open source!

I wrote some simple code that just plays an ogg file. Here it is:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      Simple Audio
    </title>
      <script>

      // Global variables
      var myAudio;

      // Load the page.
      window.addEventListener("load",
        runFirst, false);

      // Runs when the page is loaded.
      function runFirst() {

        console.log("page loaded");

        // Create audio object.
        // We like OGG.
        myAudio = new Audio("oggsong.ogg");

        // Listen for fully loaded audio.
        myAudio.addEventListener("canplaythrough",
          processMyAudio, false); 
      }

      function processMyAudio() {

        console.log("audio loaded");

        // Play the audio.
        myAudio.play();
      }

       </script>
    </head>

    <body>
    </body>

</html>


This code is pretty simple. Use these steps:
  1. Make a global variable for your audio object.
  2. Wait until the page loads.
  3. Create an audio object and give it an audio file to load.
  4. Wait until the audio file loads.
  5. When it loads, play the audio!
You'll notice a pattern that is often useful. Load something, set an event handler to wait until it loads, and then use it. Because we're working in the mysterious world of browsers, you can't always know when exactly something will load or in what order. Especially if you're loading something from a server or something is slow, like a big file.

Creating the Audio Object

Here's the bit that creates the audio object.

        myAudio = new Audio("oggsong.ogg");

This is going deeper into the DOM and is called a constructor. It makes an object and initializes it with the name of an audio file. This is assuming that your song is in the root directory as defined by the app manifest. Specify the folder in the constructor; you don't need to tell the manifest where the audio file is, it will just pull it in the same as an art file. Always make sure that you use the .ogg file extension (and that your file is OGG based.

Waiting for Audio

Here's the bit that waits for the audio to load.

         myAudio.addEventListener("canplaythrough",
          processMyAudio, false); 


It sets up an event listener that is waiting for the canplaythrough event to take place on the audio object.  The event is fired when all of the audio is loaded. Read more about it on the new-and-improved truly beautiful Mozilla Developer Network page at https://developer.mozilla.org/en-US/docs/Web/Reference/Events/canplaythrough. No, it isn't an special rule for golfers.

Play the Audio

After all this, the command is simple.

        myAudio.play();

The command sits in a function that is called only when the audio is good and ready. For many uses, you could just skip the waiting, but I like to be careful. You don't want to mess up your audio. I've noticed that not all the game I review have working audio and this is sad. Music is such a powerful addition to games and most games that succeed not only have a great game programmer, they have a great artist and a great musician. (And a great web site designer, business manager, and tea boy.)

The song will play once and that's all for now. There's more to the world of HTML Audio, but that's all for now. Stay tuned, but not iTuned!