Browse files

first commit

  • Loading branch information...
0 parents commit 60a11237e794dcd3d9b17340bd8616dbc0f87c9a @tommoor committed Mar 19, 2011
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Tom Moor
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
93 Readme.md
@@ -0,0 +1,93 @@
+# Zap! HTML 5 Game Audio
+
+Zap! is an audio manager for html 5 applications with a focus on real time uses such as games.
+
+It provides a common interface that works across the individual browser quirks and shortcomings such as multiple channels, looping and callbacks.
+
+## Documentation
+
+### init(options)
+
+Init should be run before anything else to setup configuration and create dom elements
+
+__Arguments__
+* options - Optional configuration object
+
+__Example__
+
+ Zap.init({
+ console: true,
+ complete: function(){
+ // callback for all sounds finished loading
+ },
+ error: function(ref){
+ // callback when a sound fails to load
+ },
+ update: function(percent){
+ // callback when a sound finishes loading
+ }
+ });
+
+
+
+### addSound(ref, sources, channels, time)
+
+Add a sound to be loaded, this method can be chained.
+
+__Arguments__
+* refs - A unique string reference for this sound
+* sources - An array of possible sources in the order they should be checked
+* channels - The maximum number of channels available for this sample
+* time - Time to wait until giving up on the sound loading
+
+__Example__
+
+ Zap.addSound('beat', ['beat.mp3', 'beat.ogg', 'beat.wav'])
+ .addSound('laser', ['shoot.mp3', 'shoot.ogg'], 5);
+
+
+### play(ref, volume, loops, callback)
+
+Play a sound by reference, this method can be chained.
+
+__Arguments__
+* ref - The sound reference
+* volume - A number between 0-1
+* loops - The number of times the sample should loop
+* callback - An optional callback to be run once the sample finishes
+
+__Example__
+
+ Zap.play('mysound', 1, 10, function(){
+
+ alert('My sound has finished');
+ });
+
+### stop(ref)
+
+Stop a sound by reference, this method can be chained.
+
+__Arguments__
+* ref - The sound reference
+
+__Example__
+
+ Zap.stop('mysound');
+
+### stopAllSounds
+
+Stop every loaded sound
+
+__Example__
+
+ Zap.stopAllSounds();
+
+
+## Download
+
+Releases are available for download from
+[GitHub](http://github.com/tommoor/zap/downloads).
+
+__Development:__ [zap.js](https://github.com/tommoor/zap/raw/master/zap.js)
+
+__Production:__ [zap.min.js](https://github.com/tommoor/zap/raw/master/zap.min.js)
238 Zap.js
@@ -0,0 +1,238 @@
+/**
+ * Zap! - HTML5 Sound Manager
+ * Copyright (c) 2011 Tom Moor
+ * MIT Licensed
+ */
+
+var Zap = (function() {
+
+ var exports = {},
+ sounds = {},
+ loaded = 0,
+ timeout = 6*1000,
+ self = this,
+ options = {
+ container: 'sounds',
+ console: true,
+ complete: function(){},
+ error: function(){},
+ update: function(){}
+ };
+
+
+ /**
+ * Initalise zap object, optionally include configs
+ *
+ * @param {Object} config object
+ * @return {Zap} return itself to allow chaining
+
+ */
+
+ exports.init = function(opt){
+
+ options = $.extend(options, opt);
+ $('<div/>', {'id': options.container}).appendTo('body');
+
+ return this;
+ }
+
+
+ /**
+ * Add a sound to be played later
+ *
+ * @param {String} ref
+ * @param {Array} sources
+ * @param {Integer} maximum channels
+ * @param {Integer} maximum ms loading before considered to have timed out
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.addSound = function(ref, sources, channels, time){
+
+ var channels = channels || 1;
+ var element = ref;
+
+ // create reference to sound channels
+ sounds[ref] = {
+ asset: '#' + ref,
+ loaded: false,
+ failed: false,
+ duration: 0,
+ channels: channels,
+ channel: 0
+ }
+
+ // if a sound fails to load for any reason it shouldnt stop complete callback
+ var loadTimeout = setTimeout(function(){
+
+ log('Zap: sound failed to load: ' + ref);
+ sounds[ref].failed = true;
+ soundLoaded();
+ options.error(ref);
+
+ }, time || timeout);
+
+ // create new wrapper to categorise channels
+ $('<div/>', {
+ 'id': ref
+ }).appendTo('#' + options.container);
+
+ var c;
+ // create an audio element for each channel
+ while(channels--){
+
+ c = 'sound-' + element + '-' + channels;
+
+ // create new channel
+ $('<audio/>', {
+ 'id': c,
+ 'preload': 'auto',
+ 'autobuffer': true
+ }).appendTo('#' + ref);
+
+ // bind event handlers
+ $('#' + c).bind('canplaythrough', function(){
+ clearTimeout(loadTimeout);
+ sounds[ref].loaded = true;
+ sounds[ref].duration = $(this).get(0).duration*1000;
+ soundLoaded();
+ });
+
+ // add sound sources
+ for(var s in sources){
+ $('<source/>', {
+ 'src': sources[s]
+ }).appendTo('#' + c);
+ }
+ }
+
+ log('Zap: sound added ' + ref);
+
+ return this;
+ }
+
+
+ /**
+ * Play a sound by reference
+ *
+ * @param {String} ref
+ * @param {Float} vol
+ * @param {Integer} loops
+ * @param {Function} callback
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.play = function(ref, vol, loops, c){
+
+ if(! sounds[ref].loaded){
+ log('Zap: sound with reference "' + ref + '" is not loaded');
+ return false;
+ }
+ var callback = c || function(){};
+ var volume = vol || 1;
+ var sound = sounds[ref];
+ var element = $('#sounds #' + ref + ' audio').get(sound.channel);
+
+ log('Zap: playing "' + ref + '" on channel ' + (sound.channel+1));
+
+ // circulate through the available channels
+ if(sound.channel++ >= sound.channels-1){
+ sound.channel = 0;
+ }
+
+ // play one shot
+ element.volume = volume;
+ element.play();
+
+ if(loops){
+ // loop, if requested
+ var count = 0;
+ var loopInterval = setInterval(function(){
+
+ if(++count < loops){
+ Zap.play(ref, vol);
+ return true;
+ }
+ clearInterval(loopInterval);
+ callback();
+ }, sound.duration);
+
+ } else {
+ // callback, if provided
+ setTimeout(callback, sound.duration);
+ }
+
+ return this;
+ }
+
+
+ /**
+ * Stop a sound by reference
+ *
+ * @param {String} ref
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.stop = function(ref){
+
+ // find all channels this sound could
+ // be playing on and stop each one individually.
+ var element = $('#sounds #' + ref + ' audio').each(function(){
+
+ $(this).get(0).pause();
+ });
+
+ return this;
+ }
+
+
+ /**
+ * Stop every sound that has been loaded
+ *
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.stopAllSounds = function(){
+
+ $('#sounds audio').each(function(){
+
+ $(this).get(0).pause();
+ });
+
+ return this;
+ }
+
+
+ var getChannelCount = function(){
+
+ var c = 0;
+ for (var i in sounds) {
+ c += sounds[i].channels;
+ }
+
+ return c;
+ }
+
+
+ var getPercentageLoaded = function(){
+ return (getChannelCount() / loaded )*100;
+ }
+
+
+ var soundLoaded = function(){
+ loaded++;
+ options.update( getPercentageLoaded() );
+
+ if(loaded == getChannelCount()) options.complete();
+ }
+
+
+ var log = function(){
+ if(window.console && options.console){
+ window.console.log( Array.prototype.slice.call(arguments) );
+ }
+ }
+
+ return exports;
+})();
+
BIN examples/beat.mp3
Binary file not shown.
BIN examples/beat.ogg
Binary file not shown.
25 examples/click.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Zap!</title>
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
+ <script src="../Zap.js"></script>
+ <script>
+ $(function(){
+ Zap.init({
+ complete: function(){
+ $(window).click(function(){
+
+ Zap.play('laser');
+ });
+ }
+ });
+ Zap.addSound('laser', ['zap.mp3', 'zap.ogg'], 5);
+ });
+ </script>
+ </head>
+ <body>
+ <h1>Zap! Action Example</h1>
+ <p>Turn your speakers on and click the page.</p>
+ </body>
+</html>
26 examples/loop.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Zap!</title>
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
+ <script src="../Zap.js"></script>
+ <script>
+ $(function(){
+ Zap.init({
+ complete: function(){
+ Zap.play('beat', 1, 5, function(){
+
+ alert('loop finished!');
+ });
+ }
+ });
+
+ Zap.addSound('beat', ['beat.mp3', 'beat.ogg'], 1);
+ });
+ </script>
+ </head>
+ <body>
+ <h1>Zap! Looping Example</h1>
+ <p>Turn your speakers on and view the source.</p>
+ </body>
+</html>
BIN examples/zap.mp3
Binary file not shown.
BIN examples/zap.ogg
Binary file not shown.

0 comments on commit 60a1123

Please sign in to comment.