From: itozyun Date: Tue, 11 Nov 2014 07:36:07 +0000 (+0900) Subject: forgot to commit... X-Git-Url: http://git.osdn.jp/view?a=commitdiff_plain;h=9052863126b700b4a60d22b95532b4efedd055d0;p=pettanr%2FclientJs.git forgot to commit... --- diff --git a/0.6.x/js/07_audio/01_XWebAudio.js b/0.6.x/js/07_audio/01_XWebAudio.js new file mode 100644 index 0000000..8299229 --- /dev/null +++ b/0.6.x/js/07_audio/01_XWebAudio.js @@ -0,0 +1,283 @@ + +var X_Audio_WebAudio_context = window.webkitAudioContext || window.AudioContext, + X_Audio_WebAudio_LIVE_LIST = [], + X_Audio_WebAudio_POOL_LIST = [], + X_Audio_WebAudio, X_Audio_WebAudioWrapper, X_Audio_rawAudio; + +if( X_Audio_WebAudio_context ){ + + X_Audio_WebAudio_context = new X_Audio_WebAudio_context; + + function getWebAudioWrapper( proxy ){ + var i = X_Audio_WebAudio_LIVE_LIST.length; + for( ; i; ){ + if( X_Audio_WebAudio_LIVE_LIST[ --i ].proxy === proxy ) return X_Audio_WebAudio_LIVE_LIST[ i ]; + }; + }; + + X_Audio_WebAudio = + { + backendName : 'Web Audio', + + detect : function( proxy, source, ext ){ + var ok = ext === 'mp3' || ext === 'ogg'; + + proxy.asyncDispatch( ok ? 'support' : 'nosupport' ); + }, + + register : function( proxy, source, option ){ + X_Audio_WebAudio_LIVE_LIST.push( new X_Audio_WebAudioWrapper( proxy, source, option ) ); + }, + + close : function( proxy ){ + return getWebAudioWrapper( proxy ).close(); + }, + + play : function( proxy, startTime, endTime, loop, loopStartTime ){ + return getWebAudioWrapper( proxy ).play( startTime, endTime, loop, loopStartTime ); + }, + + pause : function( proxy ){ + return getWebAudioWrapper( proxy ).pause(); + }, + + state : function( proxy, obj ){ + return getWebAudioWrapper( proxy ).state( obj ); + } + }; + + X_Audio_BACKENDS.push( X_Audio_WebAudio ); + + X_Audio_WebAudioWrapper = X.EventDispatcher.inherits( + 'X.AV.WebAudioWrapper', + X.Class.POOL_OBJECT, + { + + proxy : null, + + startTime : 0, + endTime : 0, + loopStartTime : 0, + seekTime : 0, + duration : 0, + + playing : false, + error : 0, + loop : false, + volume : 0.5, + + _startTime : 0, + _playTime : 0, + _timerID : 0, + _interval : 0, + buffer : null, + gainNode : null, + _onended : null, + + xhr : null, + onDecodeSuccess : null, + onDecodeError : null, + + Constructor : function( proxy, source, option ){ + this.closed = false; + this.proxy = proxy; + this.xhr = X.Net.xhrGet( source, 'arraybuffer' ) + .listen( X.Event.PROGRESS, this ) + .listenOnce( [ X.Event.SUCCESS, X.Event.COMPLETE, X.Event.CANCELED ], this ); + X_AudioWrapper_updateStates( this, option ); + }, + + handleEvent : function( e ){ + switch( e.type ){ + case X.Event.PROGRESS : + e.percent ? + this.proxy.dispatch( { type : 'progress', percent : e.percent } ) : + this.proxy.dispatch( 'loadstart' ); + return; + + case X.Event.SUCCESS : + X_Audio_WebAudio_context.decodeAudioData( e.data, + this.callbackDecodeSuccess = X_Callback_create( this, this._onDecodeSuccess ), + this.callbackDecodeError = X_Callback_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 : 'error', message : 'xhr error' } ); + break; + }; + this.xhr.unlisten( [ X.Event.PROGRESS, X.Event.SUCCESS, X.Event.COMPLETE, X.Event.CANCELED ], this ); + delete this.xhr; + }, + + _onDecodeSuccess : function( buffer ){ + this._onDecodeComplete(); + + if ( !buffer ) { + this.proxy.asyncDispatch( { type : 'error', message : 'buffer is ' + buffer } ); + return; + }; + + this.buffer = buffer; + this.duration = buffer.duration * 1000; + this.endTime = this.endTime || this.duration; + + this.proxy.asyncDispatch( 'loadedmetadata' ); + this.proxy.asyncDispatch( 'loadeddata' ); + this.proxy.asyncDispatch( 'canplay' ); + this.proxy.asyncDispatch( 'canplaythrough' ); + }, + + _onDecodeError : function(){ + this._onDecodeComplete(); + this.error = 3; + this.proxy.asyncDispatch( { type : 'error', message : 'decode error' } ); + }, + + _onDecodeComplete : function(){ + X_Callback_correct( this.callbackDecodeSuccess ); + delete this.callbackDecodeSuccess; + X_Callback_correct( this.callbackDecodeError ); + delete this.callbackDecodeError; + }, + + close : function(){ + delete this.buffer; + + this.playing && this.pause(); + this.source && this._sourceDispose(); + + this._onended && X_Callback_correct( this._onended ); + + this.gainNode && this.gainNode.disconnect(); + }, + + _sourceDispose : function(){ + this.source && this.source.disconnect(); + delete this.source.onended; + delete this.source; + }, + + play : function( seekTime ){ + var begin; + + if( !this.buffer ) return this; + + begin = ( seekTime || seekTime === 0 ) ? seekTime : this.playing ? this.loopStartTime : this.startTime; + + console.log( '[WebAudio] play' ); + + if( this.source ) this._sourceDispose(); + if( !this.gainNode ) this.gainNode = X_Audio_WebAudio_context.createGain(); + + this.source = X_Audio_WebAudio_context.createBufferSource(); + this.source.buffer = this.buffer; + this.source.connect( this.gainNode ); + + this.gainNode.connect( X_Audio_WebAudio_context.destination ); + this.gainNode.gain.value = this.volume; + + this._timerID && X.Timer.remove( this._timerID ); + + // おかしい、stop 前に外していても呼ばれる、、、@Firefox + if( this.source.onended !== undefined ){ + //console.log( '> use onended' ); + this.source.onended = this._onended || ( this._onended = X_Callback_create( this, this._onEnded ) ); + } else { + this._timerID = X.Timer.once( this.endTime - begin, this, this._onEnded ); + }; + + if( this.source.start ){ + this.source.start( 0, begin / 1000, this.endTime / 1000 ); + } else { + this.source.noteGrainOn( 0, begin / 1000, this.endTime / 1000 ); + }; + + this.playing = true; + this._startTime = begin; + this._playTime = X_Audio_WebAudio_context.currentTime * 1000; + this._interval = this._interval || X.Timer.add( 1000, 0, this, this._onInterval ); + }, + + _onInterval : function(){ + if( !this.playing ){ + delete this._interval; + return X_Callback_UN_LISTEN; + }; + this.proxy.dispatch( 'timeupdate' ); + }, + + _onEnded : function(){ + delete this._timerID; + if( this.playing ){ + console.log( '> onEnd ' + ( this.playing && ( X_Audio_WebAudio_context.currentTime * 1000 - this._playTime ) ) + ' < ' + ( this.endTime - this._startTime ) ); + // Firefox 用の対策,,, + if( X_Audio_WebAudio_context.currentTime * 1000 - this._playTime < this.endTime - this._startTime ) return; + + if( this.loop ){ + this.play(); + } else { + this.pause(); + this.proxy.dispatch( 'ended' ); + }; + }; + }, + + pause : function(){ + if( !this.playing ) return this; + + console.log( '[WebAudio] pause' ); + + this._timerID && X.Timer.remove( this._timerID ); + delete this._timerID; + delete this.playing; + + if( this.source ){ + if( this.source.onended ) delete this.source.onended; + + this.source.stop ? + this.source.stop( 0 ) : this.source.noteOff( 0 ); + }; + }, + + state : function( obj ){ + var time = this.playing ? ( X_Audio_WebAudio_context.currentTime * 1000 - this._playTime ) : 0, + result, halfway; + + if( obj === undefined ){ + return { + startTime : this.startTime, + endTime : this.endTime, + loopStartTime : this.loopStartTime, + currentTime : time + this._startTime, + loop : this.loop, + volume : this.volume, + error : this.error, + playing : this.playing, + duration : this.duration + }; + }; + + result = X_AudioWrapper_updateStates( this, obj ); + + if( result & 2 ){ // seek + this.play( this.seekTime ); + delete this.seekTime; + } else + if( result & 1 ){ + this.play(); + } else + if( result & 4 ){ + this.gainNode.gain.value = this.volume; + }; + } + + } + ); + +}; diff --git a/0.6.x/js/import.js b/0.6.x/js/import.js index dba0ff4..9dcc19f 100644 --- a/0.6.x/js/import.js +++ b/0.6.x/js/import.js @@ -55,7 +55,7 @@ document.write( [ 'js/06_net/04_XNetImage.js', 'js/07_audio/00_XAudio.js', - //'js/07_audio/01_XWebAudio.js', + 'js/07_audio/01_XWebAudio.js', 'js/07_audio/02_XHTMLAudio.js', 'js/07_audio/03_XSilverlightAudio.js'