I really like to get feedback on the topics I write, good or bad. The good ones immediately get forwarded to my boss in hopes of a few more points in my review. The bad ones I try to fix the topics to make them better.

Some recent feedback wasn't bad, but rather a suggestion. "Luke" posted a comment on my topic "Using JavaScript to Control the Audio Object". He said that he'd like to change songs on the fly with a pick list. The original example had a text box that you could write in your own audio file to play, so it really didn't fit the bill.

On the Internet Explorer Testdrive site, there's a slick multi-file player that uses SVG, audio, and XML. For something a little simpler (seems to be a theme song in here somewhere), the mods I did to my original single song player might do the trick.

Specifying a source file on an audio element

There are two ways to assign a URL to an audio element in HTML, use the src attribute on the audio element or use the source element between the audio tags. The src attribute is good when you have just a single file that you're going to play.

Here's an ultra simple audio player:

<!DOCTYPE html>
< html>
  <head>
    <title>Simple Audio Example</title>
< /head>
< body>
  <audio control src="songfile.mp3" >Not supported</audio>
< /body>
< /html>

If you want to give the audio element a few choices of format, such as mp3, aac, or ogg, then you'll want to use the source elements.

<!doctype html>
< head>
    <title>
         Multiple format audio example
    </title>
    <!-- Uncomment the following meta tag if you have issues rendering this page on an intranet site. -->   
    <!--  <meta http-equiv="X-UA-Compatible" content="IE=9"/> -->
< /head>
< body>
    <h1>
         Using source to support multiple audio formats
    </h1>
    <!-- The browser will automatically choose the format it supports. -->
    <audio controls="true">
        <source src="demo.mp3" type="audio/mp3">
        <source src="demo.ogg" type="audio/ogg">
        <source src="demo.aac" type="audio/mp4">
        <!-- If no support at all. -->
        HTML5 audio not supported
    </audio>
< /body>
< /html>

The source element takes a single src attribute, but you can stack up as many elements as you have formats for a given file. The <audio> element picks the first format it can play. If you try to put three different mp3 songs in <source> elements, only the first will play, every time. Unlike the track element which similarly resides between the video element tags, you have no control, selection is automatic.

Swapping different audio source files

To set up multiple sources, like a playlist, you need to write a little JavaScript. When you want to change songs on an audio control, you can simply assign a new URL to the src property and call play(). There is one gotcha that can pop up. If you originally specified a song with the source element, you need to add one step, call load() before calling play().

<!DOCTYPE html>

<html>
< head>
    <title>Simple song switcher</title>
< /head>
< body>
  <audio controls="controls" id="myaudio">
    source src="firstaudiofile.mp3" type="audio/mp3">
    Sorry, HTML5 audio isn't supported.
  </audio><br />
  <button id="mybutton">Change songs</button>
  <script>
    // Handle the button click and play new file
    document.getElementById("mybutton").addEventListener("click", function () {
      // Get audio object from audio element
      var oAudio = document.getElementById('myaudio');
      // double check support, and set the
      if (oAudio) {
        oAudio.src = "nextaudioURL.mp4";
        oAudio.load();
        oAudio.play();
      }
    }, false);
  </script>
< /body>
< /html>

That's pretty much all you need to do. Where code could get complex is in the song switching algorithm.

A little more of a demo

Here's a dressed up version of the original sample from Using JavaScript to control the audio object.

audiojavascripttest

Not much to look at, but you can choose between 5 songs, or load your own. The code is below.

The example has a simple UI that consists of an input field, a select box, and a few buttons. The songs are hard coded into the select box, with the text and URL for a song as a data pair on each option element.

All events are handled by addEventListeners in the JavaScript code. The play button calls play or pause, depending on its current state. The load method is called first if play is being called.

To switch the Play button label between "Play" and "Pause", we've added event listeners to the pause and play events, rather the play button code itself. This allows the button text to follow the actual state of the audio control. While the initial code doesn't expose the audio controls, you could add the intrinsic controls by adding the controls="controls" attribute to the audio element. The play button that switches labels would still stay in sync.

