2013-01-13 5 views
5

Vorrei suonare un accordo con OscillatorNodes:Eseguendo un accordo con OscillatorNodes utilizzando l'API Web Audio

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); 
} 

Ma questo approccio suona come un pasticcio (here's what it sounds like). Se provo la creazione di nuovi AudioContexts per ogni nota dell'accordo, poi suona bene (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); 
} 

ma ho letto che si suppone solo per avere un'AudioContext. Che cosa sto facendo di sbagliato?

+0

Il il problema è il ciclo e la chiusura con l'uso di 'o' che viene riassegnato ogni passaggio. Inoltre evita del tutto "setTimeout", usa le funzioni che ti vengono date. Vedere la soluzione ** janesconference ** di seguito. – justinjmoses

risposta

5

Non sono sicuro questo può essere una soluzione, ma ho scoperto che l'inserimento di un GainNode e impostando un valore basso elimina il problema:

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); 
} 

Ho provato questo su Chrome 23.0.1271.101

+0

Grazie, questo sicuramente ha aiutato. – Labbekak

+0

Risolve ma non spiega il suo errore con la riassegnazione di 'o' e introduce guadagno senza valore reale. – justinjmoses

4

noteOn(0) avvia immediatamente l'oscillatore/nota.

Poiché il ciclo for richiede tempo per creare gli oscillatori, l'ora di inizio viene leggermente ritardata per ogni nota dopo la prima. Vorrei inizializzare ogni oscillatore, inserirli in un array, quindi chiamare noteOn() su ognuno di essi in un altro ciclo for.

E non è necessario chiamare setTimeout, che è inaffidabile: noteOff verrà eseguito dopo un secondo chiamando lo 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); 
} 
+0

Stai ancora creando AudioContex separati per ogni oscillatore, è accettabile? – Labbekak

+0

Se eseguo il codice con un AudioContext, sembra ancora molto male. – Labbekak

+0

Il mio male, ho appena cambiato il codice con un solo audiocontext – janesconference

Problemi correlati