Web 音频 API - 终结点事件范围

Web Audio API- onended event scope

本文关键字:结点 事件 范围 音频 API Web      更新时间:2023-09-26

我在Web Audio API AudioSourceBufferNode及其onend事件方面遇到了一个棘手的问题。

基本上,我想做的是有两个AudioSourceBufferNodes,当另一个完成并继续来回播放时,每个节点都会被触发。我知道一旦你调用start(),AudioSourceBufferNodes就已经完成了,并且它们被设计为在此之后进行垃圾回收。所以我试图像这样解决这个问题:

var source1;
var source2;
source1 = getSound(buffer1);
source2 = getSound(buffer2);
source1.start();
source1.onended = function(){
    source2 = getSound(buffer2);
    source2.start();
}
source2.onended = function(){
    source1 = getSound(buffer1);
    source1.start();
}
function getSound(buffer){
    var src = context.createBufferSource();
    src.buffer = buffer;
    src.connect(context.destination);
    return src;
}

这可能看起来很麻烦,但我有非常具体的原因来做整个来回播放的事情,所以我真的很想弄清楚。无论如何,问题似乎是当我在source1.onended回调中调用source2.start()时,source2.onended似乎听不到它何时结束并且永远不会被调用。因此,如果我设法进入source2.onended回调,source1.onended也不会听到新重新分配的source1,这也是有道理的。

所以我想我想知道的是,事件的范围是什么,有没有更好的方法来完成我想要做的事情?

这不是范围问题。 您将在第 5 行(在 getSound() 中)创建一个新的 source2 对象,并设置其 onend 属性。 但是,当调用source1.onend时,它将source2设置为由getSound创建的新对象 - 该对象不会有onend set。 实际上,您需要在已结束的方法中设置已结束的方法。

var source1=null;
var source2=null;
function onendedSource1() {
    source2 = getSound(buffer2);
    source2.onended = onendedSource2;
    source2.start();
}
function onendedSource2() {
    source1 = getSound(buffer1);
    source1.onended = onendedSource1;
    source1.start();
}
function getSound(buffer){
    var src = context.createBufferSource();
    src.buffer = buffer;
    src.connect(context.destination);
    return src;
}
// kick it all off.
source1 = getSound(buffer1);
source1.onended = onendedSource1;
source1.start();
// note you could just replace the three lines above with one call to onendedSource2();

请注意,如果它们旨在真正彼此相邻,则使用"onended"将缓冲区链接在一起不会很好地工作 - 当音频在音频线程中完成播放,然后在主线程上排队一条消息,并且该消息通过事件队列时,将存在明显的差距。 如果应该有一个间隙(比如,两首歌淡入/淡出),那很好。