text: // ----------------------------------------------------------------------------
  // Buzz, a Javascript HTML5 Audio library
  // Licensed under the MIT license.
  // http://buzz.jaysalvat.com/
  // ----------------------------------------------------------------------------
  // Copyright (C) Jay Salvat
  // http://jaysalvat.com/
  // ----------------------------------------------------------------------------
  /* jshint browser: true, node: true */
  /* global define */
  
  (function (context, factory) {
      "use strict";
  
      if (typeof module !== 'undefined' && module.exports) {
          module.exports = factory();
      } else if (typeof define === 'function' && define.amd) {
          define([], factory);
      } else {
          context.buzz = factory();
      }
  })(this, function () {
      "use strict";
  
      var AudioContext = window.AudioContext || window.webkitAudioContext;
  
      var buzz = {
          defaults: {
              autoplay: false,
              crossOrigin: null,
              duration: 5000,
              formats: [],
              loop: false,
              placeholder: '--',
              preload: 'metadata',
              volume: 80,
              webAudioApi: false,
              document: window.document // iframe support
          },
          types: {
              'mp3': 'audio/mpeg',
              'ogg': 'audio/ogg',
              'wav': 'audio/wav',
              'aac': 'audio/aac',
              'm4a': 'audio/x-m4a'
          },
          sounds: [],
          el: document.createElement('audio'),
  
          getAudioContext: function() {
              if (this.audioCtx === undefined) {
                  try {
                      this.audioCtx = AudioContext ? new AudioContext() : null;
                  } catch (e) {
                      // There is a limit to how many contexts you can have, so fall back in case of errors constructing it
                      this.audioCtx = null;
                  }
              }
  
              return this.audioCtx;
          },
  
          sound: function (src, options) {
              options = options || {};
  
              var doc = options.document || buzz.defaults.document;
  
              var pid = 0,
                  events = [],
                  eventsOnce = {},
                  supported = buzz.isSupported();
  
              // publics
              this.load = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.load();
  
                  return this;
              };
  
              this.play = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.play();
  
                  return this;
              };
  
              this.togglePlay = function () {
                  if (!supported) {
                      return this;
                  }
  
                  if (this.sound.paused) {
                      this.sound.play();
                  } else {
                      this.sound.pause();
                  }
  
                  return this;
              };
  
              this.pause = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.pause();
  
                  return this;
              };
  
              this.isPaused = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return this.sound.paused;
              };
  
              this.stop = function () {
                  if (!supported ) {
                      return this;
                  }
  
                  this.setTime(0);
                  this.sound.pause();
  
                  return this;
              };
  
              this.isEnded = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return this.sound.ended;
              };
  
              this.loop = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.loop = 'loop';
                  this.bind('ended.buzzloop', function () {
                      this.currentTime = 0;
                      this.play();
                  });
  
                  return this;
              };
  
              this.unloop = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.removeAttribute('loop');
                  this.unbind('ended.buzzloop');
  
                  return this;
              };
  
              this.mute = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.muted = true;
  
                  return this;
              };
  
              this.unmute = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.muted = false;
  
                  return this;
              };
  
              this.toggleMute = function () {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.muted = !this.sound.muted;
  
                  return this;
              };
  
              this.isMuted = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return this.sound.muted;
              };
  
              this.setVolume = function (volume) {
                  if (!supported) {
                      return this;
                  }
  
                  if (volume < 0) {
                      volume = 0;
                  }
                  if (volume > 100) {
                      volume = 100;
                  }
  
                  this.volume = volume;
                  this.sound.volume = volume / 100;
  
                  return this;
              };
  
              this.getVolume = function () {
                  if (!supported) {
                      return this;
                  }
  
                  return this.volume;
              };
  
              this.increaseVolume = function (value) {
                  return this.setVolume(this.volume + (value || 1));
              };
  
              this.decreaseVolume = function (value) {
                  return this.setVolume(this.volume - (value || 1));
              };
  
              this.setTime = function (time) {
                  if (!supported) {
                      return this;
                  }
  
                  var set = true;
                  this.whenReady(function () {
                      if (set === true) {
                          set = false;
                          this.sound.currentTime = time;
                      }
                  });
  
                  return this;
              };
  
              this.getTime = function () {
                  if (!supported) {
                      return null;
                  }
  
                  var time = Math.round(this.sound.currentTime * 100) / 100;
  
                  return isNaN(time) ? buzz.defaults.placeholder : time;
              };
  
              this.setPercent = function (percent) {
                  if (!supported) {
                      return this;
                  }
  
                  return this.setTime(buzz.fromPercent(percent, this.sound.duration));
              };
  
              this.getPercent = function () {
                  if (!supported) {
                      return null;
                  }
  
                  var percent = Math.round(buzz.toPercent(this.sound.currentTime, this.sound.duration));
  
                  return isNaN(percent) ? buzz.defaults.placeholder : percent;
              };
  
              this.setSpeed = function (duration) {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound.playbackRate = duration;
  
                  return this;
              };
  
              this.getSpeed = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return this.sound.playbackRate;
              };
  
              this.getDuration = function () {
                  if (!supported) {
                      return null;
                  }
  
                  var duration = Math.round(this.sound.duration * 100) / 100;
  
                  return isNaN(duration) ? buzz.defaults.placeholder : duration;
              };
  
              this.getPlayed = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return timerangeToArray(this.sound.played);
              };
  
              this.getBuffered = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return timerangeToArray(this.sound.buffered);
              };
  
              this.getSeekable = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return timerangeToArray(this.sound.seekable);
              };
  
              this.getErrorCode = function () {
                  if (supported && this.sound.error) {
                      return this.sound.error.code;
                  }
  
                  return 0;
              };
  
              this.getErrorMessage = function () {
                  if (!supported) {
                      return null;
                  }
  
                  switch(this.getErrorCode()) {
                      case 1:
                          return 'MEDIA_ERR_ABORTED';
                      case 2:
                          return 'MEDIA_ERR_NETWORK';
                      case 3:
                          return 'MEDIA_ERR_DECODE';
                      case 4:
                          return 'MEDIA_ERR_SRC_NOT_SUPPORTED';
                      default:
                          return null;
                  }
              };
  
              this.getStateCode = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return this.sound.readyState;
              };
  
              this.getStateMessage = function () {
                  if (!supported) {
                      return null;
                  }
  
                  switch(this.getStateCode()) {
                      case 0:
                          return 'HAVE_NOTHING';
                      case 1:
                          return 'HAVE_METADATA';
                      case 2:
                          return 'HAVE_CURRENT_DATA';
                      case 3:
                          return 'HAVE_FUTURE_DATA';
                      case 4:
                          return 'HAVE_ENOUGH_DATA';
                      default:
                          return null;
                  }
              };
  
              this.getNetworkStateCode = function () {
                  if (!supported) {
                      return null;
                  }
  
                  return this.sound.networkState;
              };
  
              this.getNetworkStateMessage = function () {
                  if (!supported) {
                      return null;
                  }
  
                  switch(this.getNetworkStateCode()) {
                      case 0:
                          return 'NETWORK_EMPTY';
                      case 1:
                          return 'NETWORK_IDLE';
                      case 2:
                          return 'NETWORK_LOADING';
                      case 3:
                          return 'NETWORK_NO_SOURCE';
                      default:
                          return null;
                  }
              };
  
              this.set = function (key, value) {
                  if (!supported) {
                      return this;
                  }
  
                  this.sound[key] = value;
  
                  return this;
              };
  
              this.get = function (key) {
                  if (!supported) {
                    return null;
                  }
  
                  return key ? this.sound[key] : this.sound;
              };
  
              this.bind = function (types, func) {
                  if (!supported) {
                      return this;
                  }
  
                  types = types.split(' ');
  
                  var self = this,
                      efunc = function (e) { func.call(self, e); };
  
                  for (var t = 0; t < types.length; t++) {
                      var type = types[t],
                          idx = type;
                          type = idx.split('.')[0];
  
                          events.push({ idx: idx, func: efunc });
                          this.sound.addEventListener(type, efunc, true);
                  }
  
                  return this;
              };
  
              this.unbind = function (types) {
                  if (!supported) {
                      return this;
                  }
  
                  types = types.split(' ');
  
                  for (var t = 0; t < types.length; t++) {
                      var idx = types[t],
                          type = idx.split('.')[0];
  
                      for (var i = 0; i < events.length; i++) {
                          var namespace = events[i].idx.split('.');
                          if (events[i].idx === idx || (namespace[1] && namespace[1] === idx.replace('.', ''))) {
                              this.sound.removeEventListener(type, events[i].func, true);
                              // remove event
                              events.splice(i, 1);
                          }
                      }
                  }
  
                  return this;
              };
  
              this.bindOnce = function (type, func) {
                  if (!supported) {
                      return this;
                  }
  
                  var self = this;
  
                  eventsOnce[pid++] = false;
                  this.bind(type + '.' + pid, function () {
                     if (!eventsOnce[pid]) {
                         eventsOnce[pid] = true;
                         func.call(self);
                     }
                     self.unbind(type + '.' + pid);
                  });
  
                  return this;
              };
  
              this.trigger = function (types, detail) {
                  if (!supported) {
                      return this;
                  }
  
                  types = types.split(' ');
  
                  for (var t = 0; t < types.length; t++) {
                      var idx = types[t];
  
                      for (var i = 0; i < events.length; i++) {
                          var eventType = events[i].idx.split('.');
  
                          if (events[i].idx === idx || (eventType[0] && eventType[0] === idx.replace('.', ''))) {
                              var evt = doc.createEvent('HTMLEvents');
  
                              evt.initEvent(eventType[0], false, true);
  
                              evt.originalEvent = detail;
  
                              this.sound.dispatchEvent(evt);
                          }
                      }
                  }
  
                  return this;
              };
  
              this.fadeTo = function (to, duration, callback) {
                  if (!supported) {
                      return this;
                  }
  
                  if (duration instanceof Function) {
                      callback = duration;
                      duration = buzz.defaults.duration;
                  } else {
                      duration = duration || buzz.defaults.duration;
                  }
  
                  var from = this.volume,
                      delay = duration / Math.abs(from - to),
                      self = this,
                      fadeToTimeout;
  
                  this.play();
  
                  function doFade() {
                      clearTimeout(fadeToTimeout);
  
                      fadeToTimeout = setTimeout(function () {
                          if (from < to && self.volume < to) {
                              self.setVolume(self.volume += 1);
                              doFade();
                          } else if (from > to && self.volume > to) {
                              self.setVolume(self.volume -= 1);
                              doFade();
                          } else if (callback instanceof Function) {
                              callback.apply(self);
                          }
                      }, delay);
                  }
  
                  this.whenReady(function () {
                      doFade();
                  });
  
                  return this;
              };
  
              this.fadeIn = function (duration, callback) {
                  if (!supported) {
                      return this;
                  }
  
                  return this.setVolume(0).fadeTo(100, duration, callback);
              };
  
              this.fadeOut = function (duration, callback) {
                  if (!supported) {
                      return this;
                  }
  
                  return this.fadeTo(0, duration, callback);
              };
  
              this.fadeWith = function (sound, duration) {
                  if (!supported) {
                      return this;
                  }
  
                  this.fadeOut(duration, function () {
                      this.stop();
                  });
  
                  sound.play().fadeIn(duration);
  
                  return this;
              };
  
              this.whenReady = function (func) {
                  if (!supported) {
                      return null;
                  }
  
                  var self = this;
  
                  if (this.sound.readyState === 0) {
                      this.bind('canplay.buzzwhenready', function () {
                          func.call(self);
                      });
                  } else {
                      func.call(self);
                  }
              };
  
              this.addSource = function (src) {
                  var self   = this,
                      source = doc.createElement('source');
  
                  source.src = src;
  
                  if (buzz.types[getExt(src)]) {
                      source.type = buzz.types[getExt(src)];
                  }
  
                  this.sound.appendChild(source);
  
                  source.addEventListener('error', function (e) {
                      self.trigger('sourceerror', e);
                  });
  
                  return source;
              };
  
              // privates
              function timerangeToArray(timeRange) {
                  var array = [],
                      length = timeRange.length - 1;
  
                  for (var i = 0; i <= length; i++) {
                      array.push({
                          start: timeRange.start(i),
                          end: timeRange.end(i)
                      });
                  }
  
                  return array;
              }
  
              function getExt(filename) {
                  return filename.split('.').pop();
              }
  
              // init
              if (supported && src) {
  
                  for (var i in buzz.defaults) {
                      if (buzz.defaults.hasOwnProperty(i)) {
                          if (options[i] === undefined) {
                              options[i] = buzz.defaults[i];
                          }
                      }
                  }
  
                  this.sound = doc.createElement('audio');
  
                  // Shoud we set crossOrigin?
                  if (options.crossOrigin !== null) {
                      this.sound.crossOrigin = options.crossOrigin;
                  }
  
                  // Use web audio if possible to improve performance.
                  if (options.webAudioApi) {
                      var audioCtx = buzz.getAudioContext();
                      if (audioCtx) {
                        this.source = audioCtx.createMediaElementSource(this.sound);
                        this.source.connect(audioCtx.destination);
                      }
                  }
  
                  if (src instanceof Array) {
                      for (var j in src) {
                          if (src.hasOwnProperty(j)) {
                              this.addSource(src[j]);
                          }
                      }
                  } else if (options.formats.length) {
                      for (var k in options.formats) {
                          if (options.formats.hasOwnProperty(k)) {
                              this.addSource(src + '.' + options.formats[k]);
                          }
                      }
                  } else {
                      this.addSource(src);
                  }
  
                  if (options.loop) {
                      this.loop();
                  }
  
                  if (options.autoplay) {
                      this.sound.autoplay = 'autoplay';
                  }
  
                  if (options.preload === true) {
                      this.sound.preload = 'auto';
                  } else if (options.preload === false) {
                      this.sound.preload = 'none';
                  } else {
                      this.sound.preload = options.preload;
                  }
  
                  this.setVolume(options.volume);
  
                  buzz.sounds.push(this);
              }
          },
  
          group: function (sounds) {
              sounds = argsToArray(sounds, arguments);
  
              // publics
              this.getSounds = function () {
                  return sounds;
              };
  
              this.add = function (soundArray) {
                  soundArray = argsToArray(soundArray, arguments);
  
                  for (var a = 0; a < soundArray.length; a++) {
                      sounds.push(soundArray[a]);
                  }
              };
  
              this.remove = function (soundArray) {
                  soundArray = argsToArray(soundArray, arguments);
  
                  for (var a = 0; a < soundArray.length; a++) {
                      for (var i = 0; i < sounds.length; i++) {
                          if (sounds[i] === soundArray[a]) {
                              sounds.splice(i, 1);
                              break;
                          }
                      }
                  }
              };
  
              this.load = function () {
                  fn('load');
  
                  return this;
              };
  
              this.play = function () {
                  fn('play');
  
                  return this;
              };
  
              this.togglePlay = function () {
                  fn('togglePlay');
  
                  return this;
              };
  
              this.pause = function (time) {
                  fn('pause', time);
  
                  return this;
              };
  
              this.stop = function () {
                  fn('stop');
  
                  return this;
              };
  
              this.mute = function () {
                  fn('mute');
  
                  return this;
              };
  
              this.unmute = function () {
                  fn('unmute');
  
                  return this;
              };
  
              this.toggleMute = function () {
                  fn('toggleMute');
  
                  return this;
              };
  
              this.setVolume = function (volume) {
                  fn('setVolume', volume);
  
                  return this;
              };
  
              this.increaseVolume = function (value) {
                  fn('increaseVolume', value);
  
                  return this;
              };
  
              this.decreaseVolume = function (value) {
                  fn('decreaseVolume', value);
  
                  return this;
              };
  
              this.loop = function () {
                  fn('loop');
  
                  return this;
              };
  
              this.unloop = function () {
                  fn('unloop');
  
                  return this;
              };
  
              this.setSpeed = function (speed) {
                  fn('setSpeed', speed);
  
                  return this;
              };
  
              this.setTime = function (time) {
                  fn('setTime', time);
  
                  return this;
              };
  
              this.set = function (key, value) {
                  fn('set', key, value);
  
                  return this;
              };
  
              this.bind = function (type, func) {
                  fn('bind', type, func);
  
                  return this;
              };
  
              this.unbind = function (type) {
                  fn('unbind', type);
  
                  return this;
              };
  
              this.bindOnce = function (type, func) {
                  fn('bindOnce', type, func);
  
                  return this;
              };
  
              this.trigger = function (type) {
                  fn('trigger', type);
  
                  return this;
              };
  
              this.fade = function (from, to, duration, callback) {
                  fn('fade', from, to, duration, callback);
  
                  return this;
              };
  
              this.fadeIn = function (duration, callback) {
                  fn('fadeIn', duration, callback);
  
                  return this;
              };
  
              this.fadeOut = function (duration, callback) {
                  fn('fadeOut', duration, callback);
  
                  return this;
              };
  
              // privates
              function fn() {
                  var args = argsToArray(null, arguments),
                      func = args.shift();
  
                  for (var i = 0; i < sounds.length; i++) {
                      sounds[i][func].apply(sounds[i], args);
                  }
              }
  
              function argsToArray(array, args) {
                  return (array instanceof Array) ? array : Array.prototype.slice.call(args);
              }
          },
  
          all: function () {
              return new buzz.group(buzz.sounds);
          },
  
          isSupported: function () {
              return !!buzz.el.canPlayType;
          },
  
          isOGGSupported: function () {
              return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/ogg; codecs="vorbis"');
          },
  
          isWAVSupported: function () {
              return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/wav; codecs="1"');
          },
  
          isMP3Supported: function () {
              return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/mpeg;');
          },
  
          isAACSupported: function () {
              return !!buzz.el.canPlayType && (buzz.el.canPlayType('audio/x-m4a;') || buzz.el.canPlayType('audio/aac;'));
          },
  
          toTimer: function (time, withHours) {
              var h, m, s;
  
              h = Math.floor(time / 3600);
              h = isNaN(h) ? '--' : (h >= 10) ? h : '0' + h;
              m = withHours ? Math.floor(time / 60 % 60) : Math.floor(time / 60);
              m = isNaN(m) ? '--' : (m >= 10) ? m : '0' + m;
              s = Math.floor(time % 60);
              s = isNaN(s) ? '--' : (s >= 10) ? s : '0' + s;
  
              return withHours ? h + ':' + m + ':' + s : m + ':' + s;
          },
  
          fromTimer: function (time) {
              var splits = time.toString().split(':');
  
              if (splits && splits.length === 3) {
                  time = (parseInt(splits[0], 10) * 3600) + (parseInt(splits[1], 10) * 60) + parseInt(splits[2], 10);
              }
  
              if (splits && splits.length === 2) {
                  time = (parseInt(splits[0], 10) * 60) + parseInt(splits[1], 10);
              }
  
              return time;
          },
  
          toPercent: function (value, total, decimal) {
              var r = Math.pow(10, decimal || 0);
  
              return Math.round(((value * 100) / total) * r) / r;
          },
  
          fromPercent: function (percent, total, decimal) {
              var r = Math.pow(10, decimal || 0);
  
              return  Math.round(((total / 100) * percent) * r) / r;
          }
      };
  
      return buzz;
  });
  