{"id":4177,"date":"2018-09-18T15:39:07","date_gmt":"2018-09-18T15:39:07","guid":{"rendered":"http:\/\/www.drmop.com\/?p=4177"},"modified":"2018-09-18T15:39:07","modified_gmt":"2018-09-18T15:39:07","slug":"simple-web-audio-wrapper","status":"publish","type":"post","link":"http:\/\/www.drmop.com\/index.php\/2018\/09\/18\/simple-web-audio-wrapper\/","title":{"rendered":"Simple Web Audio Wrapper"},"content":{"rendered":"<p>Seen this question asked numerous times, how to set up and use the Web Audio API, so I ripped some code out of my engine Booty5 and slimmed it down a bit and here it is, I have also pushed it to <a href=\"https:\/\/github.com\/mrmop\/simplewebaudio\">Github here<\/a>.<\/p>\n<p>[sourcecode language=&#8221;js&#8221;]<br \/>\n\/**<br \/>\n * A Sound represents a sound effect object and can be used to play back audio<br \/>\n *<br \/>\n * Generally a sound should be added to either a {@link b5.Scene} or the global {@link b5.App}&#8217;s resources so that it can be managed by them.<br \/>\n *<br \/>\n * Example showing how to load and play a sound effect<br \/>\n *<br \/>\n *      var sound = new b5.Sound(&quot;explosion&quot;, &quot;sounds\/explosion.mp3&quot;, true);<br \/>\n *      var instance = sound.play();<br \/>\n *<br \/>\n * For a complete overview of Resources see {@link http:\/\/booty5.com\/html5-game-engine\/booty5-html5-game-engine-introduction\/resources-the-stuff-that-games-are-made-of\/ Booty5 Resources Overview}<br \/>\n *<br \/>\n * @class b5.Sound<br \/>\n * @constructor<br \/>\n * @returns {b5.Sound}                      The created sound<br \/>\n * @param name {string}                     Name of sound resource<br \/>\n * @param location {string}                 The sound file location<br \/>\n *<br \/>\n * @property {b5.App|b5.Scene}          parent          &#8211; Parent resource manager (internal)<br \/>\n * @property {object}                   snd             &#8211; Sound instance (re-usable sound only) (internal). For Web Audio stores a {source:AudioBufferSourceNode, gain:GainNode} object for auto play sounds<br \/>\n * @property {object}                   buffer          &#8211; AudioBufferSourceNode containing decoded audio data (Web Audio only)<br \/>\n * @property {string}                   name            &#8211; Name of this sound resource<br \/>\n * @property {string}                   location        &#8211; The location of the sound file that is used to create the audio object<br \/>\n * @property {boolean}                  loop            &#8211; If set to true then sound will be looped<br \/>\n * @property {boolean}                  preload         &#8211; If set to true then this sound will be preloaded<br \/>\n * @property {boolean}                  auto_play         &#8211; If set to true then this sound will be preloaded<br \/>\n * @property {boolean}                  loaded          &#8211; If true then this resource has finished loading<br \/>\n *\/<\/p>\n<p>var loadFile = function(filename, blocking, callback, binary)<br \/>\n{<br \/>\n    var req = new XMLHttpRequest();<br \/>\n    req.open(&quot;GET&quot;, filename, !blocking);<br \/>\n    req.overrideMimeType(&quot;application\/json&quot;);<br \/>\n    if (binary)<br \/>\n        req.responseType = &quot;arraybuffer&quot;;<br \/>\n    if (!blocking)<br \/>\n    {<br \/>\n        req.onreadystatechange = function()<br \/>\n        {<br \/>\n            if (req.readyState === 4)<br \/>\n            {<br \/>\n                if (req.status === 200 || req.status === 0) \/\/ 0 for node-webkit<br \/>\n                {<br \/>\n                    if (binary)<br \/>\n                        callback(req.response);<br \/>\n                    else<br \/>\n                        callback(req.responseText);<br \/>\n                }<br \/>\n                else<br \/>\n                    callback(null);<br \/>\n            }<br \/>\n        };<br \/>\n    }<br \/>\n    try<br \/>\n    {<br \/>\n        req.send();<br \/>\n    }<br \/>\n    catch(e)<br \/>\n    {<br \/>\n        return false;<br \/>\n    }<\/p>\n<p>    if (blocking)<br \/>\n    {<br \/>\n        if (req.status === 200)<br \/>\n        {<br \/>\n            if (binary)<br \/>\n                callback(req.response);<br \/>\n            else<br \/>\n                callback(req.responseText);<br \/>\n        }<br \/>\n        else<br \/>\n            callback(null);<br \/>\n    }<\/p>\n<p>    return true;<br \/>\n};<\/p>\n<p>b5.Sound = function(name, location)<br \/>\n{<br \/>\n    \/\/ internal variables<br \/>\n    this.parent = null;                 \/\/ Parent container<br \/>\n    this.snd = null;                    \/\/ Sound instance (re-usable sound only). For Web Audio stores a {AudioBufferSourceNode, GainNode } object for auto play sounds<br \/>\n    this.buffer = null;                 \/\/ AudioBufferSourceNode containing decoded audio data (Web Audio only)<\/p>\n<p>    \/\/ Public variables<br \/>\n    this.name = name;\t\t\t\t\t\/\/ The sound name<br \/>\n    this.location = location;\t\t\t\/\/ Location of the sound<br \/>\n    this.loop = false;                  \/\/ If set to true the this sound will replay continuously<br \/>\n    this.preload = false;               \/\/ Set to true to preload sound<br \/>\n    this.loaded = false;                \/\/ Set to true once audio cam be played<br \/>\n    this.auto_play = false;             \/\/ Set to true to auto play sound when loaded<br \/>\n    this.load_retry = 0;<br \/>\n};<\/p>\n<p>\/**<br \/>\n * AudioContext used by Web Audio API<br \/>\n * @type {object}<br \/>\n *\/<br \/>\nb5.Sound.context = null;<br \/>\nb5.Sound.muted = false;<\/p>\n<p>\/**<br \/>\n * Initialises the sound system<br \/>\n * @parm app {b5.App}   The App that will manage the audio engine<br \/>\n * @returns {boolean}   true for success or false if error<br \/>\n *\/<br \/>\nb5.Sound.init = function(app)<br \/>\n{<br \/>\n    if (app.use_web_audio)<br \/>\n    {<br \/>\n        try<br \/>\n        {<br \/>\n            window.AudioContext = window.AudioContext || window.webkitAudioContext;<br \/>\n            if (window.AudioContext === undefined)<br \/>\n                return false;<br \/>\n            b5.Sound.context = new AudioContext();<br \/>\n        }<br \/>\n        catch(e)<br \/>\n        {<br \/>\n            return false;<br \/>\n        }<br \/>\n        return true;<br \/>\n    }<br \/>\n    return false;<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Loads the sound<br \/>\n *\/<br \/>\nb5.Sound.prototype.load = function(force)<br \/>\n{<br \/>\n    var debug = b5.app.debug;<br \/>\n    \/\/var snd;<br \/>\n    var that = this;<br \/>\n    var filename = this.location;<br \/>\n    var auto_play = this.auto_play;<br \/>\n    if (!loadFile(filename, false, function(data) {<br \/>\n        if (data !== null)<br \/>\n        {<br \/>\n            b5.Sound.context.decodeAudioData(data, function(buffer) {<br \/>\n                that.buffer = buffer;<br \/>\n                if (auto_play)<br \/>\n                    that.play(force);<br \/>\n            }, function(e)<br \/>\n            {<br \/>\n                console.log(e)<br \/>\n            });<br \/>\n        }<br \/>\n        else<br \/>\n        {<br \/>\n            that.load_retry++;<br \/>\n            if (that.load_retry &lt; 3)<br \/>\n                that.load();<br \/>\n        }<br \/>\n    }, true))<br \/>\n    {<br \/>\n        that.load_retry++;<br \/>\n        if (that.load_retry &lt; 3)<br \/>\n            that.load();<br \/>\n    }<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Starts playback of the sound<br \/>\n * @returns {object} An Audio object representing the playing sound or a {source, gain} object if using Web Audio API<br \/>\n *\/<br \/>\nb5.Sound.prototype.play = function(force)<br \/>\n{<br \/>\n    if (force != true &amp;&amp; b5.Sound.muted)<br \/>\n        return null;<br \/>\n    if (this.buffer === null)<br \/>\n        return null;<br \/>\n    var context = b5.Sound.context;<br \/>\n    var source = context.createBufferSource();<br \/>\n    var gain = context.createGain();<br \/>\n    source.buffer = this.buffer;<br \/>\n    source.loop = this.loop;<br \/>\n    source.connect(gain);<br \/>\n    gain.connect(context.destination);<br \/>\n    gain.gain.value = 1;<br \/>\n    source.start(0);<br \/>\n    if (this.auto_play)<br \/>\n        this.snd = { source: source, gain: gain };<br \/>\n    return { source: source, gain: gain };<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Stops playback of thr sound (re-usable sound only)<br \/>\n *\/<br \/>\nb5.Sound.prototype.stop = function()<br \/>\n{<br \/>\n    var snd = this.snd;<br \/>\n    if (snd === null || snd === undefined)<br \/>\n        return;<br \/>\n    snd = snd.source;<br \/>\n    snd.stop();<br \/>\n};<br \/>\n[\/sourcecode]<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Seen this question asked numerous times, how to set up and use the Web Audio API, so I ripped some code out of my engine Booty5 and slimmed it down a bit and here it is, I have also pushed it to Github here. [sourcecode language=&#8221;js&#8221;] \/** * A Sound represents a sound effect object [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[672,120,3,623],"tags":[606],"class_list":["post-4177","post","type-post","status-publish","format-standard","hentry","category-instant-games","category-javascript-programming","category-programming","category-web-development-2","tag-web-audio-api"],"_links":{"self":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/4177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/comments?post=4177"}],"version-history":[{"count":4,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/4177\/revisions"}],"predecessor-version":[{"id":4181,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/4177\/revisions\/4181"}],"wp:attachment":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/media?parent=4177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/categories?post=4177"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/tags?post=4177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}