views:

4835

answers:

6

I'm using HTML5 for its most noblest purpose: games, of course! The obstacle I've run into now is how to play sound effects.

The game is a port of an old Macintosh game, and because of it's age, the 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'. Neat. 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? Preferebly something within HTML5 and Javascript, because this experiment is focused on these two technologies. (And I lack any experience in Flash or Silverlight.)

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.

+4  A: 

For the widest compatibility I would really recommend using small FLASH object that can interact with Javascript. That's much easier method than trying audio element in HTML5 due to the current (and not-to-be-soon) support.

check this project as an example: http://www.schillmania.com/projects/soundmanager/ current and advanced version: http://www.schillmania.com/projects/soundmanager2/

dusoft
I wonder why this got voted down?
zombat
OP specifically asked for an HTML5-based solution that didn't involve any Flash or Silverlight
Raul Agrait
Something shiny HTML5ish was definitely preferred, but it's good to know there's a fall-back. Going by their frontpage, SoundManager even abstract away all the Flash-specifics, which is neat. I may use this in fall-back code, so thanks!
Shtééf
Raul: read better next time, he said: "Preferebly something within HTML5 and Javascript, because this experiment is focused on these two technologies. (And I lack any experience in Flash or Silverlight.)" - yes, preferebaly, not ONLY. give me a break.
dusoft
Yes, SoundManager is nicely wrapped in JavaScript and so shouldn't require any actual Flash development, so voted this up.Since the goal of the project sounds partly like making a demo of HTML5 functionality though, guessing porneL's answer re: the Audio API might be the best solution for this particular case.
Ben
@dusoft: You are correct, I did miss the "preferably" part. I tried negating my down vote, but it said my vote was too old to be changed, unless your post was edited. Sorry.
Raul Agrait
A: 

To play the same sample multiple times, wouldn't it be possible to do something like this:

e.pause(); // Perhaps optional
e.currentTime = 0;
e.play();

(e is the audio element)

Perhaps I completely misunderstood your problem, do you want the sound effect to play multiple times at the same time? Then this is completely wrong.

adamse
That's correct, I need to play the same sample multiple times at the same time.
Shtééf
+2  A: 

Have a look at the jai (javascript audio interface) site. From looking at their source, they appear to be calling play() repeatedly, and they mention that their library might be appropriate for use in HTML5-based games.

You can fire multiple audio events simultaneously, which could be used for creating Javascript games, or having a voice speaking over some background music

Raul Agrait
That link didn't work for me, but this does: http://bocoup.com/open-source/jai/
Derek Kurth
+2  A: 

Sounds like what you want is multi-channel sounds. Let's suppose you have 4 channels (like on really old 16-bit games), I haven't got round to playing with the HTML5 audio feature yet, but don't you just need 4 <audio> elements, and cycle which is used to play the next sound effect? Have you tried that? What happens? If it works: To play more sounds simultaneously, just add more <audio> elements.

I have done this before without the HTML5 <audio> element, using a little Flash object from http://flash-mp3-player.net/ - I wrote a music quiz (http://webdeavour.appspot.com/) and used it to play clips of music when the user clicked the button for the question. Initially I had one player per question, and it was possible to play them over the top of each other, so I changed it so there was only one player, which I pointed at different music clips.

Lee Kowalkowski
That's an interesting thought, to use <audio> elements as channels. When I put two elements on a page, I *can* play them simultaneously.It looks like the cloning I'm doing doesn't actually do what I expect, because in my original code, playing two samples also works. Just not twice the same sample.I'll have to experiment with this some more, and will get back on the results!
Shtééf
Yeah, there's possibly a subtle reason why it's called clone and not copy. Perhaps the clone is still sharing something with the original that prevents them from both playing simultaneously.
Lee Kowalkowski
For reference, re-using the same <audio> element doesn't work, at least in Firefox. You can set the 'src' attribute, but it won't actually load a different sample.
Shtééf
+13  A: 

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

var snd = new Audio("file.mp3");
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.

porneL
This is exactly what I'm doing now, thanks for the pointer! I still use the <audio> elements, because they allow me to a) autobuffer and b) still specify all resources in the HTML page. I just read their 'src' attributes like before to instantiate the Audio. Firebug doesn't show any additional requests, so cache works, and everything's peachy!
Shtééf
`Audio` objects are autobuffered. They're designed analoguous to `Image` objects, so oldschool image preloading techniques work with audio too.
porneL
A: 

It's not possible to do multi-shot playing with a single <audio> element. You need to use multiple elements for this.

Eli Grey