我想使用OscillatorNodes来演奏和弦:
var ac = new (window.AudioContext || window.webkitAudioContext);
// C4, E4, G4
var freqs = [261.63, 329.63, 392.00];
for(var i=0;i<freqs.length;i++) {
var o = ac.createOscillator();
o.frequency.value = freqs[i];
o.connect(ac.destination);
o.noteOn(0);
setTimeout(function() {o.noteOff(0)}, 1000);
}
但这种方法听起来像是一团糟(here's what it sounds like)。如果我尝试为和弦中的每个音符创建新的AudioContexts,那么听起来不错(like this):
// C4, E4, G4
var freqs = [261.63, 329.63, 392.00];
for(var i=0;i<freqs.length;i++) {
var ac = new (window.AudioContext || window.webkitAudioContext);
var o = ac.createOscillator();
o.frequency.value = freqs[i];
o.connect(ac.destination);
o.noteOn(0);
setTimeout(function() {o.noteOff(0)}, 1000);
}
但我读到你只应该有一个AudioContext。我做错了什么?
答案 0 :(得分:5)
不确定这可能是一个解决方案,但我发现插入一个GainNode并设置一个低值可以消除这个问题:
var ac = new (window.AudioContext || window.webkitAudioContext);
// C4, E4, G4
var freqs = [261.63, 329.63, 392.00];
for(var i=0;i<freqs.length;i++) {
var o = ac.createOscillator();
var g = ac.createGainNode();
o.frequency.value = freqs[i];
o.connect(g);
g.gain.value = 0.25;
g.connect(ac.destination);
o.noteOn(0);
setTimeout(function(s) {s.noteOff(0)}, 1000, o);
}
我在Chrome 23.0.1271.101
上试过这个答案 1 :(得分:4)
noteOn(0)
立即启动振荡器/音符。
由于你的for循环需要时间来创建振荡器,因此在第一个之后的每个音符的开始时间会稍微延迟。
我会初始化每个振荡器,将它们放入一个数组中,然后在另一个振荡器上调用noteOn()
进行循环。
你不需要调用setTimeout,这是不可靠的:noteOff
将在一秒钟之后通过调用noteOff(1)
来执行。
var ac = new (window.AudioContext || window.webkitAudioContext);
// C4, E4, G4
var freqs = [261.63, 329.63, 392.00];
var oscs = [];
// initialize the oscillators
for(var i=0;i<freqs.length;i++) {
var o = ac.createOscillator();
o.frequency.value = freqs[i];
o.connect(ac.destination);
oscs.push(o);
}
// schedule noteOn and noteOff (deprecated: the methods will be renamed to start() and stop() soon)
for (i = 0; i < oscs.length; i +=1) {
oscs[i].noteOn(0);
oscs[i].noteOff(1);
}