File:HTMLAudioPlugin.js
/*
* HTMLAudioPlugin
* Visit http://createjs.com/ for documentation, updates and examples.
*
*
* Copyright (c) 2012 gskinner.com, inc.
*
* 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.
*/
/**
* @module SoundJS
*/
// namespace:
this.createjs = this.createjs || {};
(function () {
"use strict";
/**
* Play sounds using HTML <audio> tags in the browser. This plugin is the second priority plugin installed
* by default, after the {{#crossLink "WebAudioPlugin"}}{{/crossLink}}. For older browsers that do not support html
* audio, include and install the {{#crossLink "FlashAudioPlugin"}}{{/crossLink}}.
*
* <h4>Known Browser and OS issues for HTML Audio</h4>
* <b>All browsers</b><br />
* Testing has shown in all browsers there is a limit to how many audio tag instances you are allowed. If you exceed
* this limit, you can expect to see unpredictable results. Please use {{#crossLink "Sound.MAX_INSTANCES"}}{{/crossLink}} as
* a guide to how many total audio tags you can safely use in all browsers. This issue is primarily limited to IE9.
*
* <b>IE html limitations</b><br />
* <ul><li>There is a delay in applying volume changes to tags that occurs once playback is started. So if you have
* muted all sounds, they will all play during this delay until the mute applies internally. This happens regardless of
* when or how you apply the volume change, as the tag seems to need to play to apply it.</li>
* <li>MP3 encoding will not always work for audio tags if it's not default. We've found default encoding with
* 64kbps works.</li>
* <li>Occasionally very short samples will get cut off.</li>
* <li>There is a limit to how many audio tags you can load or play at once, which appears to be determined by
* hardware and browser settings. See {{#crossLink "HTMLAudioPlugin.MAX_INSTANCES"}}{{/crossLink}} for a safe estimate.
* Note that audio sprites can be used as a solution to this issue.</li></ul>
*
* <b>Safari limitations</b><br />
* <ul><li>Safari requires Quicktime to be installed for audio playback.</li></ul>
*
* <b>iOS 6 limitations</b><br />
* <ul><li>can only have one <audio> tag</li>
* <li>can not preload or autoplay the audio</li>
* <li>can not cache the audio</li>
* <li>can not play the audio except inside a user initiated event.</li>
* <li>Note it is recommended to use {{#crossLink "WebAudioPlugin"}}{{/crossLink}} for iOS (6+)</li>
* <li>audio sprites can be used to mitigate some of these issues and are strongly recommended on iOS</li>
* </ul>
*
* <b>Android Native Browser limitations</b><br />
* <ul><li>We have no control over audio volume. Only the user can set volume on their device.</li>
* <li>We can only play audio inside a user event (touch/click). This currently means you cannot loop sound or use a delay.</li></ul>
* <b> Android Chrome 26.0.1410.58 specific limitations</b><br />
* <ul> <li>Can only play 1 sound at a time.</li>
* <li>Sound is not cached.</li>
* <li>Sound can only be loaded in a user initiated touch/click event.</li>
* <li>There is a delay before a sound is played, presumably while the src is loaded.</li>
* </ul>
*
* See {{#crossLink "Sound"}}{{/crossLink}} for general notes on known issues.
*
* @class HTMLAudioPlugin
* @extends AbstractPlugin
* @constructor
*/
function HTMLAudioPlugin() {
this.AbstractPlugin_constructor();
// Public Properties
this._capabilities = s._capabilities;
this._loaderClass = createjs.SoundLoader;
this._soundInstanceClass = createjs.HTMLAudioSoundInstance;
}
var p = createjs.extend(HTMLAudioPlugin, createjs.AbstractPlugin);
var s = HTMLAudioPlugin;
// Static Properties
/**
* The maximum number of instances that can be loaded or played. This is a browser limitation, primarily limited to IE9.
* The actual number varies from browser to browser (and is largely hardware dependant), but this is a safe estimate.
* Audio sprites work around this limitation.
* @property MAX_INSTANCES
* @type {Number}
* @default 30
* @static
*/
s.MAX_INSTANCES = 30;
/**
* Event constant for the "canPlayThrough" event for cleaner code.
* @property _AUDIO_READY
* @type {String}
* @default canplaythrough
* @static
* @private
*/
s._AUDIO_READY = "canplaythrough";
/**
* Event constant for the "ended" event for cleaner code.
* @property _AUDIO_ENDED
* @type {String}
* @default ended
* @static
* @private
*/
s._AUDIO_ENDED = "ended";
/**
* Event constant for the "seeked" event for cleaner code. We utilize this event for maintaining loop events.
* @property _AUDIO_SEEKED
* @type {String}
* @default seeked
* @static
* @private
*/
s._AUDIO_SEEKED = "seeked";
/**
* Event constant for the "stalled" event for cleaner code.
* @property _AUDIO_STALLED
* @type {String}
* @default stalled
* @static
* @private
*/
s._AUDIO_STALLED = "stalled";
/**
* Event constant for the "timeupdate" event for cleaner code. Utilized for looping audio sprites.
* This event callsback ever 15 to 250ms and can be dropped by the browser for performance.
* @property _TIME_UPDATE
* @type {String}
* @default timeupdate
* @static
* @private
*/
s._TIME_UPDATE = "timeupdate";
/**
* The capabilities of the plugin. This is generated via the {{#crossLink "HTMLAudioPlugin/_generateCapabilities"}}{{/crossLink}}
* method. Please see the Sound {{#crossLink "Sound/capabilities:property"}}{{/crossLink}} method for an overview of all
* of the available properties.
* @property _capabilities
* @type {Object}
* @private
* @static
*/
s._capabilities = null;
// Static Methods
/**
* Determine if the plugin can be used in the current browser/OS. Note that HTML audio is available in most modern
* browsers, but is disabled in iOS because of its limitations.
* @method isSupported
* @return {Boolean} If the plugin can be initialized.
* @static
*/
s.isSupported = function () {
s._generateCapabilities();
return (s._capabilities != null);
};
/**
* Determine the capabilities of the plugin. Used internally. Please see the Sound API {{#crossLink "Sound/capabilities:property"}}{{/crossLink}}
* method for an overview of plugin capabilities.
* @method _generateCapabilities
* @static
* @private
*/
s._generateCapabilities = function () {
if (s._capabilities != null) {return;}
var t = document.createElement("audio");
if (t.canPlayType == null) {return null;}
s._capabilities = {
panning:false,
volume:true,
tracks:-1
};
// determine which extensions our browser supports for this plugin by iterating through Sound.SUPPORTED_EXTENSIONS
var supportedExtensions = createjs.Sound.SUPPORTED_EXTENSIONS;
var extensionMap = createjs.Sound.EXTENSION_MAP;
for (var i = 0, l = supportedExtensions.length; i < l; i++) {
var ext = supportedExtensions[i];
var playType = extensionMap[ext] || ext;
s._capabilities[ext] = (t.canPlayType("audio/" + ext) != "no" && t.canPlayType("audio/" + ext) != "") || (t.canPlayType("audio/" + playType) != "no" && t.canPlayType("audio/" + playType) != "");
} // OJR another way to do this might be canPlayType:"m4a", codex: mp4
};
// public methods
p.register = function (loadItem) {
var tag = createjs.HTMLAudioTagPool.get(loadItem.src);
var loader = this.AbstractPlugin_register(loadItem);
loader.setTag(tag);
return loader;
};
p.removeSound = function (src) {
this.AbstractPlugin_removeSound(src);
createjs.HTMLAudioTagPool.remove(src);
};
p.create = function (src, startTime, duration) {
var si = this.AbstractPlugin_create(src, startTime, duration);
si.playbackResource = null;
return si;
};
p.toString = function () {
return "[HTMLAudioPlugin]";
};
// plugin does not support these
p.setVolume = p.getVolume = p.setMute = null;
createjs.HTMLAudioPlugin = createjs.promote(HTMLAudioPlugin, "AbstractPlugin");
}());