2013-02-28 1 views
6

У меня есть следующий 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/ –

ответ

0

Попробуйте это:

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

Тогда первый раз вы называете это он будет получать звук, но каждый раз, после того, что он будет использовать тот же объект звука.


EDIT: Вы также можете предварительно загрузить с дубликатами, чтобы звук играть больше, чем один раз в то время:

(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

У этой проблемы есть такая же проблема. Звук будет воспроизводиться, но попытка воспроизвести его снова, прежде чем предыдущий экземпляр закончит воспроизведение результатов, в нем не будет воспроизводиться звук вообще. Кажется, что проблема с воспроизведением() аудио объекта до его завершения. –

+0

Мое обычное решение для этого - построить массив. Я отредактирую свой ответ с этим. –

+0

Кажется не работает, но я получаю общее представление о том, что вы пытаетесь сделать. –

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 только пытается загрузить аудиофайл один раз.

Предостережения: Я не уверен в воздействии на производительность, так как на моем сайте этот клип не воспроизводится более чем на 40x максимум для страницы. Возможно, вам придется очищать аудиоустройства, если вы делаете что-то гораздо большее?

0

Полагаясь больше памяти, чем время процесса, мы можем создать массив из нескольких клонов Audio, а затем воспроизводить их по порядку:

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

}