corazza
corazza

Reputation: 32354

In HTML5, can I play the same sound more than once at the same time?

I'm making a game, in which sounds are often played. I noticed that a sound wont play again while it is being played. For example, the player collides with a wall, a "thump" sound is played. But, if the player collides with one wall, and then quickly collides with another wall, only one "thump" sound is played, and I believe that this happens because the first sound didn't finish. Is that true? How should I avoid this? I thought of preloading the sound three times, always playing a different copy of that sound, but this seems rather stupid...

SOLVED:

Turns out I was right... You need to preload multiple versions of the sound and then circularly play them.

THE CODE:

var ns = 3; //The number of sounds to preload. This depends on how often the sounds need to be played, but if too big it will probably cause lond loading times.
var sounds = []; //This will be a matrix of all the sounds

for (i = 0; i < ns; i ++) //We need to have ns different copies of each sound, hence:
    sounds.push([]);

for (i = 0; i < soundSources.length; i ++)
    for (j = 0; j < ns; j ++)
        sounds[j].push(new Audio(sources[i])); //Assuming that you hold your sound sauces in a "sources" array, for example ["bla.wav", "smile.dog" "scream.wav"] 

var playing = []; //This will be our play index, so we know which version has been played the last.

for (i = 0; i < soundSources.length; i ++)
    playing[i] = 0; 

playSound = function(id, vol) //id in the sounds[i] array., vol is a real number in the [0, 1] interval
{
    if (vol <= 1 && vol >= 0)
        sounds[playing[id]][id].volume = vol;
    else
        sounds[playing[id]][id].volume = 1;

    sounds[playing[id]][id].play();
    ++ playing[id]; //Each time a sound is played, increment this so the next time that sound needs to be played, we play a different version of it,

    if (playing[id] >= ns)
        playing[id] = 0;
}

Upvotes: 12

Views: 10783

Answers (5)

Ray Hulha
Ray Hulha

Reputation: 11221

class SoundPool {
  pool : HTMLAudioElement[] = [];
  constructor(sound:HTMLAudioElement) {
    this.pool.push(sound);
  }

  play() {
    let found = false;
    for(var i=0; i<this.pool.length; i++) {
      if( this.pool[i].paused) {
        this.pool[i].play();
        found=true;
        break;
      }
    }
    if(!found) {
      let a = this.pool[0].cloneNode() as HTMLAudioElement;
      a.play();
      this.pool.push(a);
    }

  }
}

Upvotes: 0

Rex
Rex

Reputation: 71

You can clone the audio element. I don't know if you can play them more than once simultaneously, but here is how you can play a sound more than once without downloading it more than once.

var sound = document.getElementById("incomingMessageSound")
var sound2 = sound.cloneNode()
sound.play()
sound2.play()

I know this works for chrome, which is the only place I needed it. Good luck!

Upvotes: 7

justGoscha
justGoscha

Reputation: 24136

Although it is only implemented in FireFox and Chrome right now, in the future you should use the WebAudio API, which is specifically designed for games and audio applications in the browser.

There you can play back any sound multiple times and do several other fun stuff with it.

A good tutorial for that is here: http://www.html5rocks.com/en/tutorials/webaudio/games/

Upvotes: 1

apsillers
apsillers

Reputation: 115910

Yes, a single <audio> object can only play one track at a time. Consider that the <audio> object has a currentTime attribute that indicates the current position of the audio track: if an <audio> object could play multiple tracks are once, what value would currentTime reflect?

See my solution for a superset of this problem on Is playing sound in Javascript performance heavy?. (Basically, add duplicate <audio> tags with the same sound.)

Upvotes: 1

mrbinky3000
mrbinky3000

Reputation: 4291

Load the sound several times to simulate polyphony. Play them in round-robin fashion. Check out my demo at matthewtoledo.com. Specifically, the function _initSoundBank()

Upvotes: 2

Related Questions