在 javascript 中重启振荡器

Restart oscillator in javascript

我试图让振荡器在鼠标打开时播放 canvas,在鼠标不打开时停止。但是,使用当前代码,它只在加载页面后工作一次,当鼠标处于 canvas 第二次时发生错误:

"Uncaught InvalidStateError: Failed to execute 'start' on 'OscillatorNode': cannot call start more than once.

var ac = new window.AudioContext() || new window.webkitAudioContext();
var osc = ac.createOscillator();
var canvas1 = document.getElementById("canvas1");
canvas1.addEventListener("mouseover", playosc); 
canvas1.addEventListener("mouseout", stoposc); 

function playosc() {
    osc.frequency.value = 440;
    osc.connect(ac.destination);
    osc.start();
}

function stoposc() {
    osc.stop();
}

如何重启振荡器?谢谢

您每次都需要创建一个振荡对象,因为振荡器节点不可重复使用。示例:

var canvas1 = document.getElementById("canvas1");
canvas1.addEventListener("mouseover", playosc); 
canvas1.addEventListener("mouseout", stoposc); 

var ac = new window.AudioContext() || new window.webkitAudioContext();
var osc;

function playosc() {
    osc = ac.createOscillator()
    osc.frequency.value = 440;
    osc.connect(ac.destination);
    osc.start();
}

function stoposc() {
    osc.stop();
}

请参阅此 excellent blog post 以获得更多指导。

更简单的方法是让振荡器启动并连接到增益节点,您可以在 0 和 1 之间调制该节点以确定振荡器是否输出。

var ac = new window.AudioContext() || new window.webkitAudioContext();
var osc = ac.createOscillator();
var gain = ac.createGain();
var canvas1 = document.getElementById("canvas1");
canvas1.addEventListener("mouseover", playosc); 
canvas1.addEventListener("mouseout", stoposc); 

gain.gain.value = 0;
osc.connect(ac.gain);
gain.connect(ac.destination);
osc.start();

function playosc() {
    osc.frequency.value = 440;
    gain.gain.value = 1;
}

function stoposc() {
    gain.gain.value = 0;
}

您也可以(并且应该)使用渐变。另外,您可以进一步调制增益(例如根据 canvas 内的鼠标位置)等。

是的,它将使用更多 CPU 用法(因为振荡器始终是 运行)。然而,获得值为 0 的节点作弊并且实际上并不相乘,它们只是吐出零数组。