I would like to play a chord using 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);
}
But this approach sounds like a mess (here's what it sounds like). If I try creating new AudioContexts for each note in the chord, then it sounds fine (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);
}
But I read that you're only supposed to have one AudioContext. What am I doing wrong?
Not sure this can be a solution, but I found out inserting a GainNode and setting it's value so that the gain will sum to 1 eliminates the issue:
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 = 1/freqs.length;
g.connect(ac.destination);
o.start(0);
setTimeout(function(s) {s.stop(0)}, 1000, o);
}
I tried this on Chrome 23.0.1271.101
Updated to use the new start
and stop
methods: createOscillator noteOn not working
noteOn(0)
starts the oscillator / note immediately.
Since your for loop takes time to create the oscillators, the start time is slightly delayed for every note after the first.
I would initialize each oscillator, put them in an array, then call noteOn()
on every one of them in another for loop.
And you don't need to call setTimeout, which is unreliable: noteOff
will be executed after in a second by calling 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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With