2013-02-28 25 views
6

Ich habe den folgenden JS-Code für ein Canvas-basiertes Spiel.Wiedergabe von Audio durch JS mit Überlappung

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

Dies funktioniert, jedoch sendet es eine Serveranforderung, die Sounddatei jedes Mal herunterzuladen, wenn es aufgerufen wird. Alternativ kann, wenn ich die Audio-Objekt deklarieren vorher:

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

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

Dies funktioniert jedoch, wenn die createExplosion Funktion aufgerufen wird, bevor der Ton spielen fertig ist, ist es nicht den Ton spielen überhaupt. Dies bedeutet, dass nur ein einziges Durchspielen der Sounddatei gleichzeitig erlaubt ist - und in Szenarien, in denen mehrere Explosionen stattfinden, funktioniert es überhaupt nicht.

Gibt es eine Möglichkeit, eine Audiodatei mehrere Male überlappend mit sich selbst zu spielen?

+1

endete mit mit der AudioFX Bibliothek zu gehen: http: // codeincomplete .com/posts/2011/9/17/revisiting_html5_audio/ –

Antwort

0

Try this:

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

Dann wird das erste Mal, wenn Sie es so nennen sie den Klang holen, aber jedes Mal nach, dass es das gleiche Klangobjekt wiederverwendet werden.


EDIT: Sie können auch mit Dubletten vorspannen, dass der Sound mehr als einmal in einer Zeit spielen:

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

Beachten Sie, dass diese mehrere Anfragen senden, wenn Sie den Ton spielen überlappende selbst zu viel, aber es sollte nicht schnell sehr schnell zurückkommen und wird es nur tun, wenn du es öfter als vorher spielst.

+0

Dies hat das gleiche Problem. Der Sound wird abgespielt, aber der Versuch, ihn erneut zu spielen, bevor eine vorherige Instanz abgespielt wurde, führt dazu, dass der Sound überhaupt nicht wiedergegeben wird. Es scheint ein Problem mit dem Abspielen eines Audioobjekts zu sein, bevor es beendet ist. –

+0

Meine übliche Lösung ist ein Array zu erstellen. Ich werde meine Antwort damit bearbeiten. –

+0

Scheint nicht zu funktionieren, aber ich bekomme die grobe Vorstellung von dem, was Sie versuchen zu tun. –

0

Ich suchte seit Jahren in einem Tetris-Spiel, das ich baue, und ich denke, dass diese Lösung die beste ist.

haben Sie es einfach geladen und bereit zu gehen.

1

Sie könnten einfach den Knoten mit cloneNode() und play(), die Knoten duplizieren.

Meine Audio-Element sieht wie folgt aus:

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

und ich habe eine onClick Zuhörer die genau das tut:

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

Und da das audio Element wird nicht angezeigt, gehen wird, Sie muss den Knoten eigentlich nicht an etwas anhängen.

Ich verifizierte Client-Seite und Server-Seite, dass Chrome nur versucht, die Audiodatei einmal herunterzuladen.

Vorbehalte: Ich bin mir nicht sicher über Auswirkungen auf die Leistung, da dies auf meiner Website dieser Clip nicht mehr als ~ 40x maximal für eine Seite gespielt wird. Vielleicht müssen Sie die Audioknoten bereinigen, wenn Sie etwas viel Größeres machen?

0

mehr auf dem Gedächtnis als Prozesszeit Berufung können wir ein Array von mehrer Klonen des Audio machen und sie dann im Auftrag spielen:

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

}