324

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

具体要求很少:

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

我的第一种方法是使用 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——产生了不同的结果。有些什么都不播放,有些抛出异常。

4

18 回答 18

458

HTML5Audio对象

你不需要为<audio>元素而烦恼。HTML 5 允许您直接访问Audio对象

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

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

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


由于 JS 构造函数不支持后备<source>元素,您应该使用

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

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


如果您正在编写游戏或音乐应用程序(不仅仅是播放器),您将需要使用更高级的 Web Audio API,现在大多数浏览器都支持该 API 。

于 2009-12-19T22:37:51.183 回答
39

网络音频 API

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

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

尽管该Audio元素足够健壮,可以以编程方式用于基本任务,但它从未打算为游戏和其他复杂应用程序提供完整的音频支持。它旨在允许将单个媒体嵌入到页面中,类似于img标签。尝试将它用于游戏有很多问题:

  • 时差在Audio元素中很常见
  • Audio每个声音实例都需要一个元素
  • 加载事件还不是完全可靠的
  • 没有常见的音量控制,没有衰减,没有过滤器/效果

以下是开始使用 Web Audio API 的一些很好的资源:

于 2012-07-18T21:39:26.047 回答
35

吼叫.js

对于游戏创作,最好的解决方案之一是使用一个库来解决我们在为 Web 编写代码时面临的许多问题,例如howler.js。howler.js 将伟大的(但低级的)Web Audio API抽象为一个易于使用的框架。如果 Web 音频 API 不可用,它将尝试回退到HTML5 音频元素。

var sound = new Howl({
  urls: ['sound.mp3', 'sound.ogg']
}).play();
// it also provides calls for spatial/3d audio effects (most browsers)
sound.pos3d(0.1,0.3,0.5);

wad.js

另一个很棒的库是wad.js,它对于生成合成音频特别有用,例如音乐和效果。例如:

var saw = new Wad({source : 'sawtooth'})
saw.play({
    volume  : 0.8,
    wait    : 0,     // Time in seconds between calling play() and actually triggering the note.
    loop    : false, // This overrides the value for loop on the constructor, if it was set. 
    pitch   : 'A4',  // A4 is 440 hertz.
    label   : 'A',   // A label that identifies this note.
    env     : {hold : 9001},
    panning : [1, -1, 10],
    filter  : {frequency : 900},
    delay   : {delayTime : .8}
})

游戏音效

另一个类似于 Wad.js 的库是“ Sound for Games ”,它更专注于效果制作,同时通过相对独特(也许感觉更简洁)的 API 提供一组类似的功能:

function shootSound() {
  soundEffect(
    1046.5,           //frequency
    0,                //attack
    0.3,              //decay
    "sawtooth",       //waveform
    1,                //Volume
    -0.8,             //pan
    0,                //wait before playing
    1200,             //pitch bend amount
    false,            //reverse bend
    0,                //random pitch range
    25,               //dissonance
    [0.2, 0.2, 2000], //echo array: [delay, feedback, filter]
    undefined         //reverb array: [duration, decay, reverse?]
  );
}

概括

这些库中的每一个都值得一看,无论您是需要播放单个声音文件,还是创建自己的基于 html 的音乐编辑器、效果生成器或视频游戏。

于 2013-10-23T15:06:30.217 回答
9

在某些情况下,您可能还想使用它来检测 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/, ''));
}
于 2011-01-01T14:07:35.397 回答
5

这是一种可以同时播放相同声音的方法。与预加载器结合使用,一切就绪。这至少适用于 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");
于 2012-12-24T14:04:31.523 回答
4

要多次播放相同的样本,是否可以执行以下操作:

e.pause(); // Perhaps optional
e.currentTime = 0;
e.play();

e是音频元素)

也许我完全误解了你的问题,你想让音效同时播放多次吗?那么这是完全错误的。

于 2009-12-19T20:19:58.633 回答
4

看看jai (-> mirror ) (javascript 音频接口) 站点。从他们的源代码来看,他们似乎在play()反复调用,他们提到他们的库可能适合在基于 HTML5 的游戏中使用。

您可以同时触发多个音频事件,这可用于创建 Javascript 游戏,或在某些背景音乐中发出声音

于 2009-12-19T20:25:16.533 回答
4

听起来你想要的是多声道声音。假设您有 4 个通道(就像在真正的 16 位游戏中一样),我还没有开始使用 HTML5 音频功能,但您不只需要 4 个 <audio> 元素,然后循环使用播放下一个音效?你试过吗?发生什么了?如果可行:要同时播放更多声音,只需添加更多 <audio> 元素。

