本文介绍了Web Audio API随附的事件范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Web Audio API AudioSourceBufferNode及其onended事件中遇到一个棘手的问题。



基本上我想做的是有两个AudioSourceBufferNodes当另一个完成并持续播放时,每个触发。我明白,AudioSourceBufferNodes在你调用start()之后几乎完成了,而且它们被设计成在这之后进行垃圾收集。所以我试图解决这个问题:

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

函数getSound(buffer){
var src = context.createBufferSource();
src.buffer = buffer;
src.connect(context.destination);
return src;
}

这可能看起来很麻烦,但是我有很多具体的做法来回玩的东西,所以我真的很想弄清楚。无论如何,问题似乎是当我在 source1.onended 回调之内调用 source2.start() ,$ code> source2.onended 似乎听不到它什么时候结束,永远不会被调用。所以这也是理由,如果我曾经设法进入 source2.onended 回调, source1.onended 将没有听到新注册的 source1



所以我想我想知道的是什么是否有更好的方法来完成我想要做的事情?

解决方案

这是'一个范围问题。您正在第5行(getSound())内创建一个新的source2对象,并设置其onended属性。但是,当source1.onended被调用时,它将source2设置为由getSound创建的NEW对象,该对象将不会被设置。你需要设置你的onended方法,实际上。

  var source1 = null; 
var source2 = null;

函数onendedSource1(){
source2 = getSound(buffer2);
source2.onended = onendedSource2;
source2.start();
}

函数onendedSource2(){
source1 = getSound(buffer1);
source1.onended = onendedSource1;
source1.start();
}

函数getSound(buffer){
var src = context.createBufferSource();
src.buffer = buffer;
src.connect(context.destination);
return src;
}

//全部关闭
source1 = getSound(buffer1);
source1.onended = onendedSource1;
source1.start();

//注意,您只需用onendedSource2()一次调用上面的三行即可。

请注意,如果使用onended将缓冲区链接在一起,则无法正常工作要真正地相互对接 - 当音频完成在音频线程中播放时,会有一个明显的差距,然后在主线程上排队消息,并且该消息使其通过事件队列。如果应该有一个差距(就像两首淡入淡出的歌曲),没关系。


I'm having a tricky issue with the Web Audio API AudioSourceBufferNode and its onended event.

Basically what I'd like to do is have two AudioSourceBufferNodes that are each triggered when the other one finishes and keep playing back-and-forth. I understand that AudioSourceBufferNodes are pretty much done once you call start() and they're designed to be garbage-collected after this. So I tried to work around that like so:

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

This may look pretty cumbersome, but I have pretty specific reasons for doing the whole back-and-forth playing thing, so I'd really like to figure that out. At any rate, the problem seems to be that when I call source2.start() inside the source1.onended callback, source2.onended doesn't appear to hear when it ends and never gets called. So it also stands to reason that if I ever manage to get inside the source2.onended callback, source1.onended will not hear the newly-reassigned source1 either.

So I guess what I want to know is, what is the scope of the onended event, and is there a better way to accomplish what I'm trying to do?

解决方案

This isn't a scope issue. You're creating a new source2 object at line 5 (inside getSound()), and setting its onended property. However, when source1.onended is called, it's setting source2 to a NEW object created by getSound - which will not have onended set. You need to set the onended inside your onended methods, in effect.

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

Note that using "onended" to chain buffers together isn't going to work well if they are intended to truly abut each other - there will be a significant gap, as the audio finishes playing in the audio thread, then queues a message on the main thread, and that message makes its way through the event queue. If there's supposed to be a gap (like, two songs that fade in/out), it's fine.

这篇关于Web Audio API随附的事件范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 03:29