如何在Javascript中删除音轨之间的暂停

时间:2016-03-22 12:09:06

标签: javascript audio

我正在构建一个javascript游戏,我想基于声音文件片段创建背景音乐。短mp3文件将它们作为一个连续的轨道播放。我试过绑定"结束"音频文件上的事件处理程序,但这会导致音频片段之间的延迟。

为了解决这个问题,我提出了一个仍然不起作用的hacky解决方案,在完成之前1秒更改音频。

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

};

此示例有效一次,当需要将片段2切换到片段3时,循环停止。记录事件监听器的控制台在停止之前给出4次日志。

Q1:为什么这个事件发生者突然消失了? Q2:是否存在用于链接这些音频片段的非黑客解决方案。

我提前感谢你。

3 个答案:

答案 0 :(得分:7)

您不仅要暂停尝试快速切换两个短音频片段的问题,您还可能希望快速在两个音轨之间交叉淡入淡出,以防止任何弹出,文物等。

以下是使用来自howler's github issues.的咆哮的交叉淡化的示例您可能可以使用此示例,并保持已加载实例的队列转换为。我希望有所帮助。

//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);

});

答案 1 :(得分:3)

通过在pantalohnes的答案中设置timeOut的想法,我创建了以下代码来解决这个差距:

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

50毫秒的超时精确地填补了有序文件之间的差距。

答案 2 :(得分:1)

回答你的问题(虽然我发现你找到了另一个解决方案),我想我找到了你的错误:

第二次输入Ebuc.manageAudio(),Ebuc.bgsong已经设置好了,你只需要创建一个新的音频Ebuc.bgsong = new Audio(...)而不将听众附加到它,所以你没有收到任何'timeupdate的通知'播放第二个音频文件时发出的事件。

您还应该从之前播放的音频中删除侦听器。

所以,如果一切正常,我认为应该解决它:

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

};

不仅如此,我认为如果你从之前播放的音频中正确删除了听众,你根本不需要那个bgnext hack:

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

};

如果有效,请告诉我:)