我正在尝试使用网络音频,我发挥了一个功能来播放音符。
var context = new (window.AudioContext || window.webkitAudioContext)()
var make_triangle = function(destination, frequency, start, duration) {
var osc = context.createOscillator()
osc.type = "triangle"
osc.frequency.value = frequency
var gain = context.createGain()
osc.connect(gain)
gain.connect(destination)
// timing
osc.start(start)
osc.stop(start + 2*duration) // this line is discussed later
gain.gain.setValueAtTime(0.5, start)
gain.gain.linearRampToValueAtTime(0, start+duration)
}
用法是这样的:
make_triangle(context.destination, 440, context.currentTime+1, 1)
这很好用。
Firefox的开发者控制台中有一个Web Audio标签。当我播放声音时,振荡器和增益显示在图表中。如果没有osc.stop(start + 2*duration)
行,这些就永远存在。使用osc.stop(start + 2*duration)
行,振荡器会消失,但Gain会永远与AudioDestination保持连接。
我不希望因为仍然连接了许多旧东西而导致内存泄漏或性能损失。 创建节点后我需要在多大程度上清理?我应该停止振荡器吗?断开一切?既?
答案 0 :(得分:1)
如果您不希望振荡器永远存在,您肯定需要安排它最终停止。否则它将永远发挥,消耗资源。一个非常聪明的实现可能能够做一些聪明的事情,但我不会依赖它,因为这不是必需的。
当振荡器停止时,它应自动断开自身与任何下游节点的连接。如果没有其他对振荡器或任何下游节点的引用,那么它们最终都应该被收集而不必做任何事情。
如果不发生这种情况,这是实施中的错误。
Firefox的WebAudio开发人员标签中可能存在增益节点仍然出现的错误。但它也可能是Firefox实施中的一个错误。
答案 1 :(得分:1)
Web Audio API旨在让振荡器在“注释”结束后立即停止[1]。如果使用行osc.stop(start + 2*duration)
,则振荡器将与增益断开连接并立即销毁。
如果您不打算重新使用振荡器所连接的增益节点,那么我建议将其断开以便可以对其进行垃圾回收。
只需将此回调添加到make_triangle
功能中的振荡器即可:
...
osc.onended = function() {
gain.disconnect();
};
};
一旦振荡器结束其生命周期(即:调用stop
方法或使用时序参数调度时),就会触发回调。
如果您在Firefox的Web Audio选项卡打开的情况下尝试此操作,您将看到断开连接的增益节点最终被垃圾收集(只要没有其他连接到增益节点)。
此外,拥有一个与AudioContext
连接的单个增益节点并不是一个坏主意,以便其他节点可以连接到它。这种“最终增益”对于混合所有其他连接节点并防止它们被削波(即:超过幅度1)非常有用。您可以将此节点作为参数传递到make_triangle
函数中,如下所示:
var context = new (window.AudioContext || window.webkitAudioContext)()
// Gain that will remain connected to `AudioContext`
var finalGain = context.createGain();
finalGain.connect(context.destination);
var make_triangle = function(destination, frequency, start, duration) {
var osc = context.createOscillator()
osc.type = "triangle"
osc.frequency.value = frequency
var gain = context.createGain()
osc.connect(gain)
gain.connect(destination)
// timing
osc.start(start)
osc.stop(start + 2*duration) // destroy osc and disconnect from gain
gain.gain.setValueAtTime(0.5, start)
gain.gain.linearRampToValueAtTime(0, start+duration)
// Added for cleanup:
osc.onended = function() {
gain.disconnect();
};
};
// Connect a new triangle osc to the finalGain
make_triangle(finalGain, 440, context.currentTime, 1);