我使用HTML5来编写游戏;我现在遇到的障碍是如何播放音效。

具体要求不多:

播放和混合多种声音, 多次播放相同的样本,可能会重复播放, 在任何时候中断样本的回放, 最好播放WAV文件包含(低质量)原始PCM,但我可以转换这些,当然。

我的第一个方法是使用HTML5 <audio>元素并在我的页面中定义所有音效。Firefox播放WAV文件的效果很好,但是多次调用#play并不能真正地多次播放示例。根据我对HTML5规范的理解,<audio>元素还跟踪播放状态,这就解释了为什么。

我的第一个想法是克隆音频元素,所以我创建了以下小型JavaScript库来为我做这件事(依赖于jQuery):

var Snd = {
  init: function() {
    $("audio").each(function() {
      var src = this.getAttribute('src');
      if (src.substring(0, 4) !== "snd/") { return; }
      // Cut out the basename (strip directory and extension)
      var name = src.substring(4, src.length - 4);
      // Create the helper function, which clones the audio object and plays it
      var Constructor = function() {};
      Constructor.prototype = this;
      Snd[name] = function() {
        var clone = new Constructor();
        clone.play();
        // Return the cloned element, so the caller can interrupt the sound effect
        return clone;
      };
    });
  }
};

现在我可以写snd。boom();从Firebug控制台并播放snd/boom.wav,但我仍然不能多次播放相同的样本。<audio>元素似乎更像是一个流媒体功能,而不是用来播放声音效果的。

有什么聪明的方法可以做到这一点,最好只使用HTML5和JavaScript?

我还应该提一下,我的测试环境是Ubuntu 9.10上的Firefox 3.5。我尝试过的其他浏览器——Opera、Midori、Chromium、Epiphany——产生了不同的结果。有些不播放任何内容,有些则抛出异常。


当前回答

var AudioContextFunc = window.AudioContext || window.webkitAudioContext; var audioContext = new AudioContextFunc(); var player=new WebAudioFontPlayer(); var instrumVox,instrumApplause; var drumClap,drumLowTom,drumHighTom,drumSnare,drumKick,drumCrash; loadDrum(21,function(s){drumClap=s;}); loadDrum(30,function(s){drumLowTom=s;}); loadDrum(50,function(s){drumHighTom=s;}); loadDrum(15,function(s){drumSnare=s;}); loadDrum(5,function(s){drumKick=s;}); loadDrum(70,function(s){drumCrash=s;}); loadInstrument(594,function(s){instrumVox=s;}); loadInstrument(1367,function(s){instrumApplause=s;}); function loadDrum(n,callback){ var info=player.loader.drumInfo(n); player.loader.startLoad(audioContext, info.url, info.variable); player.loader.waitLoad(function () {callback(window[info.variable])}); } function loadInstrument(n,callback){ var info=player.loader.instrumentInfo(n); player.loader.startLoad(audioContext, info.url, info.variable); player.loader.waitLoad(function () {callback(window[info.variable])}); } function uhoh(){ var when=audioContext.currentTime; var b=0.1; player.queueWaveTable(audioContext, audioContext.destination, instrumVox, when+b*0, 60, b*1); player.queueWaveTable(audioContext, audioContext.destination, instrumVox, when+b*3, 56, b*4); } function applause(){ player.queueWaveTable(audioContext, audioContext.destination, instrumApplause, audioContext.currentTime, 54, 3); } function badumtss(){ var when=audioContext.currentTime; var b=0.11; player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*0, drumSnare.zones[0].keyRangeLow, 3.5); player.queueWaveTable(audioContext, audioContext.destination, drumLowTom, when+b*0, drumLowTom.zones[0].keyRangeLow, 3.5); player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*1, drumSnare.zones[0].keyRangeLow, 3.5); player.queueWaveTable(audioContext, audioContext.destination, drumHighTom, when+b*1, drumHighTom.zones[0].keyRangeLow, 3.5); player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*3, drumSnare.zones[0].keyRangeLow, 3.5); player.queueWaveTable(audioContext, audioContext.destination, drumKick, when+b*3, drumKick.zones[0].keyRangeLow, 3.5); player.queueWaveTable(audioContext, audioContext.destination, drumCrash, when+b*3, drumCrash.zones[0].keyRangeLow, 3.5); } <script src='https://surikov.github.io/webaudiofont/npm/dist/WebAudioFontPlayer.js'></script> <button onclick='badumtss();'>badumtss</button> <button onclick='uhoh();'>uhoh</button> <button onclick='applause();'>applause</button> <br/><a href='https://github.com/surikov/webaudiofont'>More sounds</a>

其他回答

Web音频API是这项工作的正确工具。在加载声音文件和播放它的过程中涉及到一些工作。幸运的是,有很多库可以简化这项工作。出于对声音的兴趣,我还创建了一个名为musquito的库,你也可以查看一下。

目前它只支持衰落的声音效果,我正在做其他的事情,比如3D空间化。

你可以尝试AudioContext,它的支持有限,但它是web音频api工作草案的一部分。如果你打算在未来发布一些东西,这可能是值得的。如果你只会为chrome和Firefox编程,那你就太棒了。

http://robert.ocallahan.org/2011/11/latency-of-html5-sounds.html

http://people.mozilla.org/~roc/audio-latency-repeating.html

对我来说,在Firefox和Chrome中工作正常。

想要停止由你引起的声音,就这么做 var sound = document.getElementById("shot").cloneNode(true); sound.play (); 后来 sound.pause ();

听起来你想要的是多声道的声音。让我们假设你有4个频道(就像在非常老的16位游戏中),我还没有时间玩HTML5音频功能,但你不需要4 <audio>元素,以及用于播放下一个音效的循环吗?你试过吗?会发生什么呢?如果有效:要同时播放更多声音,只需添加更多<audio>元素。

我以前在没有HTML5 <audio>元素的情况下做到了这一点,使用来自http://flash-mp3-player.net/的一个小Flash对象-我写了一个音乐测试(http://webdeavour.appspot.com/),并在用户单击问题按钮时使用它来播放音乐剪辑。一开始,每个问题都有一个播放器,而且可以互相播放,所以我改变了它,只有一个播放器,我指向不同的音乐片段。

Web音频API

编辑:截至2021年12月,Chrome、Firefox、Safari和所有其他主要浏览器(当然不包括IE)基本上都支持Web Audio API。

截至2012年7月,Web Audio API已在Chrome中得到支持,Firefox也至少部分支持,并计划在IOS 6版中添加。

尽管Audio元素足够健壮,可以通过编程方式用于基本任务,但它从未打算为游戏和其他复杂应用程序提供完整的音频支持。它的设计目的是允许在页面中嵌入单个媒体片段,类似于img标签。在游戏中使用it存在很多问题:

定时卡瓦在音频元素中很常见 每个声音实例都需要一个Audio元素 加载事件还不是完全可靠的 没有常用的音量控制,没有淡出,没有过滤器/效果

这里有一些很好的资源来开始使用Web Audio API:

MDN documentaion 从WebAudio文章开始 《FieldRunners WebAudio案例研究》也是一本不错的读物