<!DOCTYPE html>
< html>
 
  <head>
    <title>HTML5 audio playlist demo </title>   
    <!-- Uncomment the following meta tag if you have issues rendering this page on an intranet site. -->   
    <!--  <meta http-equiv="X-UA-Compatible" content="IE=edge"/> --> 
  </head>
 
  <body>
    <h1>Audio playlist demo</h1>
    <p><label>Enter an audio file URL:
      <input type="text" id="audiofile" size="80" />
      </label>
    </p>
    <p>Or pick from this list:</p>
    <select id="myselect">
      <option value="http://samples.msdn.microsoft.com/Workshop/samples/media/Musopen_Com_Symphony_No_5_in_C_Minor_Op_67_-_I_Allegro_con_brio.mp3">Symphony No. 5 in C Minor, Op. 67 - I. Allegro con brio (Ludwig van Beethoven)</option>
      <option value="http://samples.msdn.microsoft.com/Workshop/samples/media/Musopen_Com_Symphony_No_5_in_C_Minor_Op_67_-_II_Andante_con_moto.mp3">Symphony No. 5 in C Minor, Op. 67 - II. Andante con moto (Ludwig van Beethoven)</option>
      <option value="http://samples.msdn.microsoft.com/Workshop/samples/media/Musopen_Com_Symphony_No_5_in_C_Minor_Op_67_-_III_Allegro.mp3">Symphony No. 5 in C Minor, Op. 67 - III. Allegro (Ludwig van Beethoven)</option>
       <option value="http://samples.msdn.microsoft.com/Workshop/samples/media/Musopen_Com_Symphony_No_5_in_C_Minor_Op_67_-_IV_Allegro.mp3">Symphony No. 5 in C Minor, Op. 67 - IV. Allegro (Ludwig van Beethoven)</option>
      <option value="http://samples.msdn.microsoft.com/Workshop/samples/media/Musopen_Com_Piano_Concerto_in_A_Minor_Op_16_-_I_Allegro_molto_moderato.mp3">Piano Concerto in A Minor, Op. 16 - I. Allegro molto moderato (Edvard Grieg)</option>

    </select>
    <p>All selections performed by Skidmore College Orchestra, available on https://musopen.org/.</p>
    
    <audio id="myaudio">
      HTML5 audio not supported
    </audio>

    <button id="play">
      Play
    </button>
   
    <button id="rewind">
      Rewind
    </button>
   
    <button id="forward">
      Fast forward
    </button>
   
    <button id="restart">
      Restart
    </button>

    <script>
    // Global variable to track current file name.
      var currentFile = "";
      var oAudio = document.getElementById('myaudio');
      var btn = document.getElementById('play');
      var audioURL = document.getElementById('audiofile');
      var mySelect = document.getElementById("myselect");

      document.getElementById("play").addEventListener("click", function () {
        // Check for audio element support.
        if (oAudio) {
          try {
             // Tests the paused attribute and set state.
            if (oAudio.paused) {
              //Skip loading if current file hasn't changed.
              if (audioURL.value !== "") {
                 if (audioURL.value !== currentFile) {
                   oAudio.src = audioURL.value;
                  currentFile = audioURL.value;
                  oAudio.load(); // load the file
                }
              } else {
                var index = mySelect.selectedIndex;
                var playThis = mySelect.options[index].value;
                if (playThis !== currentFile) {
                  oAudio.src = playThis;
                   currentFile = playThis;
                  oAudio.load(); // load the file
                }
              }

              oAudio.play();
            }
            else {
               oAudio.pause();
            }
          }
          catch (e) {
            // Fail silently but show in F12 developer tools console
            if (window.console && console.error("Error:" + e));
          }
        }
      }, false);

      // These two event listeners handle changing the play button from Pause to Play and back.
      oAudio.addEventListener("pause", function () { btn.textContent = "Play"; }, false);
      oAudio.addEventListener("play", function () { btn.textContent = "Pause"; }, false);

      // Rewinds the audio file by 30 seconds.
      document.getElementById("rewind").addEventListener("click", function () {
        if (oAudio) {        // Check for audio element support.
          try {
            oAudio.currentTime -= 30.0;
           }
          catch (e) {
            // Fail silently but show in F12 developer tools console
            if (window.console && console.error("Error:" + e));
          }
        }
      }, false);

      // Fast forwards the audio file by 30 seconds.

      document.getElementById("forward").addEventListener("click", function () {
        if (oAudio) {        // Check for audio element support.

          try {
            oAudio.currentTime += 30.0;
          }
          catch (e) {
            // Fail silently but show in F12 developer tools console
            if (window.console && console.error("Error:" + e));
          }
         }
      }, false);

      // Restart the audio file to the beginning.
      document.getElementById("restart").addEventListener("click", function () {
        if (oAudio) {        // Check for audio element support.
          try {
            oAudio.currentTime = 0;
          }
          catch (e) {
            // Fail silently but show in F12 developer tools console
            if (window.console && console.error("Error:" + e));
          }
        }
      }, false);

      // On changing songs, pause video and call Play function again
      mySelect.addEventListener("change", function () {
        oAudio.pause();
        btn.click();
      }, false);
    </script>
  </body>
< /html>