X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F07_audio%2F01_XWebAudio.js;h=1cc3cba7b5cbe5e99845ef6b27f407bcf49d3ac2;hb=4e4ab3be10850546063d4a4b93250ed142bb8cd2;hp=522443dace906cad48136cf5fee45db77074eebe;hpb=1ed2190f012cf923f7e48d3c0d122aa56c56c5f3;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/07_audio/01_XWebAudio.js b/0.6.x/js/07_audio/01_XWebAudio.js index 522443d..1cc3cba 100644 --- a/0.6.x/js/07_audio/01_XWebAudio.js +++ b/0.6.x/js/07_audio/01_XWebAudio.js @@ -1,8 +1,8 @@ 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(); + //a = document.createElement( 'audio' ); + //a.src = s; + //a.load(); return a; } : // Android1.6 + MobileOpera12 HTMLAudio はいるが呼ぶとクラッシュする @@ -78,14 +78,23 @@ if( X_Audio_constructor ){ }; -var X_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] && - // TODO なんで fennec を禁止? - !( X_UA[ 'Gecko' ] && X_UA[ 'Android' ] ) && +var X_WebAudio_context = // 4s 以下ではない iPad 2G または iPad mini 1G 以下ではない, iPod touch 4G 以下ではない + !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] && + // iOS7 以上で HTML Audio が鳴らない問題を見ていくよ + // !X_UA[ 'iOS' ] && + // Android2 + Gecko で WebAudio が極めて不安定 + !( X_UA[ 'Fennec' ] && X_UA[ 'Android' ] < 3 ) && + // AOSP でも WebAudio を不完全に実装するものがある, touch の有無も不明のため一律に切ってしまう + !X_UA[ 'AOSP' ] && !( X_UA[ 'ChromeWV' ] < 5 ) && + // Blink HTMLAudio 調査用 + //!X_UA[ 'Blink' ] && // Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる // Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる - !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 42 && X_UA[ 'Windows' ] ) && + !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 46 && X_UA[ 'Windows' ] ) && ( window[ 'AudioContext' ] || window[ 'webkitAudioContext' ] ), - X_WebAudio_BUFFER_LIST = [], + X_WebAudio_BUFFER_LIST = [], + X_WebAudio_need1stTouch = X_UA[ 'iOS' ], + X_WebAudio_touchState = X_WebAudio_need1stTouch, X_WebAudio, X_WebAudio_BufferLoader, X_WebAudio_fpsFix; @@ -120,9 +129,13 @@ if( X_WebAudio_context ){ }, handleEvent : function( e ){ + var i, l; + switch( e.type ){ case X_EVENT_PROGRESS : - this[ 'dispatch' ]( { type : 'progress', 'percent' : e[ 'percent' ] } ); + for( i = 0, l = this.webAudioList.length; i < l; ++i ){ + this.webAudioList[ i ][ 'dispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : e[ 'percent' ] } ); + }; return; case X_EVENT_SUCCESS : @@ -155,7 +168,7 @@ if( X_WebAudio_context ){ _onDecodeSuccess : function( buffer ){ this.onDecodeSuccess && this._onDecodeComplete(); - if ( !buffer ) { + if( !buffer ){ this.errorState = 2; this[ 'asyncDispatch' ]( X_EVENT_COMPLETE ); return; @@ -187,9 +200,10 @@ if( X_WebAudio_context ){ unregister : function( webAudio ){ var list = this.webAudioList, i = list.indexOf( webAudio ); + if( 0 < i ){ list.splice( i, 1 ); - if( list.length ){ + if( !list.length ){ this.xhr && this.xhr[ 'kill' ](); this[ 'kill' ](); }; @@ -210,14 +224,14 @@ if( X_WebAudio_context ){ _startPos : 0, _endPosition : 0, _startTime : 0, - _timerID : 0, + //_timerID : 0, _interval : 0, audioBuffer : null, bufferSource : null, gainNode : null, - _onended : null, + //_onended : null, - 'Constructor' : function( target, url, option ){ + 'Constructor' : function( disatcher, url, option ){ var i = 0, l = X_WebAudio_BUFFER_LIST.length, loader; @@ -245,8 +259,7 @@ if( X_WebAudio_context ){ this.loader = loader = X_WebAudio_BufferLoader( this, url ); }; - this.target = target || this; - + this.disatcher = disatcher || this; this.setState( option ); this[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, this.onKill ); @@ -267,7 +280,7 @@ if( X_WebAudio_context ){ this.playing && this.actualPause(); this.bufferSource && this._sourceDispose(); - this._onended && X_Closure_correct( this._onended ); + //this._onended && X_Closure_correct( this._onended ); this.gainNode && this.gainNode.disconnect(); }, @@ -279,8 +292,7 @@ if( X_WebAudio_context ){ if ( !buffer ) { this.error = loader.errorState; - - this.target[ 'dispatch' ]({ + this.disatcher[ 'dispatch' ]({ type : X_EVENT_ERROR, error : loader.errorState, message : loader.errorState === 1 ? @@ -294,36 +306,52 @@ if( X_WebAudio_context ){ this.audioBuffer = buffer; this.duration = buffer.duration * 1000; - this.target[ 'asyncDispatch' ]( X_EVENT_READY ); - - console.log( 'WebAudio buffer ready' ); - - this.autoplay && X_Timer_once( 16, this, this.play ); - + this.disatcher[ 'asyncDispatch' ]( X_WebAudio_touchState ? X_EVENT_MEDIA_WAIT_FOR_TOUCH : X_EVENT_READY ); }, actualPlay : function(){ - var begin, end; + var e, begin, end; + + console.log( '[WebAudio] play abuf:' + !!this.audioBuffer ); if( !this.audioBuffer ){ - this.autoplay = true; + this._playReserved = true; return; }; + if( X_WebAudio_touchState ){ + e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ]; + if( !e || !e[ 'pointerType' ] ){ + // alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) ); + return; + }; + // http://qiita.com/uupaa/items/e5856e3cb2a9fc8c5507 + // iOS9 + touchstart で呼んでいた場合、 X_ViewPort['listenOnce']('pointerup',this,this.actualPlay()) + this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY ); + }; + X_WebAudio_touchState = false; + end = X_Audio_getEndTime( this ); begin = X_Audio_getStartTime( this, end, true ); - console.log( '[WebAudio] play ' + begin + ' -> ' + end ); + console.log( '[WebAudio] play ' + begin + ' -> ' + end + ' loop: ' + this.autoLoop + ' :' + this.loopStartTime + ' -> ' + this.loopEndTime ); if( this.bufferSource ) this._sourceDispose(); if( !this.gainNode ){ this.gainNode = X_WebAudio_context[ 'createGain' ] ? X_WebAudio_context[ 'createGain' ]() : X_WebAudio_context[ 'createGainNode' ](); - this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] ); + this.gainNode[ 'connect' ]( X_WebAudio_context[ 'destination' ] ); }; + this.bufferSource = X_WebAudio_context[ 'createBufferSource' ](); this.bufferSource.buffer = this.audioBuffer; - this.bufferSource[ 'connect' ]( this.gainNode ); + /* win8.1 Firefox45, win8.1 Chrome48 で動かなくなる... + if( this.bufferSource[ 'loop' ] = this.autoLoop ){ + this.bufferSource[ 'loopStart' ] = 0 <= this.loopStartTime ? this.loopStartTime / 1000 : begin / 1000; + this.bufferSource[ 'loopEnd' ] = 0 <= this.loopEndTime ? this.loopEndTime / 1000 : end / 1000; + }; */ + + this.bufferSource[ 'connect' ]( this.gainNode ); this.gainNode[ 'gain' ].value = this.gain; // おかしい、stop 前に外していても呼ばれる、、、@Firefox33.1 @@ -333,83 +361,78 @@ if( X_WebAudio_context ){ //console.log( '> use 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 ); + //this._timerID && X_Timer_remove( this._timerID ); + //this._timerID = X_Timer_once( end - begin, this, this._onEnded ); //}; if( this.bufferSource.start ){ - this.bufferSource.start( 0, begin / 1000, end / 1000 ); + this.bufferSource.start( 0, begin / 1000, ( end - begin ) / 1000 ); + } else + if( this.bufferSource[ 'noteOn' ] ){ + this.bufferSource[ 'noteOn' ]( 0, begin / 1000, ( end - begin ) / 1000 ); } else { - this.bufferSource[ 'noteGrainOn' ]( 0, begin / 1000, end / 1000 ); + this.bufferSource[ 'noteGrainOn' ]( 0, begin / 1000, ( end - begin ) / 1000 ); }; this.playing = true; this._startPos = begin; this._endPosition = end; this._startTime = X_WebAudio_context.currentTime * 1000; - this._interval = this._interval || X_Timer_add( 1000, 0, this, this._onInterval ); + this._interval = this._interval || X_Timer_add( 100, 0, this, this._onInterval ); }, _sourceDispose : function(){ this.bufferSource.disconnect(); - delete this.bufferSource.onended; + //delete this.bufferSource.onended; delete this.bufferSource; }, + /* _onInterval : function(){ if( !this.playing ){ delete this._interval; return X_CALLBACK_UN_LISTEN; }; - this.target[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING ); - }, - - _onEnded : function(){ + this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING ); + }, */ + + _onInterval : function(){ var time; - delete this._timerID; if( this.playing ){ + // TODO 再生中に終了時間だけ変えた場合! 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_WebAudio_context.currentTime * 1000 ) + ' startTime:' + this._startTime + - // ' from:' + this._startPos + ' to:' + this._endPosition ); - this._timerID = X_Timer_once( -time, this, this._onEnded ); - return; - }; - }; + + if( time < 0 ){ + this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_PLAYING ); + return; + }; if( this.autoLoop ){ - if( !( this.target[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){ + if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){ this.looped = true; - this.target[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED ); + this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_LOOPED ); this.actualPlay(); + } else { + delete this._interval; + return X_CALLBACK_UN_LISTEN; }; } else { this.actualPause(); - this.target[ 'dispatch' ]( X_EVENT_MEDIA_ENDED ); + this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_ENDED ); }; }; }, actualPause : function(){ - //if( !this.playing ) return this; - console.log( '[WebAudio] pause' ); - this.seekTime = this.getActualCurrentTime(); - - this._timerID && X_Timer_remove( this._timerID ); - delete this._timerID; + this._interval && X_Timer_remove( this._interval ); + delete this._interval; delete this.playing; if( this.bufferSource ){ - if( this.bufferSource.onended ) delete this.bufferSource.onended; - this.bufferSource.stop ? this.bufferSource.stop( 0 ) : this.bufferSource[ 'noteOff' ]( 0 ); }; @@ -439,7 +462,7 @@ if( X_WebAudio_context ){ canPlay : X_Audio_codecs, - detect : function( proxy, source, ext ){ + detect : function( proxy, ext /* hash */ ){ proxy[ 'asyncDispatch' ]( { type : X_EVENT_COMPLETE, canPlay : X_Audio_codecs[ ext ] } ); },