我使用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——产生了不同的结果。有些不播放任何内容,有些则抛出异常。


当前回答

在某些情况下,你可能也想用它来检测HTML 5音频:

http://diveintohtml5.ep.io/everything.html

HTML 5 JS检测功能

function supportsAudio()
{
    var a = document.createElement('audio'); 
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}

其他回答

不可能使用单个<audio>元素进行多镜头播放。为此需要使用多个元素。

HTML5音频对象

您不需要为<audio>元素而烦恼。HTML 5让你直接访问音频对象:

var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();

在当前版本的规范中不支持混合。

要多次播放相同的声音,请创建Audio对象的多个实例。你也可以设置snd。在对象播放结束后,currentTime=0。


由于JS构造函数不支持回退<源>元素,您应该使用

(new Audio()).canPlayType("audio/ogg; codecs=vorbis")

测试浏览器是否支持Ogg Vorbis。


如果你正在编写一个游戏或音乐应用程序(而不仅仅是一个播放器),你会想要使用更高级的Web Audio API,现在大多数浏览器都支持它。

在某些情况下,你可能也想用它来检测HTML 5音频:

http://diveintohtml5.ep.io/everything.html

HTML 5 JS检测功能

function supportsAudio()
{
    var a = document.createElement('audio'); 
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}

这里有一种方法可以同时播放相同的声音。结合预加载器,你就万事俱备了。这至少适用于Firefox 17.0.1,还没有在其他任何东西上测试过。

// collection of sounds that are playing
var playing={};
// collection of sounds
var sounds={step:"knock.ogg",throw:"swing.ogg"};

// function that is used to play sounds
function player(x)
{
    var a,b;
    b=new Date();
    a=x+b.getTime();
    playing[a]=new Audio(sounds[x]);
    // with this we prevent playing-object from becoming a memory-monster:
    playing[a].onended=function(){delete playing[a]};
    playing[a].play();
}

将此绑定到键盘键,并享受:

player("step");

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

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