2013-02-28 125 views
6

我有以下的基於canvas的遊戲的JS代碼。通過JS重疊播放音頻

var EXPLOSION = "sounds/explosion.wav"; 

function playSound(str, vol) { 
    var snd = new Audio(); 
    snd.src = str; 
    snd.volume = vol; 
    snd.play(); 
} 

function createExplosion() { 
    playSound(EXPLOSION, 0.5); 
} 

這工作,但它向服務器發送請求,每次被調用時,下載的聲音文件。或者,如果我宣佈了音頻對象事先:

var snd = new Audio(); 
snd.src = EXPLOSION; 
snd.volume = 0.5; 

function createExplosion() { 
    snd.play(); 
} 

這工作,但是如果之前的聲音播放完createExplosion函數被調用,它不播放聲音都沒有。這意味着一次只允許一次播放聲音文件 - 在發生多次爆炸的情況下,它根本不起作用。

有什麼方法可以正確播放多次與自身重疊的音頻文件?

+1

結束了與使用AudioFX庫去:HTTP:// codeincomplete .com/posts/2011/9/17/revisiting_html5_audio/ – 2013-02-28 03:25:00

回答

0

試試這個:

(function() { 
    var snds = {}; 
    window.playSound(str,vol) { 
     if(!snds[str]) (snds[str] = new Audio()).src = str; 
     snds[str].volume = vol; 
     snds[str].play(); 
    } 
})(); 

然後你第一次調用它,將取回的聲音,但之後它會重複使用同一個聲音對象每次。


編輯:您還可以重複預裝允許播放聲音不止一次在同一時間:

(function() { 
    var snds = {} 
    window.playSound = function(str,vol) { 
     if(!snds[str]) { 
      snds[str] = [new Audio()]; 
      snds[str][0].src = str; 
     } 
     var snd = snds[str], pointer = 0; 
     while(snd[pointer].playing) { 
      pointer++; 
      if(pointer >= snd.length) { 
       snd.push(new Audio()); 
       snd[pointer].src = str; 
      } 
     } 
     snd[pointer].volume = vol; 
     snd[pointer].play(); 
    }; 
})(); 

請注意,如果你玩的聲音也與其自身重疊,這將發送多個請求很多,但它應該很快返回Not Modified,並且只有在您比以前多次播放時纔會這樣做。

+0

這會遭遇同樣的問題。聲音會播放,但在前一個實例播放完畢之前嘗試播放會導致聲音根本不播放。在播放音頻對象之前,它似乎是一個問題。 – 2013-02-28 01:11:28

+0

我通常的解決方案是構建一個數組。我會用這個編輯我的答案。 – 2013-02-28 01:12:17

+0

似乎沒有工作,但我對你想要做的事情有一個粗略的想法。 – 2013-02-28 01:27:47

0

我一直在尋找這個在我正在建設的俄羅斯方塊遊戲的年齡,我認爲這個解決方案是最好的。

function playSoundMove() { 
    var sound = document.getElementById("move"); 
    sound.load();  
    sound.play(); 
} 

只是它已加載並準備好去。

1

您可以複製節點與cloneNode()play()複製節點。

我的聲音元素看起來是這樣的:

<audio id="knight-audio" src="knight.ogg" preload="auto"></audio> 

,我有一個onClick監聽器做到了這一點:

function click() { 
    const origAudio = document.getElementById("knight-audio"); 
    const newAudio = origAudio.cloneNode() 
    newAudio.play() 
} 

而且,由於audio元素是不會被顯示出來,你實際上並不需要將節點附加到任何東西上。

我驗證了客戶端和服務器端Chrome瀏覽器只嘗試下載音頻文件一次。

注意事項:我不確定關於性能的影響,因爲在我的網站上這個片段播放的頁面最多不會超過40倍。如果你做的比這個大得多,你可能不得不清理音頻節點?

0

更多地依賴於內存比處理時間,我們可以使音頻的多個克隆的數組,然後通過順序播放它們:

function gameSnd(){ 
    this.t = new Audio('sounds/tick.wav'); 
    this.v = new Audio('sounds/victory.wav'); 
    this.c = 0; 
    this.ticks=[]; 
    for(var i = 0; i<10;i++) 
    this.ticks.push(this.t.cloneNode()); 

    this.tick = function(){ 
    this.c = (this.c + 1)%10; 
    this.ticks[this.c].play(); 
    } 

    this.victory = function(){ 
    this.v.play(); 
    } 

}