【问题标题】:Web Audio API: How Can I Re-start the Playback Of a Sound?Web Audio API:如何重新开始播放声音?
【发布时间】:2013-09-13 01:53:48
【问题描述】:

我在 Chrome 中编写了一个基本脚本,它使用新的 Web Audio Api 加载 3 个声音文件(通过 XMLHTTPRequest)并单独播放每个文件。我为每个声音提供了一个单独的按钮,允许用户开始和停止每个声音。

脚本会立即加载所有三个声音文件,完成后,将播放按钮取消调暗,这样用户只有在声音准备好后才能点击播放。此外,声音会循环播放,因此每个按钮上的标签在单击按钮时会在“播放”和“停止”之间变化。

这一切都很好......当您点击播放按钮时,您会听到循环声音,当您点击停止时,声音会停止。但是,当您再次尝试重新播放相同的声音时,声音将不会再次开始播放。每次单击“播放/停止”按钮时,都会调用相应的 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>

另外,是否有人知道在播放完非循环声音后可能触发的任何类型的事件?如果我可以将这些声音设置为非循环播放,并且一旦播放完声音,使用这样的事件来切换它的标签,那就太酷了。我在规范中看不到任何内容,但也许有更好的方法?

谢谢, 布拉德。

【问题讨论】:

  • 你解决过这个问题吗?我也有类似的问题。
  • 我在这里遇到了完全相同的问题! :S 有什么想法吗?

标签: javascript google-chrome html5-audio


【解决方案1】:

我知道这已经晚了一年,但我遇到了类似的问题,我快速搜索了几下,结果如下:

在本页:http://updates.html5rocks.com/2012/01/Web-Audio-FAQ

然后参考问题:

  • “如何检查 AudioSourceNode 何时播放完毕?”
  • “我有一个 AudioBufferSourceNode,我刚刚用 noteOn() 播放了它,我想再播放一次,但是 noteOn() 什么也没做!求助!”

据我了解:从 createBufferSource() 创建的源只能播放一次。一旦你停止它,你必须创建一个新的。如果您想知道特定声音何时停止播放,则没有调度它的事件;所以你必须使用超时。

希望这会有所帮助!

【讨论】:

  • 回复。当源完成播放时没有事件 - 现在有一个“onended”回调。我刚刚验证它在 Chrome v35 中有效: audioSource.onended = function() { playingSound = false; };感谢 Anders Lauritsen 在 cmets 中的提示:updates.html5rocks.com/2012/01/Web-Audio-FAQ
【解决方案2】:

我自己只是在学习 Web Audio API。乍一看,我会说这是因为您应该在每次播放声音时都创建缓冲源,而且您似乎只在第一次时才这样做。在此处查看示例:http://www.html5rocks.com/en/tutorials/webaudio/intro/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 2017-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多