Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sound effects in JavaScript / HTML5

I'm using HTML5 to program games; the obstacle I've run into now is how to play sound effects.

The specific requirements are few in number:

  • Play and mix multiple sounds,
  • Play the same sample multiple times, possibly overlapping playbacks,
  • Interrupt playback of a sample at any point,
  • Preferably play WAV files containing (low quality) raw PCM, but I can convert these, of course.

My first approach was to use the HTML5 <audio> element and define all sound effects in my page. Firefox plays the WAV files just peachy, but calling #play multiple times doesn't really play the sample multiple times. From my understanding of the HTML5 spec, the <audio> element also tracks playback state, so that explains why.

My immediate thought was to clone the audio elements, so I created the following tiny JavaScript library to do that for me (depends on jQuery):

var Snd = {
  init: function() {
    $("audio").each(function() {
      var src = this.getAttribute('src');
      if (src.substring(0, 4) !== "snd/") { return; }
      // Cut out the basename (strip directory and extension)
      var name = src.substring(4, src.length - 4);
      // Create the helper function, which clones the audio object and plays it
      var Constructor = function() {};
      Constructor.prototype = this;
      Snd[name] = function() {
        var clone = new Constructor();
        clone.play();
        // Return the cloned element, so the caller can interrupt the sound effect
        return clone;
      };
    });
  }
};

So now I can do Snd.boom(); from the Firebug console and play snd/boom.wav, but I still can't play the same sample multiple times. It seems that the <audio> element is really more of a streaming feature rather than something to play sound effects with.

Is there a clever way to make this happen that I'm missing, preferably using only HTML5 and JavaScript?

I should also mention that, my test environment is Firefox 3.5 on Ubuntu 9.10. The other browsers I've tried - Opera, Midori, Chromium, Epiphany - produced varying results. Some don't play anything, and some throw exceptions.

like image 663
Stéphan Kochen Avatar asked Dec 19 '09 19:12

Stéphan Kochen


People also ask

How do you add sound effects to JavaScript?

The simplest way to add sound is through Javascript's Audio() constructor. It takes an argument of a string that is either the local or remote file path. Declaring this as a variable allows you to then call the play() method which starts playing the current audio.

How do you add sound effects in HTML?

HTML Audio - How It WorksThe controls attribute adds audio controls, like play, pause, and volume. The <source> element allows you to specify alternative audio files which the browser may choose from. The browser will use the first recognized format.

How do I add sound to onclick in HTML?

Using Onclick Event in Javascript: The onclick event fires the function when the user clicks on the button. In the following code, the play1 function is associated with onclick event. Function play1 receives the name of the audio file, then we select division with id=sound and inserts an HTML containing the audio tag.


3 Answers

HTML5 Audio objects

You don't need to bother with <audio> elements. HTML 5 lets you access Audio objects directly:

var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();

There's no support for mixing in current version of the spec.

To play same sound multiple times, create multiple instances of the Audio object. You could also set snd.currentTime=0 on the object after it finishes playing.


Since the JS constructor doesn't support fallback <source> elements, you should use

(new Audio()).canPlayType("audio/ogg; codecs=vorbis")

to test whether the browser supports Ogg Vorbis.


If you're writing a game or a music app (more than just a player), you'll want to use more advanced Web Audio API, which is now supported by most browsers.

like image 173
Kornel Avatar answered Oct 28 '22 21:10

Kornel


Web Audio API

Edit: As of December 2021, Web Audio API is essentially supported in Chrome, Firefox, Safari and all the other major browsers (excluding IE, of course).

As of July 2012, the Web Audio API is now supported in Chrome, and at least partly supported in Firefox, and is slated to be added to IOS as of version 6.

Although the Audio element is robust enough to be used programmatically for basic tasks, it was never meant to provide full audio support for games and other complex applications. It was designed to allow a single piece of media to be embedded in a page, similar to an img tag. There are a lot of issues with trying to use the it for games:

  • Timing slips are common with Audio elements
  • You need an Audio element for each instance of a sound
  • Load events aren't totally reliable, yet
  • No common volume controls, no fading, no filters/effects

Here are some good resources to get started with the Web Audio API:

  • MDN documentaion
  • Getting Started With WebAudio article
  • The FieldRunners WebAudio Case Study is also a good read
like image 26
Chris Jaynes Avatar answered Oct 28 '22 21:10

Chris Jaynes


howler.js

For game authoring, one of the best solutions is to use a library which solves the many problems we face when writing code for the web, such as howler.js. howler.js abstracts the great (but low-level) Web Audio API into an easy to use framework. It will attempt to fall back to HTML5 Audio Element if Web Audio API is unavailable.

var sound = new Howl({
  urls: ['sound.mp3', 'sound.ogg']
}).play();
// it also provides calls for spatial/3d audio effects (most browsers)
sound.pos3d(0.1,0.3,0.5);

wad.js

Another great library is wad.js, which is especially useful for producing synth audio, such as music and effects. For example:

var saw = new Wad({source : 'sawtooth'})
saw.play({
    volume  : 0.8,
    wait    : 0,     // Time in seconds between calling play() and actually triggering the note.
    loop    : false, // This overrides the value for loop on the constructor, if it was set. 
    pitch   : 'A4',  // A4 is 440 hertz.
    label   : 'A',   // A label that identifies this note.
    env     : {hold : 9001},
    panning : [1, -1, 10],
    filter  : {frequency : 900},
    delay   : {delayTime : .8}
})

Sound for Games

Another library similar to Wad.js is "Sound for Games", it has more focus on effects production, while providing a similar set of functionality through a relatively distinct (and perhaps more concise feeling) API:

function shootSound() {
  soundEffect(
    1046.5,           //frequency
    0,                //attack
    0.3,              //decay
    "sawtooth",       //waveform
    1,                //Volume
    -0.8,             //pan
    0,                //wait before playing
    1200,             //pitch bend amount
    false,            //reverse bend
    0,                //random pitch range
    25,               //dissonance
    [0.2, 0.2, 2000], //echo array: [delay, feedback, filter]
    undefined         //reverb array: [duration, decay, reverse?]
  );
}

Summary

Each of these libraries are worth a look, whether you need to play back a single sound file, or perhaps create your own html-based music editor, effects generator, or video game.

like image 35
d13 Avatar answered Oct 28 '22 20:10

d13