Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async play sound in javascript?

how can I load asynchronously a sound in javascript ?

I want to play in loop severals sounds ans calculus in parallel. This is the timeline :

     10 seconds           7 seconds           10 seconds
|--------------------|------------------|--------------------|--- etc
| Sound1 playing     |Sound2 playing    | Sound1 playing     |--- etc 
| Do a calculus      |Do a calculus     | Do a calculus      |--- etc

Sound1 and Sound2 last less than 5 seconds Calculs last 1 second.

How can i do that in javascript ?

I must use Workers in HTML5 ?

Thanks.

like image 652
Scanpat Avatar asked Feb 17 '23 01:02

Scanpat


2 Answers

Playing sounds asynchronously in JS is in fact pretty simple. You just have to create new Audios and play() them right away instead of play()ing global Audio objects. Here's an example:

function playSoundAsync(url){
    new Audio(url).play();
}

So in your case, your code would look like this (with a hack involving setIntervals and setTimeouts for syncing up the sounds):

// For simplicity I'll use MP3 files readily available on the Internet
var sound1url = 'https://audio.code.org/win3.mp3';
var sound2url = 'https://audio.code.org/failure3.mp3';
var calculusUrl = 'https://audio.code.org/failure1.mp3';

setInterval(function() {
    new Audio(sound1url).play();
    new Audio(calculusUrl).play();
}, 17000);
setTimeout(function() {
    setInterval(function() {
        new Audio(sound2url).play();
        new Audio(calculusUrl).play();
    }, 17000);
}, 10000);
<button onclick="new Audio(sound1url).play();">Play sound1 individually</button>
<button onclick="new Audio(sound2url).play();">Play sound2 individually</button>
<button onclick="new Audio(calculusUrl).play();">Play calculus individually</button>

In addition, you might notice this when you click the Play ${sound} individually buttons rapidly: A new playback of ${sound} starts without waiting for or interrupting the current ${sound} playback! This allows you to create an acoustic mess like this:

var cacophony = setInterval(function(){new Audio('https://audio.code.org/win3.mp3').play();}, 25);
<button onclick="clearInterval(cacophony);">Click here to stop this cacophony</button>
like image 188
dorukayhan Avatar answered Feb 19 '23 15:02

dorukayhan


You can easily make your audio play async (without using a timer) by using JS promises and async functions.

// makes playing audio return a promise
function playAudio(audio){
  return new Promise(res=>{
    audio.play()
    audio.onended = res
  })
}

// how to call
async function test(){
  const audio = new Audio('<url>')
  await playAudio(audio)
  // code that will run after audio finishes...
}
like image 20
mabarif Avatar answered Feb 19 '23 15:02

mabarif