JavaScript / HTML5中的音效

时间:2009-12-19 19:57:01

标签: javascript html5

我正在使用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;
      };
    });
  }
};

现在我可以从Firebug控制台执行Snd.boom();并播放snd/boom.wav,但我仍然无法多次播放相同的示例。似乎<audio>元素实际上更像是一个流媒体功能,而不是用于播放音效的东西。

是否有一种聪明的方法可以解决这个问题,我很想忘记,最好只使用HTML5和JavaScript?

我还应该提一下,我的测试环境是Ubuntu 9.10上的Firefox 3.5。我尝试过的其他浏览器--Opera,Midori,Chromium,Epiphany--产生了不同的结果。有些人不玩任何东西,有些人会抛出异常。

18 个答案:

答案 0 :(得分:440)

HTML5 Audio个对象

您无需担心<audio>元素。 HTML 5允许您直接访问Audio objects

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。


如果您正在编写游戏或音乐应用(不仅仅是播放器),您还需要使用more advanced Web Audio API,现在是supported by most browsers

答案 1 :(得分:36)

W3C的

WebAudio API

截至2012年7月,Chrome已支持WebAudio API,至少部分受Firefox支持,并且自版本6起计划添加到IOS。

虽然它足够强大,可以编程方式用于基本任务,但音频元素从未打算为游戏等提供完整的音频支持。它旨在允许将单个媒体嵌入到页面中,类似到img标签。尝试将音频标记用于游戏时存在很多问题:

  • 时间单与音频元素相同
  • 每个声音实例都需要一个音频元素
  • 负载事件并非完全可靠,但
  • 没有常见的音量控制,没有褪色,没有滤镜/效果

我使用这篇Getting Started With WebAudio文章开始使用WebAudio API。 FieldRunners WebAudio Case Study也很好读。

答案 2 :(得分:28)

howler.js

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

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}
})

Sound for Games

另一个类似于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的音乐编辑器,效果生成器或视频游戏,这些库中的每一个都值得一看。

答案 3 :(得分: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/, ''));
}

答案 4 :(得分: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");

答案 5 :(得分:4)

查看jai( - &gt; mirror)(javascript音频界面)网站。通过查看来源,他们似乎反复调用play(),他们提到他们的库可能适合在基于HTML5的游戏中使用。

  

您可以触发多个音频事件   同时,可以使用   用于创建Javascript游戏,或   对某些人发表意见   背景音乐

答案 6 :(得分:4)

听起来你想要的是多声道声音。假设您有4个频道(就像真正的16位游戏一样),我还没有玩到HTML5音频功能,但是你不需要4&lt; audio&gt;元素和用于播放下一个音效的循环?你试过吗?怎么了?如果有效:要同时播放更多声音,只需添加更多&lt; audio&gt;元件。

我之前没有使用HTML5&lt; audio&gt;元素,使用来自http://flash-mp3-player.net/的一个小Flash对象 - 我写了一个音乐测验(http://webdeavour.appspot.com/)并用它来播放音乐剪辑,当用户点击问题的按钮时。最初我每个问题都有一个玩家,并且可以在彼此的顶部播放它们,所以我改变它所以只有一个玩家,我指向不同的音乐剪辑。

答案 7 :(得分:3)

这是一个想法。将特定类别声音的所有音频加载到单个音频元素中,其中src数据是连续音频文件中的所有样本(可能需要一些静音,因此您可以捕获并切断样本,并且超时较少下一个样本出血的风险)。然后,寻找样本并在需要时播放。

如果你需要多个这样的游戏,你可以使用相同的src创建一个额外的音频元素,以便它被缓存。现在,你实际上有多个“轨道”。您可以利用自己喜欢的资源分配方案(如Round Robin等)来利用音轨组。

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

答案 8 :(得分:3)

要多次播放相同的样本,不可能做到这样的事情:

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

e是音频元素)

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

答案 9 :(得分: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);     sound.play(); 然后     sound.pause();

答案 10 :(得分:2)

我建议使用SoundJS,这是我帮助开发的库。它允许您编写一个可在任何地方使用的单个代码库,SoundJS会根据需要选择Web音频,html音频或flash音频。

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

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

希望有所帮助。

答案 11 :(得分:1)

使用单个<audio>元素进行多次拍摄是不可能的。您需要为此使用多个元素。

答案 12 :(得分:1)

我在编写音乐盒卡片生成器时遇到了这个问题。从不同的图书馆开始,但每次都有某种故障。正常音频实现的延迟很糟糕,没有多重播放...最终使用lowlag库+ soundmanager:

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

您可以在此处查看实施情况: http://musicbox.grit.it/

我为多个浏览器播放生成了wav + ogg文件。这款音乐盒播放器可以在ipad,iphone,Nexus,mac,pc上运行,对我有用。

答案 13 :(得分:0)

我知道这完全是黑客,但我想我应该在一段时间之前添加这个我放在github上的开源音频库...

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

单击下面的链接后,键入主页行键以播放蓝调riff(同时键入多个键等)。

使用jThump库的示例&gt;&gt; http://davealger.com/apps/jthump/

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

这当然不太理想但是你可以根据创造力来判断这个解决方案(事实上它是开源的,可以在我尝试过的任何浏览器中使用)我希望这让别人至少可以搜索一些想法。

:)

答案 14 :(得分:0)

所选答案将适用于IE以外的所有内容。我写了一个关于如何使它跨浏览器工作的教程= http://www.andy-howard.com/how-to-play-sounds-cross-browser-including-ie/index.html

这是我写的函数;

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");

答案 15 :(得分:0)

您可以随时尝试AudioContext它有限的支持,但它是web audio api工作草案的一部分。如果您计划在将来发布某些内容,那可能是值得的。如果你只是为chrome和Firefox编程,你就是金色的。

答案 16 :(得分: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>

答案 17 :(得分:0)

Web Audio API是适合此工作的工具。加载声音文件并播放它几乎不需要做任何工作。幸运的是,那里有很多可以简化工作的库。对声音感兴趣,我还创建了一个名为musquito的库,您也可以查看一下。

目前它仅支持淡入淡出的声音效果,我正在研究3D空间化等其他事情。