首页 文章

JavaScript / HTML5中的音效

提问于
浏览
305

我正在使用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--产生了不同的结果 . 有些人不玩任何东西,有些人会抛出异常 .

16 回答

  • 34

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

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

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

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

  • 4

    我知道这是一个彻头彻尾的黑客,但我想我应该添加这个我在github上放置的开源音频库...

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

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

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

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

    This is certainly not ideal 但你可以1这个基于创造力的解决方案(事实上它是开源的,并且可以在我尝试过的任何浏览器中运行)我希望这能让其他人至少搜索一些想法 .

    :)

  • 2

    HTML5音频对象

    你不需要打扰 <audio> 元素 . HTML 5允许您直接访问Audio objects

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

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

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


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

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

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


    如果你想're writing a game or a music app (more than just a player), you'想要使用more advanced Web Audio API,现在是supported by most browsers .

  • 5

    W3C的WebAudio API

    截至2012年7月,Chrome现已支持WebAudio API,至少部分支持Firefox,预计将从版本6开始添加到IOS .

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

    • 定时单对于Audio元素很常见

    • 每个声音实例都需要一个Audio元素

    • 负载事件尚不完全可靠

    • 没有常见的音量控制,没有褪色,没有滤镜/效果

    我使用这篇Getting Started With WebAudio文章开始使用WebAudio API . FieldRunners WebAudio Case Study也是一本很好的读物 .

  • 27

    howler.js

    对于游戏创作,最好的解决方案之一是使用一个库来解决我们在为Web编写代码时遇到的许多问题,例如howler.js . howler.js将伟大的(但是低级的)_939243抽象成一个易于使用的框架 . 如果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}
    })
    

    游戏之声

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

  • 0

    在某些情况下,您可能还希望使用它来检测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/, ''));
    }
    
  • 1

    这是一种可以同时播放相同声音的方法 . 与preloader结合,你就完成了 . 这至少适用于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");
    
  • 3

    听起来你想要的是多声道声音 . 让我们假设您有4个 Channels (就像真正的16位游戏一样),我还没有玩到HTML5音频功能,但是你不需要4个<audio>元素和循环使用发挥下一个音效?你试过吗?怎么了?如果有效:要同时播放更多声音,只需添加更多<audio>元素即可 .

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

  • 2

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

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

  • 4

    要多次播放相同的样本,是不是可以这样做:

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

    e 是音频元素)

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

  • 0

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

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

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

  • 0

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

  • 3

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

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

    • 播放并混合多个声音,

    • 多次播放相同的样本,可能重叠播放

    • 在任何时候中断播放样本

    • 播放包含的WAV文件(取决于浏览器支持)

    希望有所帮助 .

  • 435

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

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

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

相关问题