/** @language japanese
* <p>LWebAudio クラスは、LSoundオブジェクトの基本クラスです。</p>
* <p>LWebAudio は抽象基本クラスであるため、LWebAudio を直接呼び出すことはできません。</p>
* <p>LWebAudio クラスは、子オブジェクトを持つすべてのオブジェクトの抽象基本クラスです。これは直接インスタンス化することはできません。</p>
* @class LWebAudio
* @extends LEventDispatcher
* @constructor
* @since 1.9.0
* @public
*/
var LWebAudio = (function () {
function LWebAudio () {
var s = this;
LExtends(s, LEventDispatcher, []);
s.currentTime = 0;
s.currentStart = 0;
s.currentSave = 0;
/** @language japanese
* LSoundオブジェクトの長さ
* @property length
* @type int
* @since 1.9.0
* @public
*/
s.length = 0;
s.loopStart = 0;
s.loopEnd = 0;
s.loopIndex = 0;
s.loopLength = 1;
/** @language japanese
* LSoundオブジェクトは再生中かどうか
* @property playing
* @type Boolean
* @since 1.9.0
* @public
*/
s.playing = false;
s.volume = 1;
LSound.Container.add(s);
}
LWebAudio.container = [];
LWebAudio.containerCount = 0;
LWebAudio.audioTag = new Audio();
LWebAudio._context = null;
var p = {
getWebAudio : function () {
var data;
if(LWebAudio.containerCount > 0){
data = LWebAudio.container.shift();
} else {
if (typeof webkitAudioContext !== UNDEFINED) {
try {
data = new webkitAudioContext();
} catch (e) {
LWebAudio.containerCount = LWebAudio.container.length;
data = LWebAudio.container.shift();
}
} else if (typeof AudioContext !== UNDEFINED) {
try {
data = new AudioContext();
} catch (e) {
LWebAudio.containerCount = LWebAudio.container.length;
data = LWebAudio.container.shift();
}
} else {
throw "AudioContext not supported. :(";
}
}
if(!data.createGainNode){
data.createGainNode = data.createGain;
}
LWebAudio.container.push(data);
return data;
},
onload : function (data) {
var s = this;
if (Object.prototype.toString.apply(data) !== '[object AudioBuffer]') {
s.load(data);
return;
};
if(!s.data){
s.data = s.getWebAudio();
}
s.buffer = data;
s.length = s.buffer.duration;
var e = new LEvent(LEvent.COMPLETE);
e.currentTarget = s;
e.target = s.buffer;
s.dispatchEvent(e);
},
_onended : function () {
var s = this;
s.dispatchEvent(LEvent.SOUND_COMPLETE);
if (++s.loopIndex < s.loopLength) {
s.play(s.currentStart, undefined, s.currentTimeTo);
} else {
s.close();
}
},
/** @language japanese
* <p>指定した URL から外部 音声 ファイルのロードを開始します。</p>
* <p>複数のブラウザをサポートするため、下記のように、複数なファイルを使うことができます。</p>
* <p>medio.load("medias/a.mp3,medias/a.wav,medias/a.ogg");</p>
* @method load
* @param {String} url 外部の 音声 ファイルを指定する URL です。(AudioBufferデーターまたはArrayBufferデーターも使えます。)
* @since 1.9.0
* @public
*/
load : function (u) {
var s = this;
if (typeof u !== "string") {
if (Object.prototype.toString.apply(u) == '[object AudioBuffer]') {
s.onload(u);
} else if (Object.prototype.toString.apply(u) == '[object ArrayBuffer]') {
if(!s.data){
s.data = s.getWebAudio();
}
s.data.decodeAudioData(u, s.onload.bind(s), function (error) {
throw "AudioContext decodeAudioData error : " + error.toString();
});
}
return;
}
var a, b, c, k, d, q = {"mov" : ["quicktime"], "3gp" : ["3gpp"], "ogv" : ["ogg"], "m4a" : ["mpeg"], "mp3" : ["mpeg"], "wav" : ["wav", "x-wav", "wave"], "wave" : ["wav", "x-wav", "wave"], "aac" : ["mp4"]};
a = u.split(',');
for (k in a) {
b = a[k].split('.');
d = b[b.length - 1];
if (q[d]) {
d = q[d];
} else {
d = [d];
}
c = d.some(function (element, index, array) {
return LWebAudio.audioTag.canPlayType(s._type + "/" + element);
});
if (c) {
LAjax.responseType = LAjax.ARRAY_BUFFER;
LAjax.get(a[k], {}, s.onload.bind(s));
return;
}
}
},
/** @language japanese
* <p>再生した時間を取得。</p>
* @method getCurrentTime
* @return {int} 再生した時間。
* @since 1.9.0
* @public
*/
getCurrentTime : function () {
var s = this;
if (s.playing) {
return s.data.currentTime - s.currentSave + s.currentTime;
} else {
return s.currentSave;
}
},
/** @language japanese
* <p>音量変更。</p>
* @method setVolume
* @param {float} value 音量。
* @since 1.9.0
* @public
*/
setVolume : function (v) {
var s = this;
s.volume = v;
if (s.playing) {
s.volumeNode.gain.value = v;
}
},
/** @language japanese
* <p>音量を取得。</p>
* @method getVolume
* @return {float} 音量。
* @since 1.9.0
* @public
*/
getVolume : function () {
return this.volume;
},
/** @language japanese
* <p>音声オブジェクトを再生する。</p>
* @method play
* @param {float} startTime 再生を開始する初期位置(秒単位)です。
* @param {int} loops サウンドチャネルの再生が停止するまで startTime 値に戻ってサウンドの再生を繰り返す回数を定義します。
* @since 1.9.0
* @public
*/
play : function (c, l, to) {
var s = this;
if (s.length == 0) {
return;
}
if (typeof l !== UNDEFINED) {
s.loopIndex = 0;
s.loopLength = l;
}
if (typeof c !== UNDEFINED) {
s.currentTime = c;
s.currentStart = c;
}
if (typeof to !== UNDEFINED) {
s.currentTimeTo = to > s.length ? s.length : to;
} else {
s.currentTimeTo = s.length;
}
s.data.loop = false;
s.playing = true;
if (s.timeout) {
clearTimeout(s.timeout);
delete s.timeout;
}
s.timeout = setTimeout(s._onended.bind(s), (s.currentTimeTo - s.currentTime) * 1000);
s.bufferSource = s.data.createBufferSource();
s.bufferSource.buffer = s.buffer;
s.volumeNode = s.data.createGainNode();
s.volumeNode.gain.value = s.volume;
s.volumeNode.connect(s.data.destination);
s.bufferSource.connect(s.volumeNode);
s.currentSave = s.data.currentTime;
if (s.bufferSource.start) {
s.bufferSource.start(0, s.currentTime, s.length - s.currentTime);
} else {
s.bufferSource.noteGrainOn(0, s.currentTime, s.length - s.currentTime);
}
},
/** @language japanese
* <p>指定する長さの音声オブジェクトを再生する。</p>
* @method playSegment
* @param {float} startTime 再生を開始する初期位置(秒単位)です。
* @param {float} segment 指定する長さ(秒単位)。
* @param {int} loops サウンドチャネルの再生が停止するまで startTime 値に戻ってサウンドの再生を繰り返す回数を定義します。
* @since 1.9.0
* @public
*/
playSegment : function (c, seg, l) {
this.playTo(c, c + seg, l);
},
/** @language japanese
* <p>指定する長さの音声オブジェクトを再生する。</p>
* @method playTo
* @param {float} startTime 再生を開始する初期位置(秒単位)です。
* @param {float} endTime 再生を終了する位置(秒単位)。
* @param {int} loops サウンドチャネルの再生が停止するまで startTime 値に戻ってサウンドの再生を繰り返す回数を定義します。
* @since 1.9.0
* @public
*/
playTo : function (c, to, l) {
this.play(c, l, to);
},
/** @language japanese
* <p>再生を一時停止する。</p>
* @method stop
* @since 1.9.0
* @public
*/
stop : function () {
var s = this;
if (!s.playing) {
return;
}
if (s.timeout) {
clearTimeout(s.timeout);
delete s.timeout;
}
if (s.bufferSource.stop) {
s.bufferSource.stop(0);
} else {
s.bufferSource.noteOff(0);
}
s.currentSave = s.getCurrentTime();
s.currentTime = s.currentSave;
s.playing = false;
},
/** @language japanese
* <p>再生を一時クローズする。</p>
* @method close
* @since 1.9.0
* @public
*/
close : function () {
var s = this;
if (!s.playing) {
return;
}
if (s.timeout) {
clearTimeout(s.timeout);
delete s.timeout;
}
if (s.bufferSource.stop) {
s.bufferSource.stop(0);
} else {
s.bufferSource.noteOff(0);
}
s.playing = false;
s.currentTime = 0;
s.currentSave = 0;
},
ll_check : function () {
var s = this;
if (!s.playing) {
return;
}
if (s.currentTimeTo < s.data.currentTime - s.currentSave + LSound.Container.time * 0.001) {
s._onended();
}
},
die : function () {
LSound.Container.remove(this);
}
};
for (var k in p) {
LWebAudio.prototype[k] = p[k];
}
return LWebAudio;
})();
/** @language japanese
* audioまたはvideoファイルロード完了。
* <p><a href="LEvent.html#property_COMPLETE">LEvent.COMPLETE</a></p>
* @event LEvent.COMPLETE
*/