问题
I'm trying to make oscillator play when mouse is on canvas and stop when it's not. However, with current code, it works just once after loading page, when mouse is on canvas second time error occurs:
"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();
}
How to restart oscillator? Thanks.
回答1:
You would need to create an Oscillator object each time as the OscillatorNodes are not reusable. Example:
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();
}
Please refer to this excellent blog post for more guidance.
回答2:
A simpler way is to have the oscillator start and connect to a gain node which you modulate between 0 and 1 to determine if the oscillator outputs or not.
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;
}
You can also (and should) use the ramping. Plus you can modulate the gain further (such as based on mouse position within the canvas) and so on.
Yes it will use more CPU usage (since the oscillator is always running). However gain nodes of values at 0 cheat and don't actually multiply, they just spit out arrays of zeros.
来源:https://stackoverflow.com/questions/37710236/restart-oscillator-in-javascript