Как быстро воспроизвести несколько копий звукового файла в javascript - PullRequest
0 голосов
/ 27 апреля 2020

Я создаю колесо фортуны в html + js, которое вращается довольно быстро. Каждый раз, когда у знака появляется новый цвет, колесо должно издавать щелчок. На максимальной скорости это звучит почти как пулемет, поэтому новый файл начинает воспроизводиться раньше, чем старый заканчивается. Сам файл всегда один и тот же: click.wav

Он отлично работает в Chrome, только в chrome. Firefox имеет странную ошибку, при которой он воспроизводит звук, только если активен какой-либо другой источник звука, например видео на YouTube, воспроизводимое на другой вкладке. Edge и Safari как бы убирают клики до конца, а затем воспроизводят их все одновременно. Это беспорядок ... Я использую метод , описанный здесь , который использует клонирование тега <audio>

Я думаю, что здесь проблема:

var sound = new Audio("sounds/click.wav");
sound.preload = 'auto';
sound.load();

function playsound(){
    var click=sound.cloneNode();
    click.volume=1;
    click.play();
}

Вот упрощенная версия моей функции вращения, которая просто вызывает функцию playsound () несколько раз в секунду:

function rotateWheel(){
  angle = angle + acceleration
  while (angle >= 360) {
    angle = angle - 360
  } 
  var wheel = document.getElementById("wheel")
  wheel.style.transform = "rotate("+angle +"deg)"
  // play the click when a new segment rotates by
  if(Math.floor(angle/21) != previousSegment){
     playsound()
     previousSegment = Math.floor(angle/21)

}

1 Ответ

1 голос
/ 27 апреля 2020

Вы использовали ответ отсюда , который в какой-то момент приводит к тому, что sh обрабатывает браузер, потому что вы либо создаете проблему с памятью, либо заполняете DOM элементами, которые должен обрабатывать браузер - поэтому вам следует переосмыслить свой подход И, как вы выяснили, он не будет работать для интенсивного использования в большинстве браузеров, таких как safari или FireFox
Если заглянуть глубже в спецификацию тега <audio>, становится ясно, что есть много вещей с этим просто невозможно обойтись, что неудивительно, поскольку он был разработан для воспроизведения мультимедиа. Одно из ограничений включает в себя -> Нет мелкой синхронизации звука.

Таким образом, вы должны найти другой способ для того, что вы хотите, мы используем Web Audio API, предназначенный для онлайн-видеоигр.
Web Audio API
AudioContext для управления и воспроизведения все звуки. Чтобы создать звук с помощью API-интерфейса Web Audio, создайте один или несколько источников звука и подключите их к месту назначения звука, предоставленному экземпляром AudioContext (обычно динамиком). AudioBuffer
С API Web Audio аудиофайлы могут воспроизводиться только после их загрузки в буфер. Загрузка звуков требует времени, поэтому ресурсы, используемые в анимации / игре, должны загружаться при загрузке страницы, в начале игры или на уровне или постепенно, пока игрок играет.
Основы c шаги

  • Мы используем XMLHttpRequest для загрузки данных в буфер из аудиофайла.
  • Далее мы делаем асинхронный обратный вызов и отправляем фактический запрос на загрузку.
  • Как только звук буферизован и декодирован, он может быть запущен мгновенно.
  • Каждый раз, когда он срабатывает, создается другой экземпляр буферизованного звука.

Ключевая особенность звуковых эффектов в играх заключается в том, что их может быть много одновременно. Вот вам пример «пулемета»: представьте, что вы находитесь в середине перестрелки, стреляющего из пулемета. Пулемет стреляет много раз в секунду, вызывая одновременное воспроизведение десятков звуковых эффектов. Это где API Web Audio действительно сияет. Простой пример для вашего приложения:

/* global AudioContext:true,
*/

var clickingBuffer = null;
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();

function loadClickSound(url) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    // Decode asynchronously
    request.onload = function() {
        context.decodeAudioData(request.response, function(buffer) {
            if (!buffer) {
                console.log('Error decoding file data: ' + url);
                return;
            }
        clickingBuffer = buffer;
        });
    request.onerror = function() {
        console.log('BufferLoader: XHR error');        
        };
    request.send();
    };
}

function playSound(buffer, time, volume) {              
  var source = context.createBufferSource();   // creates a sound source
  source.buffer = buffer;                     // tell the source which sound to play
  source.connect(context.destination);          // connect the source to the context's destination (the speakers)
  var gainNode = context.createGain();          // Create a gain node
  source.connect(gainNode);                     // Connect the source to the gain node
  gainNode.connect(context.destination);        // Connect the gain node to the destination
  gainNode.gain.value = volume;                  // Set the volume
  source.start(time);                           // play the source at the deisred time 0=now    
}

// You call with in your document ready
   loadClickSound('sounds/click.wav');
//and this plays the sound
   playSound(clickingBuffer, 0, 1);

Теперь вы можете поиграться с разными временами и вариациями громкости, например, путем введения случайного фактора. Если вам нужно более сложное решение с различными звуками щелчков (хранится в буфере). массив) и вариации объема / расстояния, это будет более длинный кусок кода.

...