API Docs for:
Show:

File: jxanimate.audio.js

/** ===========================================================================
 * @module JXAnimate.Audio
 * @description
 * Etamina Audio Library. It can preload and play audio.
 * load this file before etamina.js
 *
 * @author minren 
 * ===========================================================================
 * 
 */

/**
 * @class JXAnimate.Audio
 * @description
 *
 */
Jx().$package("JXAnimate.Audio", function(J){

	var 
		MAX_SOUNDS=10,
		soundRedundancy = 2,//每个声音重复加载的次数。频繁重复同一个声音时,增加冗余可以保持播放流畅。
		path = '',
		audioType = false;

	var	loadCount = 0;
	var	itemsToLoadCount = 0,
		itemsToLoad = new Array(),
		soundPool = new Array();

	var onLoadProgressUpdated;


	var supportedAudioFormat = function(audio) {
		var returnExtension = "";
		if (audio.canPlayType("audio/ogg") =="probably" || audio.canPlayType("audio/ogg") == "maybe") {
			returnExtension = "ogg";
		} else if(audio.canPlayType("audio/wav") =="probably" || audio.canPlayType("audio/wav") == "maybe") {
			returnExtension = "wav";
		} else if(audio.canPlayType("audio/mp3") == "probably" || audio.canPlayType("audio/mp3") == "maybe") {
			returnExtension = "mp3";
		}
		
		return returnExtension;
		
	};

	var onItemLoaded = function(event){
		if(J.isFunction(onLoadProgressUpdated)){
			onLoadProgressUpdated(event);
		}
	}
	var itemLoaded =  function (event) {
		//TODO:还要考虑加载失败的情况。
		//var _audio = etamina.audio;
		loadCount++;
		//raise 
		onItemLoaded(J.extend(event,{'loadCount':loadCount,'itemsToLoadCount':itemsToLoadCount}));
		var item;
		if (loadCount >= itemsToLoadCount) {
			console.log('itemLoaded: total item is '+loadCount);
			for (var i = itemsToLoadCount - 1; i >= 0; i--) {
				item = itemsToLoad[i];
				item.element.removeEventListener("canplaythrough",itemLoaded,false);
				soundPool.push(item);
				itemsToLoad.splice(i,1);
			};
			itemsToLoadCount=0;
			loadCount = 0;
		}
	}

	//添加一个事件,当声音加载进度更新时触发。
	this.addListenerForLoadProgressUpdated = function(func){
		onLoadProgressUpdated = func;
	};
	/**
	 * 获取当前浏览器所支持的音频文件格式
	 * @method getAudioType
	 * @param  {AudioElement} audio [HTML5中的audio元素]
	 * @return {string}       [所支持音频格式的扩展名,不包括"."]
	 *
	 */
	this.getAudioType = function(audio){
		if(!audioType){
			if(audio==null){
				return false;
			}
			audioType = supportedAudioFormat(audio);
			return audioType;
		}
		return audioType;
	};

	/**
	 * 初始化音频引擎
	 * @method init
	 * @param  {object} params 初始化参数(path:声音文件的默认路径)
	 * @return {void}        
	 */
	this.init=function(params){
		params = params||{};
		if(J.isObject(params) && 'path' in params){
			this.path = params.path;
		}
	};
	/**
	 * 预加载一个或多个声音
	 * @method preload
	 * @param  {Array} sounds     声音URL的字符串或字符串数组
	 * @param  {int} redundancy 每个声音的冗余数
	 * @param  {string} path       相对路径
	 * @return {void}
	 */
	this.preload=function(sounds,redundancy,path){
		if(itemsToLoadCount>0){
			return;
		}

		if(J.isString(sounds)){
			this.preloadSound(sounds,redundancy,path);
			return;
		}
		else if(J.isArray(sounds) && sounds.length>0){
			var fullname;
			for (var i = sounds.length - 1; i >= 0; i--) {

				var sound = sounds[i];
				
				redundancy = redundancy || soundRedundancy;
				path = path|| this.path;
				fullname = path+sound;
				var tempSound;
				for (var j = 0; j <redundancy; j++) {
					itemsToLoadCount++;
					tempSound = document.createElement("audio");

					tempSound.setAttribute("src", fullname + "." + this.getAudioType(tempSound));
					tempSound.addEventListener("canplaythrough",itemLoaded,false);
					document.body.appendChild(tempSound)
					itemsToLoad.push({name:sound, element:tempSound, type:this.getAudioType(), played:false});
				};					
			};
		}
	};

	/**
	 * 预加载一个声音文件
	 * @method preloadSound
	 * @param  {string} sound      声音文件URL
	 * @param  {int} redundancy 每个声音的冗余数
	 * @param  {string} path       相对路径
	 * @return {void}            
	 */
	this.preloadSound=function(sound,redundancy,path){
		if(J.isString(sound)){
			this.preload([sound],redundancy,path);
			return;
		}
	};

	/**
	 * 播放声音
	 * @method playSound
	 * @param  {string} sound  声音的文件名
	 * @param  {float} volume 音量,0到1之间
	 * @return {void}        
	 */
	this.playSound= function(sound,volume){
		volume = volume||1;

		var soundFound = false;
		var soundIndex = 0;
		var tempSound;
		//var soundPool = this.soundPool;
		
		if (soundPool.length > 0) {
			console.log('play:'+sound+',pool length='+soundPool.length)
			while (!soundFound && soundIndex < soundPool.length) {
			
				var tSound = soundPool[soundIndex];
				if ((tSound.element.ended || !tSound.played) && tSound.name == sound) {
					soundFound = true;
					tSound.played = true;
				} else {
					soundIndex++;
				}
		
			}
		}
		if (soundFound) {
			tempSound = soundPool[soundIndex].element;
			tempSound.volume = volume;
			tempSound.play();
			
		} else if (soundPool.length < this.MAX_SOUNDS){  //在运行时加载声音,可能会导致停顿。
			/*
			tempSound = document.createElement("audio");
			tempSound.setAttribute("src", sound + "." + this.audioType);
			tempSound.volume = volume;
			tempSound.play();
			soundPool.push({name:sound, element:tempSound, type:this.audioType, played:true});
			*/
		}
	}

});