Restart oscillator in javascript

♀尐吖头ヾ 提交于 2020-01-11 11:34:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!