我们有一个web音频助手功能,可以播放声音表中的声音,并让我们知道它们何时完成。在过去,我们在更新循环中使用playbackState
来检查已经完成播放的节点,但由于Chrome 36现在使用当前规范,不支持playbackState
,我们更新了代码以使用'ended'
事件。
然而,这似乎并没有被解雇。
以下是我们的playAudio函数:-playAudio: function(trackName){
var node = this._atx.createBufferSource();
node.buffer = this._buffer;
var gain = this._atx.createGain();
node.connect(gain);
gain.connect(this._atx.destination);
var start = this._tracks[trackName][0];
var length = this._tracks[trackName][1] - start;
node.start(0, start, length);
var sound = {name: trackName, srcNode: node, gainNode: gain, startTime: this._atx.currentTime, duration: length, loop: false, playHeadStart: start};
if (this._features.hasEvents) {
//node.addEventListener("ended", function () {
// this._soundEnded(sound)
//}.bind(this));
node.onended = function(){
this._soundEnded(sound);
}.bind(this);
}
this._playingSounds[++this._soundId] = sound;
return this._soundId;
},
_soundEnded: function (sound) {
this._playingSounds[sound] = null;
delete this._playingSounds[sound];
}
通过在加载期间创建的音频节点上检查node.onended !== null
来设置this._features.hasEvents
变量。缓冲区是通过XHR文件创建的。这可以是mp3或m4a,这取决于我们播放的是什么。
_soundedEnded
函数没有被调用的原因是什么?我尝试了node.onended = function(){...}
和node.addEventListener("ended", function(){..})
语法,都没有运气。我们似乎在iOS 7 Safari和桌面/Android Chrome中都有相同的行为。
我刚刚解决了这个问题,在意识到我做了一些愚蠢的事情之后。这个bug不是WebAudio,而是回调函数,它应该从_playingSounds
数组中删除声音对象。
这段代码:
var sound = {name: trackName, srcNode: node, gainNode: gain, startTime: this._atx.currentTime, duration: length, loop: false, playHeadStart: start};
if (this._features.hasEvents) {
//node.addEventListener("ended", function () {
// this._soundEnded(sound)
//}.bind(this));
node.onended = function(){
this._soundEnded(sound);
}.bind(this);
}
this._playingSounds[++this._soundId] = sound;
return this._soundId;
应该更像这样:
var sound = {name: trackName, srcNode: node, gainNode: gain, startTime: this._atx.currentTime, duration: length, loop: false, playHeadStart: start};
var soundId = ++this._soundId;
if (this._features.hasEvents) {
node.onended = function(){
this._soundEnded(soundId);
}.bind(this);
}
this._playingSounds[soundId] = sound;
return soundId;
我试图通过值而不是键来删除对象,这显然不起作用。现在,代码将键传递给函数,一切都恢复正常。