How to remove pause between audio tracks in Javascript

I am creating a javascript game and I want to create background music based on the sound fragments of a file. Short mp3 files to play them as one continuous track. I tried to link the "finished" event handler in the sound file, although this causes a delay between the sound bites.

To solve this problem, I made a hacker solution that still does not work, changing the audio 1 second before its completion.

Ebuc.manageAudio = function(){ var listener = function (event) { if (this.currentTime > (this.duration - 1) && Ebuc.bgnext) { Ebuc.manageAudio(); console.log("aduio"); Ebuc.bgnext = false; } if(this.currentTime < 2){ Ebuc.bgnext = true; console.log("reset"); } console.log(event); console.log("listener active") }; var color = Level.current.color; if(Ebuc.bgsong == null) { Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); Ebuc.bgsong.addEventListener('timeupdate', listener, true); } else{ Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); } Ebuc.bgsong.play(); Resources.audioSetList[color].next(); }; 

This example works once, when it is time to switch fragment 2 to fragment 3, the cycle stops. The console registering the event listener gives four times the log before stopping.

Q1: Why does this event handler suddenly disappear? Q2: Is there a non-hacking solution for combining these sound bites.

I thank you in advance.

+8
javascript audio
source share
3 answers

You will have more than just pausing problems trying to quickly switch between two short audio clips, and you probably want to cross cross between two audio tracks as well to prevent any pop-ups, artifacts, etc.

Here's an example of crossfading using howler from howler github. Perhaps you can use this example and save the queue of loaded instances to go to. Hope this helps.

 //you'll probably want this crossfade duration to be shorter. var crossfadeDuration = 5000, volume = 0.7; var instance1, instance2, soundDuration; // Singleton helper to build similar instances var createHowlerInstance = function (urls, onload) { return new Howl({ urls: urls, loop: false, volume: 0, onload: onload }); }; // Create "slave" instance. This instance is meant // to be played after the first one is done. instance2 = createHowlerInstance(['file2.mp3']); // Create "master" instance. The onload function passed to // the singleton creator will coordinate the crossfaded loop instance1 = createHowlerInstance(['file1.mp3'], function(){ // Get the sound duration in ms from the Howler engine soundDuration = Math.floor(instance1._duration * 1000); (function crossfadedLoop(enteringInstance, leavingInstance){ // Fade in entering instance enteringInstance.pos(0).play().fade(0, volume, crossfadeDuration); // Wait for the audio end to fade out entering instance // white fading in leaving instance setTimeout(function(){ enteringInstance.fade(volume, 0, crossfadeDuration); crossfadedLoop(leavingInstance, enteringInstance); }, soundDuration - crossfadeDuration); })(instance1, instance2); }); 
+7
source share

Using the idea of ​​setting timeOut in response to pantalohnes, I created the following code to bridge the gap:

 Ebuc.manageAudio = function(){ var color = Level.current.color; Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); Ebuc.bgsong.addEventListener("loadedmetadata",function(){ setTimeout(Ebuc.manageAudio, (Ebuc.bgsong.duration * 1000) - 50); Ebuc.bgsong.play(); console.log(Ebuc.bgsong.duration); Resources.audioSetList[color].next(); }); }; 

A 50 millisecond timeout accurately drags the gap between sequenced files.

+3
source share

Answering your question (although I see that you found a different solution), I think I found your error:

The second time you enter Ebuc.manageAudio (), Ebuc.bgsong is already configured, and you just create a new Audio Ebuc.bgsong = new Audio(...) without adding a listener to it, so you will not be notified of any "timeupdate" events when playing the second audio file.

You must also remove the listener from the previous playback sound.

So, if everything else is fine, I think this should fix it:

 Ebuc.manageAudio = function(){ var listener = function (event) { if (this.currentTime > (this.duration - 1) && Ebuc.bgnext) { Ebuc.manageAudio(); console.log("aduio"); Ebuc.bgnext = false; } if(this.currentTime < 2){ Ebuc.bgnext = true; console.log("reset"); } console.log(event); console.log("listener active") }; var color = Level.current.color; if(Ebuc.bgsong != null) { Ebuc.bgsong.removeEventListener('timeupdate', listener, true); } Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); Ebuc.bgsong.addEventListener('timeupdate', listener, true); Ebuc.bgsong.play(); Resources.audioSetList[color].next(); }; 

Moreover, I think that if you correctly remove the listener from the previous playback sound, you will not need this bgnext hack at all:

 var listener = function (event) { if (this.currentTime > (this.duration - 1)) { Ebuc.manageAudio(); console.log("aduio"); } console.log(event); console.log("listener active") }; Ebuc.manageAudio = function () { var color = Level.current.color; if (Ebuc.bgsong != null) { Ebuc.bgsong.removeEventListener('timeupdate', listener, true); } Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); Ebuc.bgsong.addEventListener('timeupdate', listener, true); Ebuc.bgsong.play(); Resources.audioSetList[color].next(); }; 

Let me know if this worked :)

+1
source share

All Articles