我之前在没有 HTML5 <audio> 元素的情况下使用http://flash-mp3-player.net/中的一个小 Flash 对象完成了此操作- 我写了一个音乐测验 ( http://webdeavour.appspot.com/ ) 和当用户单击问题的按钮时,用它来播放音乐片段。最初我每个问题都有一个播放器,并且可以将它们重叠播放,所以我将其更改为只有一个播放器,我指向不同的音乐片段。

于 2009-12-19T20:55:02.010 回答
3

这是一个想法。将某一类声音的所有音频加载到一个单独的音频元素中,其中 src 数据是连续音频文件中的所有样本(可能需要一些静音,以便您可以在超时的情况下捕获和剪切样本出血到下一个样本的风险)。然后,寻找样本并在需要时播放。

如果您需要多个其中一个来播放,您可以创建一个具有相同 src 的附加音频元素,以便将其缓存。现在,您实际上拥有多个“轨道”。您可以将轨道组与您最喜欢的资源分配方案(如循环等)一起使用。

您还可以指定其他选项,例如在该资源可用时将声音排入轨道以播放或剪切当前播放的样本。

于 2011-04-04T05:21:34.853 回答
2

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); 声音.play(); 后来 sound.pause();

于 2012-01-11T23:58:17.743 回答
2

我会推荐使用SoundJS,一个我帮助开发的库。它允许您编写一个适用于任何地方的单一代码库,SoundJS 可以根据需要选择 Web 音频、html 音频或 flash 音频。

它可以让你做你想做的所有事情:

  • 播放和混合多种声音,
  • 多次播放相同的样本,可能会重叠播放
  • 在任何时候中断样本的播放
  • 播放包含(取决于浏览器支持)的 WAV 文件

希望有帮助。

于 2013-10-03T18:21:14.530 回答
1

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

于 2009-12-19T23:04:48.277 回答
1

我在编写音乐盒卡生成器时遇到了这个问题。从不同的库开始,但每次都以某种方式出现故障。正常音频实现的滞后很糟糕,没有多次播放......最终使用了lowlag库+声音管理器:

http://lowlag.alienbill.com/http://www.schillmania.com/projects/soundmanager2/

你可以在这里查看实现:http: //musicbox.grit.it/

我为多浏览器播放生成了 wav + ogg 文件。这款音乐盒播放器可在 ipad、iphone、Nexus、mac、pc 上响应...适合我。

于 2014-04-01T06:24:47.383 回答
0

我知道这完全是 hack,但我认为我应该添加我不久前放在 github 上的这个示例开源音频库......

https://github.com/run-time/jThump

单击下面的链接后,在主行键上键入以播放布鲁斯即兴演奏(也可以同时键入多个键等)

使用 jThump 库的示例 >> http://davealger.com/apps/jthump/

它基本上通过制作不可见<iframe>的元素来加载播放声音 onReady() 的页面。

这当然不是理想的,但是您可以仅基于创造力+1这个解决方案(事实上它是开源的并且可以在我尝试过的任何浏览器中工作)我希望这至少能给其他人搜索一些想法。

:)

于 2013-03-28T23:25:49.090 回答
0

选定的答案将适用于除 IE 之外的所有内容。我写了一篇关于如何让它跨浏览器工作的教程。这是我写的函数:

function playSomeSounds(soundPath) {
    var trident = !!navigator.userAgent.match(/Trident\/7.0/);
    var net = !!navigator.userAgent.match(/.NET4.0E/);
    var IE11 = trident && net
    var IEold = (navigator.userAgent.match(/MSIE/i) ? true : false);
    if (IE11 || IEold) {
        document.all.sound.src = soundPath;
    } else {
        var snd = new Audio(soundPath); // buffers automatically when created
        snd.play();
    }
}

您还需要将以下标记添加到 html 页面:

<bgsound id="sound">

最后,您可以调用该函数并简单地通过此处的路径:

playSomeSounds("sounds/welcome.wav");
于 2014-05-13T08:01:27.337 回答
0

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

于 2016-08-29T03:23:52.540 回答
0

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>

于 2019-03-29T06:01:53.537 回答
0

Web Audio API 是这项工作的正确工具。加载声音文件和播放它涉及的工作很少。幸运的是,有很多图书馆可以简化这项工作。由于对声音感兴趣,我还创建了一个名为musquito的库,您也可以查看它。

目前它只支持淡入淡出的音效,我正在研究其他的东西,比如 3D 空间化。

于 2019-04-11T07:30:04.543 回答