2013-01-13 169 views
5

我想用OscillatorNodes發揮和絃OscillatorNodes和絃:播放使用網絡音頻API

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

的問題是使用'o'的循環和關閉,每次都要重新分配。另外避免使用'setTimeout',使用你給的函數。請參閱下面的** janesconference **解決方案。 – justinjmoses

回答

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

+0

謝謝,這當然有幫助。 – Labbekak

+0

解決了它,但並沒有解釋他的錯誤,重新分配了「o」並引入了沒有實際價值的收益。 – justinjmoses

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

你還在爲每個振盪器創建獨立的AudioContexts,這是可以接受的嗎? – Labbekak

+0

如果我用一個AudioContext運行你的代碼,它仍然聽起來很糟糕。 – Labbekak

+0

我的不好,我只是改變了代碼只有一個audiocontext – janesconference