12

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; } 
2
  • What are you using to play the audio? I assume it is the <audio> tag. Commented Apr 30, 2012 at 14:58
  • sound = new Audio("souce.wav"); sound.play(); Commented Apr 30, 2012 at 14:59

5 Answers 5

7

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!

Sign up to request clarification or add additional context in comments.

1 Comment

Since i created an audio tag with a source tag as a child (<audio><source src="sound.mp3"/></audio>), I needed to set the optional deep param to true (sound.cloneNode(true)) in order for the play method to work on the cloned node.
2

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()

2 Comments

Yep. That's the best way I found. If anyone has a better solution, I would really like to know.
Late to the party, but you can also just "fake" your round robin by never playing the original: preload your clips, and then use audio.cloneNode(true).play() instead, so that you always get a fresh copy playing.
1

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.)

1 Comment

Aha! I knew someone planted that idea in my head before... Thanks ;)
1

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/

Comments

0
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); } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.