[英]Sound effects in JavaScript / HTML5
我正在使用 HTML5 编写游戏; 我现在遇到的障碍是如何播放音效。
具体要求很少:
我的第一种方法是使用 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——产生了不同的结果。 有些什么都不玩,有些抛出异常。
Audio
对象你不需要理会<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 ,现在大多数浏览器都支持它。
截至 2012 年 7 月,Chrome 现在支持WebAudio API ,Firefox 至少部分支持,并计划从第 6 版开始添加到 IOS。
尽管它足够健壮,可以以编程方式用于基本任务,但 Audio 元素从未打算为游戏等提供完整的音频支持。它旨在允许将单个媒体嵌入页面中,类似于 img标记。 尝试在游戏中使用 Audio 标签有很多问题:
我使用WebAudio 入门这篇文章开始使用 WebAudio API。 FieldRunners WebAudio Case Study也是一本很好的读物。
对于游戏创作,最好的解决方案之一是使用一个库来解决我们在为 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 ,它对于制作合成音频特别有用,例如音乐和效果。 例如:
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 的音乐编辑器、效果生成器或视频游戏。
在某些情况下,您可能还想使用它来检测 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");
要多次播放相同的样本,难道不可能做这样的事情:
e.pause(); // Perhaps optional
e.currentTime = 0;
e.play();
( e
是音频元素)
可能我完全误解了你的问题,你想让音效同时播放多次吗? 那么这是完全错误的。
听起来您想要的是多声道声音。 假设您有 4 个频道(就像在非常老的 16 位游戏上一样),我还没有开始玩 HTML5 音频功能,但是您是否只需要 4 个 <audio> 元素,并循环使用播放下一个音效? 你试过吗? 会发生什么? 如果有效:要同时播放更多声音,只需添加更多 <audio> 元素。
我之前在没有 HTML5 <audio> 元素的情况下使用了http://flash-mp3-player.net/ 中的一个小 Flash 对象完成了这项工作 - 我写了一个音乐测验( http://webdeavour.appspot.com/ )和当用户单击问题按钮时,用它来播放音乐片段。 最初我每个问题有一个播放器,并且可以将它们重叠播放,所以我改变了它,所以只有一个播放器,我指向不同的音乐片段。
这是一个想法。 将某一类声音的所有音频加载到单个单独的音频元素中,其中 src 数据是连续音频文件中的所有样本(可能需要一些静音,以便您可以在超时的情况下捕捉和剪切样本,而更少流到下一个样本的风险)。 然后,寻找样本并在需要时播放。
如果您需要播放多个音频元素,您可以使用相同的 src 创建一个额外的音频元素,以便缓存它。 现在,您实际上拥有多个“轨道”。 您可以将轨道组与您最喜欢的资源分配方案(如循环等)一起使用。
您还可以指定其他选项,例如在该资源可用或剪切当前播放的样本时将声音排队到轨道中播放。
我建议使用SoundJS ,这是我帮助开发的库。 它允许您编写一个适用于任何地方的单一代码库,SoundJS 可以根据需要选择 web 音频、html 音频或 flash 音频。
它会让你做你想做的所有事情:
希望有帮助。
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.pause();
不可能使用单个<audio>
元素进行多镜头播放。 您需要为此使用多个元素。
我在为音乐盒卡生成器编程时遇到了这个问题。 从不同的库开始,但每次都会以某种方式出现故障。 正常音频实现的延迟很糟糕,没有多次播放......最终最终使用了lowlag library + soundmanager:
http://lowlag.alienbill.com/和http://www.schillmania.com/projects/soundmanager2/
你可以在这里查看实现: http : //musicbox.grit.it/
我为多浏览器播放生成了 wav + ogg 文件。 这个音乐盒播放器在 ipad、iphone、Nexus、mac、pc 上工作响应迅速,对我有用。
我知道这是一个彻头彻尾的黑客,但我想我应该添加这个示例开源音频库我前一段时间放在github上......
https://github.com/run-time/jThump
单击下面的链接后,在主行键上键入以播放蓝调即兴演奏(也可以同时键入多个键等)
使用 jThump 库的示例 >> http://davealger.com/apps/jthump/
它基本上通过制作不可见的<iframe>
元素来加载页面,该页面在 onReady() 中播放声音。
这当然不是理想的,但是您可以仅根据创造力来+1 此解决方案(并且它是开源的并且可以在我尝试过的任何浏览器中运行)我希望这至少可以让其他人搜索一些想法。
:)
选定的答案将适用于除 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");
您可以随时尝试AudioContext
它的支持有限,但它是网络音频 api工作草案的一部分。 如果你打算在未来发布一些东西,这可能是值得的。 如果你只为 chrome 和 Firefox 编程,那你就是黄金。
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 Audio API 是这项工作的正确工具。 加载声音文件并播放它涉及的工作很少。 幸运的是,有很多库可以简化工作。 由于对声音感兴趣,我还创建了一个名为musquito的库,您也可以查看它。
目前它只支持淡入淡出的音效,我正在做其他事情,比如 3D 空间化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.