Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play multiple instances of an html5's Audio object

I'm making a small game in Javascript and it requires some audio for better user experience. The main issue I have is that I have to play 1 song/sound multiple times, and sometimes at the same time. However, if I cloneNode the Audio object, the audio is downloaded one more time from the server, and so is only played latter, as it has to be downloaded first. So the sound can be downloaded over 100 times during normal game !

As I coulnd't find an answer on Internet, I'm asking you :)

Please note, that I want to do that with my own code, and not with a library.

like image 622
pictuga Avatar asked Jan 18 '11 19:01

pictuga


1 Answers

Solutions using new Audio()/HTMLAudioElement.play are good for things like music, but won't allow playing multiple copies of the same audio at a time. For sound effects, the right tool to use would be an AudioBuffer from the Web Audio API. As a simple example:

const playButton = document.getElementById('play');

let interval = null;

playButton.addEventListener('click', async () => {
  // if already started playback, just stop it
  if (interval !== null) {
    clearInterval(interval);
    interval = null;
    return;
  }

  // create an audio context
  const audioCtx = new AudioContext();
  
  // fetch a sound effect, and get an ArrayBuffer
  const resp = await fetch('https://upload.wikimedia.org/wikipedia/commons/6/68/Crash.ogg');
  const arrayBuffer = await resp.arrayBuffer();
  
  // decode the ArrayBuffer into an AudioBuffer
  const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
  
  // set an interval for every 250ms
  interval = setInterval(() => {
    // create an AudioBufferSourceNode
    const source = audioCtx.createBufferSource();
    
    // set the AudioBuffer
    source.buffer = audioBuffer;
    
    // connect it to the default sound output
    source.connect(audioCtx.destination);
    
    // start playback
    source.start();
  }, 250);
});
<button id="play">Play</button>
like image 90
leo60228 Avatar answered Nov 03 '22 12:11

leo60228