+var X_Audio_constructor = 3.1 <= X_UA[ 'Safari' ] && X_UA[ 'Safari' ] < 4 ?
+ function( s, a ){
+ a = document.createElement( 'audio' );
+ a.src = s;
+ a.load();
+ return a;
+ } :
+ // Android1.6 + MobileOpera12 HTMLAudio はいるが呼ぶとクラッシュする
+ !( X_UA[ 'Android' ] < 2 ) ?
+ window[ 'Audio' ] || window.HTMLAudioElement : null,
+
+ // Blink5 Opera32 Win8 は HTMLAudio が壊れている、WebAudio は mp3 がデコードに失敗、ogg が動作
+ X_Audio_blinkOperaFix = X_UA[ 'BlinkOpera' ] && X_UA[ 'Windows' ],
+
+ X_Audio_codecs;
+
+if( X_Audio_constructor ){
+ //http://himaxoff.blog111.fc2.com/blog-entry-97.html
+ //引数なしで new Audio() とすると、Operaでエラーになるそうなので注意。
+ X_TEMP.rawAudio = new X_Audio_constructor( '' );
+
+ // https://html5experts.jp/miyuki-baba/3766/
+ // TODO Chrome for Android31 で HE-AAC が低速再生されるバグ
+ // TODO Android4 標準ブラウザで ogg のシークが正しくない!
+ if( X_TEMP.rawAudio.canPlayType ){
+ X_Audio_codecs = {
+ 'mp3' : X_TEMP.rawAudio.canPlayType('audio/mpeg'),
+ 'opus' : X_TEMP.rawAudio.canPlayType('audio/ogg; codecs="opus"'),
+ 'ogg' : X_TEMP.rawAudio.canPlayType('audio/ogg; codecs="vorbis"'),
+ 'wav' : X_TEMP.rawAudio.canPlayType('audio/wav; codecs="1"'),
+ 'aac' : X_TEMP.rawAudio.canPlayType('audio/aac'),
+ 'm4a' : X_TEMP.rawAudio.canPlayType('audio/x-m4a') + X_TEMP.rawAudio.canPlayType('audio/m4a') + X_TEMP.rawAudio.canPlayType('audio/aac'),
+ 'mp4' : X_TEMP.rawAudio.canPlayType('audio/x-mp4') + X_TEMP.rawAudio.canPlayType('audio/mp4') + X_TEMP.rawAudio.canPlayType('audio/aac'),
+ 'weba' : X_TEMP.rawAudio.canPlayType('audio/webm; codecs="vorbis"')
+ };
+ (function( X_Audio_codecs, k, v ){
+ for( k in X_Audio_codecs ){
+ //if( X_EMPTY_OBJECT[ k ] ) continue;
+ v = X_Audio_codecs[ k ];
+ v = v && !!( v.split( 'no' ).join( '' ) );
+ if( v ){
+ console.log( k + ' ' + X_Audio_codecs[ k ] );
+ X_Audio_codecs[ k ] = true;
+ } else {
+ delete X_Audio_codecs[ k ];
+ };
+ };
+ if( X_Audio_blinkOperaFix ) delete X_Audio_codecs[ 'mp3' ];
+ })( X_Audio_codecs );
+ } else {
+ // iOS3.2.3
+ X_Audio_codecs = {
+ 'mp3' : X_UA[ 'IE' ] || X_UA[ 'Chrome' ] || ( X_UA[ 'Windows' ] && X_UA[ 'Safari' ] ),
+ 'ogg' : 5 <= X_UA[ 'Gecko' ] || X_UA[ 'Chrome' ] || X_UA[ 'Opera' ] ,
+ 'wav' : X_UA[ 'Gecko' ] || X_UA[ 'Opera' ] || ( X_UA[ 'Windows' ] && X_UA[ 'Safari' ] ),
+ 'aac' : X_UA[ 'IE' ] || X_UA[ 'WebKit' ],
+ 'm4a' : X_UA[ 'IE' ] || X_UA[ 'WebKit' ],
+ 'mp4' : X_UA[ 'IE' ] || X_UA[ 'WebKit' ],
+ 'weba' : 2 <= X_UA[ 'Gecko' ] || 10.6 <= X_UA[ 'Opera' ] // firefox4+(Gecko2+)
+ };
+ (function( X_Audio_codecs, k ){
+ for( k in X_Audio_codecs ){
+ //if( X_EMPTY_OBJECT[ k ] ) continue;
+ if( X_Audio_codecs[ k ] ){
+ console.log( k + ' ' + X_Audio_codecs[ k ] );
+ X_Audio_codecs[ k ] = true;
+ } else {
+ delete X_Audio_codecs[ k ];
+ };
+ };
+ })( X_Audio_codecs );
+ };
+
+ if( X_Audio_blinkOperaFix ){
+ X_Audio_constructor = null;
+ delete X_TEMP.rawAudio;
+ };
+};
-var X_Audio_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
+
+var X_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
+ // TODO なんで fennec を禁止?
!( X_UA[ 'Gecko' ] && X_UA[ 'Android' ] ) &&
- ( window.AudioContext || window.webkitAudioContext ),
- X_Audio_WebAudioWrapper;
+ // Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる
+ // Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる
+ !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 42 && X_UA[ 'Windows' ] ) &&
+ ( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] ),
+ X_WebAudio_BUFFER_LIST = [],
+ X_WebAudio,
+ X_WebAudio_BufferLoader,
+ X_WebAudio_fpsFix;
/*
* iPhone 4s 以下、iPad2以下、iPad mini 1以下, iPod touch 4G 以下は不可
*/
-if( X_Audio_WebAudio_context ){
-
- X_Audio_WebAudio_context = new X_Audio_WebAudio_context;
+if( X_WebAudio_context ){
- function X_Audio_WebAudio_getBuffer( url ){
- var i = 0, l = X_Audio_WRAPPER_LIST.length;
- for( i = 0; i < l; ++i ){
- if( X_Audio_WRAPPER_LIST[ i ].url === url ) return X_Audio_WRAPPER_LIST[ i ];
- };
- };
+ X_WebAudio_context = new X_WebAudio_context;
- X_Audio_WebAudioWrapper = X.EventDispatcher.inherits(
- 'X.AV.WebAudioWrapper',
- X.Class.POOL_OBJECT,
+ X_WebAudio_BufferLoader = X_EventDispatcher[ 'inherits' ](
+ 'X.WebAudio.BufferLoader',
+ X_Class.POOL_OBJECT,
{
-
- url : '',
- proxy : null,
-
- startTime : 0,
- endTime : -1,
- loopStartTime : -1,
- loopEndTime : -1,
- seekTime : -1,
- duration : 0,
-
- playing : false,
- error : 0,
- loop : false,
- looped : false,
- autoplay : false,
- volume : 0.5,
-
- _startPos : 0,
- _endPosition : 0,
- _startTime : 0,
- _timerID : 0,
- _interval : 0,
- buffer : null,
- source : null,
- gainNode : null,
- _onended : null,
-
+ audioUrl : '',
xhr : null,
onDecodeSuccess : null,
onDecodeError : null,
- Constructor : function( proxy, url, option ){
- var audio = X_Audio_WebAudio_getBuffer( url );
-
- this.proxy = proxy;
- this.url = url;
-
- X_AudioWrapper_updateStates( this, option );
-
- if( audio && audio.buffer ){
- this._onDecodeSuccess( audio.buffer );
- } else
- if( audio ){
- // TODO 当てにしていたaudioがclose 等した場合
- audio.proxy.listenOnce( 'canplaythrough', this, this._onBufferReady );
- } else {
- this.xhr = X.Net.xhrGet( url, 'arraybuffer' )
- .listen( X_Event.PROGRESS, this )
- .listenOnce( [ X_Event.SUCCESS, X_Event.COMPLETE, X_Event.CANCELED ], this );
- };
+ audioBuffer : null,
+ errorState : 0,
+ webAudioList : null,
+
+ 'Constructor' : function( webAudio, url ){
+ this.webAudioList = [ webAudio ];
+ this.audioUrl = url;
+ this.xhr = X[ 'Net' ]( { 'xhr' : url, 'dataType' : 'arraybuffer' } )
+ [ 'listen' ]( X_EVENT_PROGRESS, this )
+ [ 'listenOnce' ]( [ X_EVENT_SUCCESS, X_EVENT_COMPLETE ], this );
+ X_WebAudio_BUFFER_LIST.push( this );
},
handleEvent : function( e ){
switch( e.type ){
- case X_Event.PROGRESS :
- e.percent ?
- this.proxy.dispatch( { type : 'progress', percent : e.percent } ) :
- this.proxy.dispatch( 'loadstart' );
+ case X_EVENT_PROGRESS :
+ this[ 'dispatch' ]( { type : 'progress', 'percent' : e[ 'percent' ] } );
return;
- case X_Event.SUCCESS :
- console.log( 'WebAudio xhr success! ' + !!X_Audio_WebAudio_context.decodeAudioData + ' t:' + typeof e.data );
+ case X_EVENT_SUCCESS :
// TODO 旧api
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext
// iOS 7.1 で decodeAudioData に処理が入った瞬間にスクリーンを長押しする(スクロールを繰り返す)と
// decoeAudioData の処理がキャンセルされることがある(エラーやコールバックの発火もなく、ただ処理が消滅する)。
// ただし iOS 8.1.2 では エラーになる
- if( X_Audio_WebAudio_context.createBuffer && X_UA[ 'iOS' ] < 8 ){
- this._onDecodeSuccess( X_Audio_WebAudio_context.createBuffer( e.data, false ) );
+ if( X_UA[ 'iOS' ] < 8 || !X_WebAudio_context[ 'decodeAudioData' ] ){
+ this._onDecodeSuccess( X_WebAudio_context[ 'createBuffer' ]( e.response, false ) );
} else
- if( X_Audio_WebAudio_context.decodeAudioData ){
- X_Audio_WebAudio_context.decodeAudioData( e.data,
- this.onDecodeSuccess = X_Callback_create( this, this._onDecodeSuccess ),
- this.onDecodeError = X_Callback_create( this, this._onDecodeError ) );
- } else {
- this._onDecodeSuccess( X_Audio_WebAudio_context.createBuffer( e.data, false ) );
+ if( X_WebAudio_context[ 'decodeAudioData' ] ){
+ X_WebAudio_context[ 'decodeAudioData' ]( e.response,
+ this.onDecodeSuccess = X_Closure_create( this, this._onDecodeSuccess ),
+ this.onDecodeError = X_Closure_create( this, this._onDecodeError ) );
};
break;
- case X_Event.CANCELED :
- this.error = 1;
- this.proxy.dispatch( 'aborted' );
- break;
-
- case X_Event.COMPLETE :
- this.error = 2;
- this.proxy.asyncDispatch( { type : X_Event.ERROR, message : 'xhr error' } );
+ case X_EVENT_COMPLETE :
+ this.errorState = 1;
+ this[ 'asyncDispatch' ]( X_EVENT_COMPLETE );
break;
};
- this.xhr.unlisten( [ X_Event.PROGRESS, X_Event.SUCCESS, X_Event.COMPLETE, X_Event.CANCELED ], this );
+ this.xhr[ 'unlisten' ]( [ X_EVENT_PROGRESS, X_EVENT_SUCCESS, X_EVENT_COMPLETE ], this );
delete this.xhr;
},
_onDecodeSuccess : function( buffer ){
- console.log( 'WebAudio decode success!' );
-
this.onDecodeSuccess && this._onDecodeComplete();
if ( !buffer ) {
- this.proxy.asyncDispatch( { type : X_Event.ERROR, message : 'buffer is ' + buffer } );
+ this.errorState = 2;
+ this[ 'asyncDispatch' ]( X_EVENT_COMPLETE );
return;
};
-
- this.buffer = buffer;
- this.duration = buffer.duration * 1000;
- /*
- this.proxy.asyncDispatch( 'loadedmetadata' );
- this.proxy.asyncDispatch( 'loadeddata' );
- this.proxy.asyncDispatch( 'canplay' );
- this.proxy.asyncDispatch( 'canplaythrough' );
- */
- this.proxy.asyncDispatch( X_Event.READY );
-
- this.autoplay && X.Timer.once( 16, this, this.play );
+ console.log( 'WebAudio decode success!' );
+
+ this.audioBuffer = buffer;
+
+ this[ 'asyncDispatch' ]( X_EVENT_COMPLETE );
+
console.log( 'WebAudio decoded!' );
},
_onDecodeError : function(){
console.log( 'WebAudio decode error!' );
this._onDecodeComplete();
- this.error = 3;
- this.proxy.asyncDispatch( { type : X_Event.ERROR, message : 'decode error' } );
+ this.errorState = 2;
+ this[ 'asyncDispatch' ]( X_EVENT_COMPLETE );
},
_onDecodeComplete : function(){
- X_Callback_correct( this.onDecodeSuccess );
+ X_Closure_correct( this.onDecodeSuccess );
delete this.onDecodeSuccess;
- X_Callback_correct( this.onDecodeError );
+ X_Closure_correct( this.onDecodeError );
delete this.onDecodeError;
},
-
- _onBufferReady : function( e ){
- var audio = X_Audio_WebAudio_getBuffer( this.url );
- this._onDecodeSuccess( audio.buffer );
- },
- close : function(){
- delete this.buffer;
+ unregister : function( webAudio ){
+ var list = this.webAudioList,
+ i = list.indexOf( webAudio );
+ if( 0 < i ){
+ list.splice( i, 1 );
+ if( list.length ){
+ this.xhr && this.xhr[ 'kill' ]();
+ this[ 'kill' ]();
+ };
+ };
+ }
+
+ }
+ );
+
- if( this.xhr ) this.xhr.close();
+ X_WebAudio = X_AudioBase[ 'inherits' ](
+ 'X.WebAudio',
+ X_Class.POOL_OBJECT,
+ {
+
+ loader : null,
+
+ _startPos : 0,
+ _endPosition : 0,
+ _startTime : 0,
+ _timerID : 0,
+ _interval : 0,
+ audioBuffer : null,
+ bufferSource : null,
+ gainNode : null,
+ _onended : null,
+
+ 'Constructor' : function( disatcher, url, option ){
+ var i = 0,
+ l = X_WebAudio_BUFFER_LIST.length,
+ loader;
+
+ /*
+ * http://qiita.com/sou/items/5688d4e7d3a37b4e2ff1
+ * L-01F 等の一部端末で Web Audio API の再生結果に特定条件下でノイズが混ざることがある。
+ * 描画レート(描画 FPS)が下がるとノイズが混ざり始め、レートを上げると再生結果が正常になるというもので、オーディオ処理が描画スレッドに巻き込まれているような動作を見せる。
+ */
+ if( X_UA[ 'Android' ] && X_UA[ 'Chrome' ] && !X_WebAudio_fpsFix ){
+ X_Node_systemNode.create( 'div', { id : 'fps-slowdown-make-sound-noisy' } );
+ X_WebAudio_fpsFix = true;
+ };
+
+ for( ; i < l; ++i ){
+ loader = X_WebAudio_BUFFER_LIST[ i ];
+ if( loader.audioUrl === url ){
+ this.loader = loader;
+ loader.webAudioList.push( this );
+ break;
+ };
+ };
- if( this.onDecodeSuccess ){
- // 回収はあきらめる、、、
+ if( !this.loader ){
+ this.loader = loader = X_WebAudio_BufferLoader( this, url );
};
+
+ this.disatcher = disatcher || this;
+ this.setState( option );
+
+ this[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, this.onKill );
+
+ if( loader.audioBuffer || loader.errorState ){
+ this._onLoadBufferComplete();
+ } else {
+ loader[ 'listenOnce' ]( X_EVENT_COMPLETE, this, this._onLoadBufferComplete );
+ };
+ },
+
+ onKill : function(){
+ this.loader[ 'unlisten' ]( X_EVENT_COMPLETE, this, this._onLoadBufferComplete )
+ .unregister( this );
+
+ delete this.audioBuffer;
+
+ this.playing && this.actualPause();
+ this.bufferSource && this._sourceDispose();
- this.playing && this.pause();
- this.source && this._sourceDispose();
-
- this._onended && X_Callback_correct( this._onended );
+ this._onended && X_Closure_correct( this._onended );
- this.gainNode && this.gainNode.disconnect();
+ this.gainNode && this.gainNode.disconnect();
},
+ _onLoadBufferComplete : function( e ){
+ var loader = this.loader,
+ buffer = loader.audioBuffer;
+
+ e && loader[ 'unlisten' ]( X_EVENT_COMPLETE, this, this._onLoadBufferComplete );
+
+ if ( !buffer ) {
+ this.error = loader.errorState;
+
+ this.disatcher[ 'dispatch' ]({
+ type : X_EVENT_ERROR,
+ error : loader.errorState,
+ message : loader.errorState === 1 ?
+ 'load buffer network error' :
+ 'buffer decode error'
+ });
+ this[ 'kill' ]();
+ return;
+ };
+
+ this.audioBuffer = buffer;
+ this.duration = buffer.duration * 1000;
+
+ this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
+
+ console.log( 'WebAudio buffer ready' );
+
+ this.autoplay && X_Timer_once( 16, this, this.play );
+
+ },
- _sourceDispose : function(){
- this.source.disconnect();
- delete this.source.onended;
- delete this.source;
- },
-
- play : function(){
+ actualPlay : function(){
var begin, end;
- if( !this.buffer ){
+ console.log( '[WebAudio] play abuf:' + !!this.audioBuffe );
+
+ if( !this.audioBuffer ){
this.autoplay = true;
return;
};
- end = X_AudioWrapper_getEndTime( this );
- begin = X_AudioWrapper_getStartTime( this, end, true );
+ end = X_Audio_getEndTime( this );
+ begin = X_Audio_getStartTime( this, end, true );
console.log( '[WebAudio] play ' + begin + ' -> ' + end );
- if( this.source ) this._sourceDispose();
+ if( this.bufferSource ) this._sourceDispose();
if( !this.gainNode ){
- this.gainNode = X_Audio_WebAudio_context.createGain ? X_Audio_WebAudio_context.createGain() : X_Audio_WebAudio_context.createGainNode();
- this.gainNode.connect( X_Audio_WebAudio_context.destination );
+ this.gainNode = X_WebAudio_context[ 'createGain' ] ? X_WebAudio_context[ 'createGain' ]() : X_WebAudio_context[ 'createGainNode' ]();
+ this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] );
};
- this.source = X_Audio_WebAudio_context.createBufferSource();
- this.source.buffer = this.buffer;
- this.source.connect( this.gainNode );
+ this.bufferSource = X_WebAudio_context[ 'createBufferSource' ]();
+ this.bufferSource.buffer = this.audioBuffer;
+ this.bufferSource[ 'connect' ]( this.gainNode );
- this.gainNode.gain.value = this.volume;
+ this.gainNode[ 'gain' ].value = this.gain;
// おかしい、stop 前に外していても呼ばれる、、、@Firefox33.1
- // 破棄された X.Callback が呼ばれて、obj._() でエラーになる。Firefox では、onended は使わない
- if( false && this.source.onended !== undefined ){
+ // 破棄された X.Callback が呼ばれて、obj.proxy() でエラーになる。Firefox では、onended は使わない
+ // 多くのブラウザで onended は timer を使ったカウントより遅いので使わない
+ //if( this.bufferSource.onended !== undefined ){
//console.log( '> use onended' );
- this.source.onended = this._onended || ( this._onended = X_Callback_create( this, this._onEnded ) );
- } else {
- this._timerID && X.Timer.remove( this._timerID );
- this._timerID = X.Timer.once( end - begin, this, this._onEnded );
- };
+ //this.bufferSource.onended = this._onended || ( this._onended = X_Closure_create( this, this._onEnded ) );
+ //} else {
+ this._timerID && X_Timer_remove( this._timerID );
+ this._timerID = X_Timer_once( end - begin, this, this._onEnded );
+ //};
- if( this.source.start ){
- this.source.start( 0, begin / 1000, end / 1000 );
+ if( this.bufferSource.start ){
+ this.bufferSource.start( 0, begin / 1000, end / 1000 );
} else {
- this.source.noteGrainOn( 0, begin / 1000, end / 1000 );
+ this.bufferSource[ 'noteGrainOn' ]( 0, begin / 1000, end / 1000 );
};
this.playing = true;
this._startPos = begin;
this._endPosition = end;
- this._startTime = X_Audio_WebAudio_context.currentTime * 1000;
- this._interval = this._interval || X.Timer.add( 1000, 0, this, this._onInterval );
+ this._startTime = X_WebAudio_context.currentTime * 1000;
+ this._interval = this._interval || X_Timer_add( 1000, 0, this, this._onInterval );
},
+
+ _sourceDispose : function(){
+ this.bufferSource.disconnect();
+ delete this.bufferSource.onended;
+ delete this.bufferSource;
+ },
_onInterval : function(){
if( !this.playing ){
delete this._interval;
- return X_Callback_UN_LISTEN;
+ return X_CALLBACK_UN_LISTEN;
};
- this.proxy.dispatch( X_Event.MEDIA_PLAYING );
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING );
},
_onEnded : function(){
delete this._timerID;
if( this.playing ){
- time = X_Audio_WebAudio_context.currentTime * 1000 - this._startTime - this._endPosition + this._startPos | 0;
- //console.log( '> onEnd ' + ( this.playing && ( X_Audio_WebAudio_context.currentTime * 1000 - this._startTime ) ) + ' < ' + ( this._endPosition - this._startPos ) );
+ time = X_WebAudio_context.currentTime * 1000 - this._startTime - this._endPosition + this._startPos | 0;
+ //console.log( '> onEnd ' + ( this.playing && ( X_WebAudio_context.currentTime * 1000 - this._startTime ) ) + ' < ' + ( this._endPosition - this._startPos ) );
if( this._onended ){
// Firefox 用の対策,,,
if( time < 0 ) return;
} else {
if( time < 0 ){
- console.log( '> onEnd crt:' + ( X_Audio_WebAudio_context.currentTime * 1000 ) + ' startTime:' + this._startTime +
- ' from:' + this._startPos + ' to:' + this._endPosition );
- this._timerID = X.Timer.once( -time, this, this._onEnded );
+ //console.log( '> onEnd crt:' + ( X_WebAudio_context.currentTime * 1000 ) + ' startTime:' + this._startTime +
+ // ' from:' + this._startPos + ' to:' + this._endPosition );
+ this._timerID = X_Timer_once( -time, this, this._onEnded );
return;
};
};
- if( this.loop ){
- if( !( this.proxy.dispatch( X_Event.MEDIA_BEFORE_LOOP ) & X.Callback.PREVENT_DEFAULT ) ){
+ if( this.autoLoop ){
+ if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){
this.looped = true;
- this.proxy.dispatch( X_Event.MEDIA_LOOPED );
- this.play();
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED );
+ this.actualPlay();
};
} else {
- this.pause();
- this.proxy.dispatch( X_Event.MEDIA_ENDED );
+ this.actualPause();
+ this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED );
};
};
},
- pause : function(){
- if( !this.playing ) return this;
+ actualPause : function(){
+ //if( !this.playing ) return this;
console.log( '[WebAudio] pause' );
- this.seekTime = this.state().currentTime;
+ this.seekTime = this.getActualCurrentTime();
- this._timerID && X.Timer.remove( this._timerID );
+ this._timerID && X_Timer_remove( this._timerID );
delete this._timerID;
delete this.playing;
- if( this.source ){
- if( this.source.onended ) delete this.source.onended;
+ if( this.bufferSource ){
+ if( this.bufferSource.onended ) delete this.bufferSource.onended;
- this.source.stop ?
- this.source.stop( 0 ) : this.source.noteOff( 0 );
+ this.bufferSource.stop ?
+ this.bufferSource.stop( 0 ) : this.bufferSource[ 'noteOff' ]( 0 );
};
},
-
- state : function( obj ){
- var result;
-
- if( obj === undefined ){
- return {
- startTime : this.startTime,
- endTime : this.endTime < 0 ? this.duration : this.endTime,
- loopStartTime : this.loopStartTime < 0 ? this.startTime : this.loopStartTime,
- loopEndTime : this.loopEndTime < 0 ? ( this.endTime || this.duration ) : this.loopEndTime,
- loop : this.loop,
- looped : this.looped,
- volume : this.volume,
- playing : this.playing,
- duration : this.duration,
-
- currentTime : this.playing ? ( X_Audio_WebAudio_context.currentTime * 1000 - this._startTime + this._startPos | 0 ) : this.seekTime,
- error : this.error
- };
- };
- result = X_AudioWrapper_updateStates( this, obj );
-
+ getActualCurrentTime : function(){
+ return X_WebAudio_context.currentTime * 1000 - this._startTime + this._startPos | 0;
+ },
+
+ afterUpdateState : function( result ){
if( result & 2 || result & 1 ){ // seek
- this.play();
+ this.actualPlay();
} else
if( result & 4 ){
- this.gainNode.gain.value = this.volume;
+ this.gainNode[ 'gain' ].value = this.gain;
};
}
}
);
-
X_Audio_BACKENDS.push(
{
- backendName : 'Web Audio',
+ backendID : 1,
+
+ backendName : 'WebAudio',
+
+ canPlay : X_Audio_codecs,
- //
- detect : function( proxy, source, ext ){
- proxy.asyncDispatch( { type : X_Event.COMPLETE, canPlay : X_Audio_codecs[ ext ] } );
+ detect : function( proxy, source, ext ){
+ proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : X_Audio_codecs[ ext ] } );
},
- klass : X_Audio_WebAudioWrapper
+ klass : X_WebAudio
}
);
};