-var X_Audio_WebAudio_context = window.webkitAudioContext || window.AudioContext,
+var X_Audio_WebAudio_context = !X_UA.iPhone_4s && !X_UA.iPad_2Mini1 && !X_UA.iPod_4 &&
+ !( X_UA.Gecko && X_UA.Android ) &&
+ ( window.AudioContext || window.webkitAudioContext ),
X_Audio_WebAudioWrapper;
+/*
+ * iPhone 4s 以下、iPad2以下、iPad mini 1以下, iPod touch 4G 以下は不可
+ */
if( X_Audio_WebAudio_context ){
X_Audio_WebAudio_context = new X_Audio_WebAudio_context;
loopEndTime : -1,
seekTime : -1,
duration : 0,
-
+
playing : false,
error : 0,
loop : false,
looped : false,
+ autoplay : false,
volume : 0.5,
_startTime : 0,
Constructor : function( proxy, url, option ){
var audio = X_Audio_WebAudio_getBuffer( url );
- this.url = url;
- this.closed = false;
this.proxy = proxy;
+ this.url = url;
X_AudioWrapper_updateStates( this, option );
return;
case X.Event.SUCCESS :
+ console.log( 'WebAudio xhr success! ' + !!X_Audio_WebAudio_context.decodeAudioData + ' t:' + typeof e.data );
// TODO 旧api
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext
+
+ // http://qiita.com/sou/items/5688d4e7d3a37b4e2ff1
+ // iOS 7.1 で decodeAudioData に処理が入った瞬間にスクリーンを長押しする(スクロールを繰り返す)と
+ // decoeAudioData の処理がキャンセルされることがある(エラーやコールバックの発火もなく、ただ処理が消滅する)。
+ if( X_Audio_WebAudio_context.createBuffer && X_UA.iOS ){
+ this._onDecodeSuccess( X_Audio_WebAudio_context.createBuffer( e.data, false ) );
+ } else
if( X_Audio_WebAudio_context.decodeAudioData ){
X_Audio_WebAudio_context.decodeAudioData( e.data,
this.onDecodeSuccess = X_Callback_create( this, this._onDecodeSuccess ),
case X.Event.COMPLETE :
this.error = 2;
- this.proxy.asyncDispatch( { type : 'error', message : 'xhr error' } );
+ this.proxy.asyncDispatch( { type : X.Event.ERROR, message : 'xhr error' } );
break;
};
this.xhr.unlisten( [ X.Event.PROGRESS, X.Event.SUCCESS, X.Event.COMPLETE, X.Event.CANCELED ], this );
},
_onDecodeSuccess : function( buffer ){
+ console.log( 'WebAudio decode success!' );
+
this.onDecodeSuccess && this._onDecodeComplete();
if ( !buffer ) {
- this.proxy.asyncDispatch( { type : 'error', message : 'buffer is ' + buffer } );
+ this.proxy.asyncDispatch( { type : X.Event.ERROR, message : 'buffer is ' + buffer } );
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 decoded!' );
},
_onDecodeError : function(){
+ console.log( 'WebAudio decode error!' );
this._onDecodeComplete();
this.error = 3;
- this.proxy.asyncDispatch( { type : 'error', message : 'decode error' } );
+ this.proxy.asyncDispatch( { type : X.Event.ERROR, message : 'decode error' } );
},
_onDecodeComplete : function(){
play : function(){
var begin, end;
- if( !this.buffer ) return this;
+ if( !this.buffer ){
+ this.autoplay = true;
+ return;
+ };
end = X_AudioWrapper_getEndTime( this );
begin = X_AudioWrapper_getStartTime( this, end, true );
this.gainNode.gain.value = this.volume;
- this._timerID && X.Timer.remove( this._timerID );
-
// おかしい、stop 前に外していても呼ばれる、、、@Firefox33.1
// 破棄された X.Callback が呼ばれて、obj._() でエラーになる。Firefox では、onended は使わない
if( false && 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.remove( this._timerID );
this._timerID = X.Timer.once( end - begin, this, this._onEnded );
};
delete this._interval;
return X_Callback_UN_LISTEN;
};
- this.proxy.dispatch( 'timeupdate' );
+ this.proxy.dispatch( X.Event.MEDIA_PLAYING );
},
_onEnded : function(){
// Firefox 用の対策,,,
if( time < 0 ) return;
} else {
- if( time < -16 ){
- console.log( '> onEnd ' + time );
+ if( time < 0 ){
+ console.log( '> onEnd ' + ( -time ) + ' start:' + this._startTime + '-' + this._endTime );
this._timerID = X.Timer.once( -time, this, this._onEnded );
return;
};
};
if( this.loop ){
- this.looped = true;
- this.play();
- this.proxy.dispatch( 'looped' );
+ if( !( this.proxy.dispatch( X.Event.MEDIA_BEFORE_LOOP ) & X.Callback.PREVENT_DEFAULT ) ){
+ this.looped = true;
+ this.proxy.dispatch( X.Event.MEDIA_LOOPED );
+ this.play();
+ };
} else {
this.pause();
- this.proxy.dispatch( 'ended' );
+ this.proxy.dispatch( X.Event.MEDIA_ENDED );
};
};
},
console.log( '[WebAudio] pause' );
+ this.seekTime = this.state().currentTime;
+
this._timerID && X.Timer.remove( this._timerID );
delete this._timerID;
delete this.playing;
},
state : function( obj ){
- var time = this.playing ? ( X_Audio_WebAudio_context.currentTime * 1000 - this._playTime ) : 0,
- result;
+ var result;
if( obj === undefined ){
return {
playing : this.playing,
duration : this.duration,
- currentTime : time + this._startTime,
+ currentTime : this.playing ? ( X_Audio_WebAudio_context.currentTime * 1000 - this._playTime + this._startTime | 0 ) : this.seekTime,
error : this.error
};
};
result = X_AudioWrapper_updateStates( this, obj );
- if( result & 2 ){ // seek
+ if( result & 2 || result & 1 ){ // seek
this.play();
} else
- if( result & 1 ){
- this.play();
- } else
if( result & 4 ){
this.gainNode.gain.value = this.volume;
};
}
);
-
+
+
X_Audio_BACKENDS.push(
{
backendName : 'Web Audio',
+ //
detect : function( proxy, source, ext ){
- var ok = ext === 'mp3' || ext === 'ogg';
-
- proxy.asyncDispatch( ok ? 'support' : 'nosupport' );
+ proxy.asyncDispatch( X_Audio_codecs[ ext ] ? X_Audio_CAN_PLAY : X_Audio_NOT_PLAY );
},
klass : X_Audio_WebAudioWrapper
}
);
-
};