Web Audio API: Как я могу возобновить воспроизведение звука? - PullRequest
6 голосов
/ 23 октября 2011

Я написал базовый скрипт в Chrome, который использует новый Web Audio Api для загрузки 3 звуковых файлов (через XMLHTTPRequest) и воспроизведения каждого из них по отдельности. Я предоставил отдельную кнопку для каждого звука, которая позволяет пользователю запускать и останавливать каждый звук.

Сценарий немедленно загружает все три звуковых файла и, когда все готово, отменяет приглушение кнопок воспроизведения, чтобы пользователь мог нажать кнопку воспроизведения, только когда звук будет готов. Кроме того, звуки зацикливаются, поэтому при нажатии кнопки метка на каждой кнопке меняется с «Play» на «Stop».

Все это прекрасно работает ... Когда вы нажимаете кнопку Play, вы слышите зацикленный звук, а когда вы нажимаете кнопку Stop, звук останавливается. Однако, если вы попытаетесь повторно воспроизвести один и тот же звук во второй раз, звук не начнет воспроизводиться снова. Каждый раз, когда вы нажимаете кнопку Play / Stop, вызывается соответствующая функция playSound () или stopSound () и передаются соответствующие параметры, но по какой-то причине я просто не могу заставить звуки воспроизводиться во второй раз. Я что-то не так делаю?

Вот мой код:

<body>

<label for="playBtn1">Moog:</label>
<input id="playBtn1" type="button" value="Play" disabled />
<label for="playBtn1">Drums:</label>
<input id="playBtn2" type="button" value="Play" disabled />
<label for="playBtn1">Choir:</label>
<input id="playBtn3" type="button" value="Play" disabled />

<script>
  var playBtn1 = document.getElementById("playBtn1");
  var playBtn2 = document.getElementById("playBtn2");
  var playBtn3 = document.getElementById("playBtn3");

  var context = new webkitAudioContext();

  var soundBuffer1 = null;
  var soundBuffer2 = null;
  var soundBuffer3 = null;

  var soundBufferSourceNode1 = context.createBufferSource();
  soundBufferSourceNode1.looping = true;
  var soundBufferSourceNode2 = context.createBufferSource();
  soundBufferSourceNode2.looping = true;
  var soundBufferSourceNode3 = context.createBufferSource();
  soundBufferSourceNode3.looping = true;

  loadSound('micromoog.wav', 1);
  loadSound('breakbeat-drum-loop.wav', 2);
  loadSound('choir.wav', 3);

  playBtn1.addEventListener("click", function(e) {
    if(this.value == "Play") {
      this.value = "Stop";
      playSound(soundBuffer1, soundBufferSourceNode1);
    } else if(this.value == "Stop") {
      this.value = "Play";
      stopSound(soundBufferSourceNode1);
    }
  }, false);
  playBtn2.addEventListener("click", function(e) {
    if(this.value == "Play") {
      this.value = "Stop";
      playSound(soundBuffer2, soundBufferSourceNode2);
    } else if(this.value == "Stop") {
      this.value = "Play";
      stopSound(soundBufferSourceNode2);
    }
  }, false);
  playBtn3.addEventListener("click", function(e) {
    if(this.value == "Play") {
      this.value = "Stop";
      playSound(soundBuffer3, soundBufferSourceNode3);
    } else if(this.value == "Stop") {
      this.value = "Play";
      stopSound(soundBufferSourceNode3);
    }
  }, false);

  function loadSound(url, bufferNum) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';

    // Decode asynchronously
    request.onload = function() {
      var successCallback = function(buffer) {
        switch(bufferNum) {
          case 1:
            soundBuffer1 = buffer;
            playBtn1.disabled = false;
          break;
          case 2:
                soundBuffer2 = buffer;
            playBtn2.disabled = false;
          break;
          case 3:
            soundBuffer3 = buffer;
            playBtn3.disabled = false;
          break;
        }
      }
      var errorCallback = function(e) {
      console.log(e);
      }
      context.decodeAudioData(request.response, successCallback, errorCallback);
    }

    request.send();
  }

  function playSound(buffer, bufferSourceNode) {
    bufferSourceNode.buffer = buffer;
    bufferSourceNode.connect(context.destination);
    bufferSourceNode.noteOn(0);
  }

  function stopSound(bufferSourceNode) {
    bufferSourceNode.noteOff(0);
  }
</script>

</body>

Кроме того, кто-нибудь знает о каком-либо событии, которое может произойти, когда закончится воспроизведение нецикличного звука? Было бы здорово, если бы я мог установить эти звуки нецикличными, и как только звук закончится, используйте такое событие, чтобы переключить его метку. Я ничего не вижу в спецификации, но, может быть, есть лучший способ?

Спасибо, Бред.

Ответы [ 2 ]

6 голосов
/ 11 августа 2013

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

На этой странице: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ

Затем обратитесь к вопросам:

  • "Как я могу проверить, когда AudioSourceNode завершил воспроизведение?"
  • "У меня есть AudioBufferSourceNode, который я только что воспроизвел сnoteOn (), и я хочу воспроизвести его снова, но noteOn () ничего не делает!один раз.Как только вы остановите это, вы должны создать новый.Если вы хотите знать, когда конкретный звук перестал воспроизводиться, нет события, которое отправляет его;поэтому вы должны использовать тайм-аут.

    Надеюсь, это поможет!

5 голосов
/ 08 сентября 2012

Просто изучаю API Web Audio самостоятельно.На первый взгляд я бы сказал, что это потому, что вы должны создавать BufferSource каждый раз, когда проигрываете звук, и кажется, что вы делаете это только в первый раз.посмотрите примеры здесь: http://www.html5rocks.com/en/tutorials/webaudio/intro/

...