OSDN Git Service

Version 0.6.149, fix X.Audio & X.UI.
[pettanr/clientJs.git] / 0.6.x / js / 07_audio / 10_XAudioSprite.js
index 99d7782..45790ae 100644 (file)
@@ -27,30 +27,63 @@ var X_Audio_Sprite_shouldUse        = window.HTMLAudioElement && ( X_UA[ 'iOS' ]
                bgmLooped   : false,\r
                bgmPlaying  : false\r
        },\r
-       X_Audio_Sprite_instance;\r
+       X_Audio_Sprite_instance,\r
+       X_Audio_Sprite_numTracks,\r
+       X_Audio_Sprite_useVideo;\r
 \r
-X[ 'Audio' ][ 'Sprite' ] = {\r
-       \r
-       'shouldUse'        : X_Audio_Sprite_shouldUse,\r
+X[ 'AudioSprite' ] = function( setting ){\r
+       var tracks  = X_Audio_Sprite_TEMP.tracks,\r
+               bgms    = X_Audio_Sprite_TEMP.BGMs,\r
+               presets = X_Audio_Sprite_TEMP.presets,\r
+               urls    = setting[ 'urls' ],\r
+               video   = setting[ 'useVideo' ],\r
+               n       = video ? 1 : setting[ 'numTracks' ] || 1,\r
+               option  = {\r
+                       volume    : setting[ 'volume' ] || 0.5,\r
+                       autoplay  : false,\r
+                       startTime : 0,\r
+                       endTime   : X_Audio_Sprite_lengthSilence,\r
+                       loop      : true\r
+               },\r
+               k, i, v, track; \r
        \r
-       'needTouchFirst'   : X_Audio_Sprite_needTouchFirst,\r
+       if( X_Audio_Sprite_instance ){\r
+               X_Audio_Sprite_instance[ 'kill' ]();\r
+       } else {\r
+               X_Audio_Sprite_instance = X_Class_override( X_EventDispatcher(), X_Audio_Sprite_members );\r
+               X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], X_Audio_Sprite_instance, X_Audio_Sprite_handleEvent );\r
+       };\r
        \r
-       'enableMultiTrack' : X_Audio_Sprite_enableMultiTrack,\r
+       n = n <= X_Audio_Sprite_maxTracks ? n : X_Audio_Sprite_maxTracks;\r
        \r
-       'create' : function( setting ){\r
-               // close()\r
-               if( X_Audio_Sprite_instance ){\r
-                       X_Audio_Sprite_instance.close();\r
-               } else {\r
-                       X_Audio_Sprite_instance = X_Class_override( X_EventDispatcher(), X_Audio_Sprite_members );\r
-                       X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], X_Audio_Sprite_instance, X_Audio_Sprite_handleEvent );\r
+       for( k in setting ){\r
+               v = setting[ k ];\r
+               if( X_Type_isArray( v ) && v !== urls ){\r
+                       v = X_Object_cloneArray( v );\r
+                       for( i = v.length; i; ){\r
+                               --i;\r
+                               if( i !== 2 ) v[ i ] = X_AudioWrapper_timeStringToNumber( v[ i ] );\r
+                       };                                      \r
+                       if( v[ 2 ] ) bgms[ k ] = v;\r
+                       presets[ k ] = v;\r
                };\r
-               X_Audio_Sprite_instance.setup( setting );\r
-               return X_Audio_Sprite_instance;\r
-               \r
-       }\r
+       };\r
+       \r
+       X_Audio_startDetectionBackend( X_Audio_BACKENDS[ 0 ], X_Audio_Sprite_instance, X_Object_cloneArray( urls ), option );\r
+\r
+       X_Audio_Sprite_instance[ 'listenOnce' ]( [ X_EVENT_BACKEND_READY, X_EVENT_BACKEND_NONE ], X_AudioSprite_backendHandler );\r
+       X_Audio_Sprite_instance[ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, X_Audio_Sprite_handleEvent );\r
+       \r
+       X_Audio_Sprite_useVideo  = video;\r
+       X_Audio_Sprite_numTracks = X_Audio_Sprite_instance[ 'numTracks' ] = n;\r
+\r
+       return X_Audio_Sprite_instance;\r
 };\r
 \r
+X[ 'AudioSprite' ][ 'shouldUse'        ] = X_Audio_Sprite_shouldUse;\r
+X[ 'AudioSprite' ][ 'needTouchFirst'   ] = X_Audio_Sprite_needTouchFirst;\r
+X[ 'AudioSprite' ][ 'enableMultiTrack' ] = X_Audio_Sprite_enableMultiTrack;\r
+\r
 // 再生が終わっているもの、終わりかけのものを探す\r
 // TODO 終わりかけのもの、と一番古いもの、どちらを再利用するか?これ以上に細かい実装を望む場合は X.Audio.Sprite は使わず自力で実装\r
 function X_Audio_Sprite_getTrackEnded(){\r
@@ -60,7 +93,7 @@ function X_Audio_Sprite_getTrackEnded(){
        \r
        for( ; i < l; ++i ){\r
                track = tracks[ i ];\r
-               state = track.state();\r
+               state = track.getState();\r
                if( !state.playing ) return track;\r
                if( track === X_Audio_Sprite_TEMP.bgmTrack ) continue;\r
                if( state.currentTime <= X_Audio_Sprite_lengthSilence + X_Audio_Sprite_lengthDistance ) return track;\r
@@ -94,84 +127,18 @@ function X_Audio_Sprite_getTrackEnded(){
 \r
 X_Audio_Sprite_members = {\r
                \r
-               setup : function( setting ){\r
-                       \r
-                       var tracks  = X_Audio_Sprite_TEMP.tracks,\r
-                               bgms    = X_Audio_Sprite_TEMP.BGMs,\r
-                               presets = X_Audio_Sprite_TEMP.presets,\r
-                               urls    = setting[ 'urls' ],\r
-                               video   = setting[ 'useVideo' ],\r
-                               n       = video ? 1 : setting[ 'numTracks' ] || 1,\r
-                               option  = {\r
-                                       volume    : setting[ 'volume' ] || 0.5,\r
-                                       autoplay  : false,\r
-                                       startTime : 0,\r
-                                       endTime   : X_Audio_Sprite_lengthSilence,\r
-                                       loop      : true\r
-                               },\r
-                               k, i, v, track;\r
-                       \r
-                       n = n <= X_Audio_Sprite_maxTracks ? n : X_Audio_Sprite_maxTracks;\r
-                       \r
-                       for( k in setting ){\r
-                               v = setting[ k ];\r
-                               if( X_Type_isArray( v ) && v !== urls ){\r
-                                       v = X_Object_cloneArray( v );\r
-                                       for( i = v.length; i; ){\r
-                                               --i;\r
-                                               if( i !== 2 ) v[ i ] = X_AudioWrapper_timeStringToNumber( v[ i ] );\r
-                                       };                                      \r
-                                       if( v[ 2 ] ) bgms[ k ] = v;\r
-                                       presets[ k ] = v;\r
-                               };\r
-                       };\r
-                       \r
-                       for( i = 0; i < n; ++i ){\r
-                               if( video || ( i === 1 && X_Audio_Sprite_useVideoForMulti ) ){\r
-                                       option[ 'useVideo' ] = true;\r
-                               };\r
-                               tracks.push( X[ 'Audio' ]( urls, X_Object_clone( option ) ) );\r
-                       };\r
-                       \r
-                       tracks[ n - 1 ][ 'listenOnce' ]( [ X_EVENT_BACKEND_READY, X_EVENT_BACKEND_NONE ], this, X_Audio_Sprite_handleEvent );\r
-                       \r
-                       X_Audio_Sprite_instance.numTracks = n;\r
-               },\r
+               'numTracks' : 0,\r
                \r
-               close : function(){\r
-                       var tracks  = X_Audio_Sprite_TEMP.tracks,\r
-                               bgms    = X_Audio_Sprite_TEMP.BGMs,\r
-                               presets = X_Audio_Sprite_TEMP.presets,\r
-                               k;\r
-                       \r
-                       while( tracks.length ){\r
-                               tracks.pop()[ 'kill' ]();\r
-                       };\r
-                       \r
-                       for( k in bgms ){\r
-                               delete bgms[ k ];\r
-                       };\r
-                       for( k in presets ){\r
-                               delete presets[ k ];\r
-                       };\r
-                       \r
-                       X_Audio_Sprite_TEMP.bgmTrack    = null;\r
-                       X_Audio_Sprite_TEMP.bgmPosition = 0;\r
-                       X_Audio_Sprite_TEMP.bgmName     = '';\r
-                       X_Audio_Sprite_TEMP.bgmLooped   = false;\r
-                       X_Audio_Sprite_TEMP.bgmPlaying  = false;\r
-               },\r
-               \r
-               load : function(){\r
+               'load' : function(){\r
                        var tracks = X_Audio_Sprite_TEMP.tracks,\r
                                i = 0, l = tracks.length;\r
                        for( ; i < l; ++i ){\r
                                if( X_UA[ 'WinPhone' ] ){\r
                                        console.log( 'touch -> play()' );\r
                                        //tracks[ i ].play( 0, X_Audio_Sprite_lengthSilence, true, 0, X_Audio_Sprite_lengthSilence ).seek( 0 );\r
-                                       this.pause( i );\r
+                                       this[ 'pause' ]( i );\r
                                } else {\r
-                                       X_Audio_getAudioWrapper( tracks[ i ] )[ '_rawObject' ].load();\r
+                                       tracks[ i ][ '_rawObject' ].load();\r
                                };\r
                        };\r
                },\r
@@ -179,7 +146,7 @@ X_Audio_Sprite_members = {
                /*\r
                 * @return uid Number\r
                 */\r
-               play : function( name ){\r
+               'play' : function( name ){\r
                        var bgm     = X_Audio_Sprite_TEMP.bgmTrack,\r
                                tracks  = X_Audio_Sprite_TEMP.tracks,\r
                                bgms    = X_Audio_Sprite_TEMP.BGMs,\r
@@ -193,9 +160,11 @@ X_Audio_Sprite_members = {
                                                // bgm変更\r
                                                X_Audio_Sprite_TEMP.bgmName     = name;\r
                                                X_Audio_Sprite_TEMP.bgmPosition = preset[ 0 ];\r
-                                               X_Audio_Sprite_TEMP.bgmPlaying  = true;\r
                                                X_Audio_Sprite_TEMP.bgmLooped   = false;\r
                                        };\r
+                                       \r
+                                       X_Audio_Sprite_TEMP.bgmPlaying = true;\r
+                                       \r
                                        if( bgm ){\r
                                                track = bgm;\r
                                        } else\r
@@ -205,22 +174,20 @@ X_Audio_Sprite_members = {
                                                track = X_Audio_Sprite_TEMP.bgmTrack = tracks[ 0 ];\r
                                        };\r
                                        \r
-                                       if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_Audio_Sprite_handleEvent ).isPlaying() ){\r
-                                               track\r
-                                                       .state( {\r
-                                                               loop          : true,\r
-                                                               looped        : X_Audio_Sprite_TEMP.bgmLooped,\r
-                                                               currentTime   : X_Audio_Sprite_TEMP.bgmPosition,\r
-                                                               startTime     : preset[ 0 ],\r
-                                                               endTime       : preset[ 1 ],\r
-                                                               loopStartTime : preset[ 3 ],\r
-                                                               loopEndTime   : preset[ 4 ]\r
-                                                       } );\r
+                                       if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_Audio_Sprite_handleEvent ).playing ){\r
+                                               track.setState({\r
+                                                               'loop'          : true,\r
+                                                               'looped'        : X_Audio_Sprite_TEMP.bgmLooped,\r
+                                                               'currentTime'   : X_Audio_Sprite_TEMP.bgmPosition,\r
+                                                               'startTime'     : preset[ 0 ],\r
+                                                               'endTime'       : preset[ 1 ],\r
+                                                               'loopStartTime' : preset[ 3 ],\r
+                                                               'loopEndTime'   : preset[ 4 ]\r
+                                                       });\r
                                        } else {\r
-                                               track\r
-                                                       .state( { looped : X_Audio_Sprite_TEMP.bgmLooped } )\r
-                                                       .play( preset[ 0 ], preset[ 1 ], true, preset[ 3 ], preset[ 4 ] )\r
-                                                       .seek( X_Audio_Sprite_TEMP.bgmPosition );\r
+                                               track.setState( { 'looped' : X_Audio_Sprite_TEMP.bgmLooped } );\r
+                                               track.play( preset[ 0 ], preset[ 1 ], true, preset[ 3 ], preset[ 4 ] );\r
+                                               track.seek( X_Audio_Sprite_TEMP.bgmPosition );\r
                                        };\r
                                        \r
                                } else {\r
@@ -228,30 +195,29 @@ X_Audio_Sprite_members = {
                                                track = X_Audio_Sprite_getTrackEnded( X_Audio_Sprite_TEMP.bgmPlaying );\r
                                                track\r
                                                        [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_Audio_Sprite_handleEvent )\r
-                                                       .state( { looped : false } )\r
-                                                       .play( preset[ 0 ], preset[ 1 ], true, 0, X_Audio_Sprite_lengthSilence );\r
+                                                       .setState( { 'looped' : false } );\r
+                                               track.play( preset[ 0 ], preset[ 1 ], true, 0, X_Audio_Sprite_lengthSilence );\r
                                        } else {\r
                                                // single track, iOS\r
                                                if( bgm ){\r
                                                        X_Audio_Sprite_TEMP.bgmPosition = bgm.currentTime();\r
-                                                       console.log( 'bgm position : ' + X_Audio_Sprite_TEMP.bgmPosition + ' isPlay:' +  bgm.isPlaying() );\r
+                                                       //console.log( 'bgm position : ' + X_Audio_Sprite_TEMP.bgmPosition + ' isPlay:' +  bgm.playing );\r
                                                        X_Audio_Sprite_TEMP.bgmTrack    = null;\r
                                                };\r
                                                track = tracks[ 0 ];\r
                                        \r
-                                               if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_Audio_Sprite_handleEvent ).isPlaying() ){\r
-                                                       track\r
-                                                               .state( {\r
-                                                                       loop          : true,\r
-                                                                       looped        : false,\r
-                                                                       startTime     : preset[ 0 ],\r
-                                                                       endTime       : preset[ 1 ],\r
-                                                                       loopStartTime : 0,\r
-                                                                       loopEndTime   : X_Audio_Sprite_lengthSilence\r
-                                                               } );\r
+                                               if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_BEFORE_LOOP ], this, X_Audio_Sprite_handleEvent ).playing ){\r
+                                                       track.setState({\r
+                                                                       'loop'          : true,\r
+                                                                       'looped'        : false,\r
+                                                                       //'currentTime'   : preset[ 0 ],\r
+                                                                       'startTime'     : preset[ 0 ],\r
+                                                                       'endTime'       : preset[ 1 ],\r
+                                                                       'loopStartTime' : 0,\r
+                                                                       'loopEndTime'   : X_Audio_Sprite_lengthSilence\r
+                                                               });\r
                                                } else {\r
-                                                       track\r
-                                                               .play( preset[ 0 ], preset[ 1 ], true, 0, X_Audio_Sprite_lengthSilence );       \r
+                                                       track.play( preset[ 0 ], preset[ 1 ], true, 0, X_Audio_Sprite_lengthSilence );  \r
                                                };\r
                                        };\r
                                };\r
@@ -260,19 +226,20 @@ X_Audio_Sprite_members = {
                        return -1;\r
                },\r
                \r
-               pause : function( uid ){\r
+               'pause' : function( uid ){\r
                        var track = X_Audio_Sprite_TEMP.tracks[ uid ];\r
                        if( X_Audio_Sprite_TEMP.bgmTrack === track ){\r
                                X_Audio_Sprite_TEMP.bgmPosition = track.currentTime();\r
                                X_Audio_Sprite_TEMP.bgmPlaying  = false;\r
                                X_Audio_Sprite_TEMP.bgmTrack    = null;\r
                        };\r
-                       track && track.play( 0, X_Audio_Sprite_lengthSilence, true, 0, X_Audio_Sprite_lengthSilence ).seek( 0 );\r
+                       track && track.play( 0, X_Audio_Sprite_lengthSilence, true, 0, X_Audio_Sprite_lengthSilence );\r
+                       track && track.seek( 0 );\r
                        this[ 'asyncDispatch' ]( X_EVENT_MEDIA_PAUSED );\r
                        return this;\r
                },\r
                \r
-               seek : function( uid, position ){\r
+               'seek' : function( uid, position ){\r
                        var track = X_Audio_Sprite_TEMP.tracks[ uid ],\r
                                end;\r
                        if( track ){\r
@@ -283,7 +250,7 @@ X_Audio_Sprite_members = {
                        return this;\r
                },\r
                \r
-               volume : function( uid, opt_volume ){\r
+               'volume' : function( uid, opt_volume ){\r
                        var track, i;\r
                        // TODO uid = 0\r
                        if( uid === 0 ){\r
@@ -297,48 +264,64 @@ X_Audio_Sprite_members = {
                        };\r
                        track = X_Audio_Sprite_TEMP.tracks[ uid ];\r
                        if( opt_volume === undefined ){\r
-                               return track ? track.volume() : -1;\r
+                               return track ? track.gain : -1;\r
                        };\r
                        track && track.volume( opt_volume );\r
                        return this;\r
                },\r
                \r
-               state : function( uid, opt_obj ){\r
+               'state' : function( uid, opt_obj ){\r
                        var track = X_Audio_Sprite_TEMP.tracks[ uid ],\r
                                state, start, end;\r
                        // TODO uid = 0\r
                        if( opt_obj === undefined ){\r
                                // TODO pause\r
                                if( track ){\r
-                                       state = track.state();\r
+                                       state = track.getState();\r
                                        start = state.startTime;\r
                                        return {\r
-                                       'currentTime' : state.currentTime - state.startTime,\r
-                                       'playing'     : state.startTime <= state.currentTime && state.currentTime <= state.endTime,\r
-                                       'duration'    : state.endTime - state.startTime,\r
+                                       'currentTime' : state.currentTime - start,\r
+                                       'playing'     : start <= state.currentTime && state.currentTime <= state.endTime,\r
+                                       'duration'    : state.endTime - start,\r
                                        'volume'      : X_Audio_Sprite_TEMP.volume\r
                                        };\r
                                };\r
                                return { 'volume' : X_Audio_Sprite_TEMP.volume, 'playing' : false };\r
                        };\r
-                       track && track.state( opt_obj );\r
+                       track && track.setState( opt_obj );\r
                        return this;\r
                }\r
 };\r
 \r
-function X_Audio_Sprite_handleEvent( e ){\r
-       var i, tracks, track, _e;\r
+function X_AudioSprite_backendHandler( e ){\r
+       var i, backend, option, src, name, last, _e;\r
        \r
        switch( e.type ){\r
                case X_EVENT_BACKEND_READY :\r
+               \r
+                       backend = X_Audio_BACKENDS[ e[ 'backendID' ] ];\r
+                       option  = e[ 'option' ];\r
+                       \r
+                       this[ 'unlisten' ]( X_EVENT_BACKEND_NONE, X_AudioSprite_backendHandler );\r
+                       this[ 'source' ]      = src = e[ 'source' ];\r
+                       this[ 'backendName' ] = name = backend.backendName;\r
+               \r
+                       for( i = 0; i < X_Audio_Sprite_numTracks; ++i ){\r
+                               if( X_Audio_Sprite_useVideo || ( i === 1 && X_Audio_Sprite_useVideoForMulti ) ){\r
+                                       option[ 'useVideo' ] = true;\r
+                               };\r
+                               // Audiobackend の owner として null を渡すとAudioBackend 自身へ dispatch する\r
+                               X_Audio_Sprite_TEMP.tracks.push( last = backend.klass( null, e[ 'source' ], option ) );\r
+                       };\r
+\r
                        _e = {\r
                                'type'        : X_EVENT_BACKEND_READY,\r
-                               'source'      : e[ 'source' ],\r
-                               'backendName' : e[ 'backendName' ]\r
+                               'source'      : src,\r
+                               'backendName' : name\r
                        };\r
                        \r
                        if( X_Audio_Sprite_needTouchFirst ){\r
-                               if( e.backendName === 'Web Audio' ){\r
+                               if( name === 'Web Audio' ){\r
                                        _e[ 'needTouchForPlay' ] = true;\r
                                } else {\r
                                        _e[ 'needTouchForLoad' ] = true;\r
@@ -346,37 +329,46 @@ function X_Audio_Sprite_handleEvent( e ){
                        };\r
                        this[ 'asyncDispatch' ]( _e );\r
                        \r
-                       e.target\r
-                               [ 'unlisten' ]( X_EVENT_BACKEND_NONE, this, X_Audio_Sprite_handleEvent )\r
-                               [ 'listenOnce' ]( X_EVENT_READY, this, X_Audio_Sprite_handleEvent );\r
+                       last[ 'listenOnce' ]( X_EVENT_READY, this, X_AudioSprite_backendHandler );\r
 \r
                        // READY, needTouchForPlay, needTouchForLoad\r
                        if( X_Audio_HTMLAudioWrapper_durationFix ){\r
                                for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){\r
-                                       X_Audio_Sprite_instance.pause( i );\r
+                                       this[ 'pause' ]( i );\r
                                };\r
                        };\r
+                       \r
+                       return X_Callback_STOP_NOW;\r
                        break;\r
 \r
                case X_EVENT_BACKEND_NONE :\r
-                       this[ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE );\r
-                       e.target[ 'unlisten' ]( X_EVENT_BACKEND_READY, this, X_Audio_Sprite_handleEvent );\r
+                       this[ 'unlisten' ]( X_EVENT_BACKEND_READY, this, X_AudioSprite_backendHandler )\r
+                               [ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE );\r
+                       return X_Callback_STOP_NOW;\r
                        break;\r
                \r
                case X_EVENT_READY :\r
                        console.log( 'X.AudioSprite - Ready!' );\r
+                       \r
                        if( X_Audio_Sprite_needTouchAndroid ){\r
                                for( i = 0; i < X_Audio_Sprite_TEMP.tracks.length; ++i ){\r
-                                       X_Audio_Sprite_instance.pause( i );\r
+                                       this[ 'pause' ]( i );\r
                                };\r
                                e.target[ 'listenOnce' ]( X_EVENT_MEDIA_PLAYING, this, this.asyncDispatch, [ X_EVENT_READY ] ); // Android 標準ブラウザ\r
                                return;\r
                        };\r
                        this[ 'asyncDispatch' ]( X_EVENT_READY );\r
                        break;\r
-                       \r
+       };\r
+};\r
+\r
+\r
+function X_Audio_Sprite_handleEvent( e ){\r
+       var i, tracks, track, _e, k;\r
+       \r
+       switch( e.type ){\r
                case X_EVENT_MEDIA_PLAYING :\r
-                       ( e.target === X_Audio_Sprite_TEMP.bgmTrack || !e.target.state().looped ) && this[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
+                       ( e.target === X_Audio_Sprite_TEMP.bgmTrack || !e.target.looped ) && this[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
                        break;\r
                \r
                case X_EVENT_MEDIA_BEFORE_LOOP :\r
@@ -384,12 +376,14 @@ function X_Audio_Sprite_handleEvent( e ){
                                X_Audio_Sprite_TEMP.bgmLooped = true;\r
                                this[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
                        } else {\r
-                               if( e.target.state().looped ){\r
+                               if( e.target.looped ){\r
                                        //this[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
                                } else {\r
                                        this[ 'asyncDispatch' ]( X_EVENT_MEDIA_ENDED ); // TODO uid\r
                                };\r
                                \r
+                               console.log( '[AudioSprite] ' + X_Audio_Sprite_TEMP.bgmPlaying + ' ' + !X_Audio_Sprite_TEMP.bgmTrack );\r
+                               \r
                                // single track | iOS\r
                                if( X_Audio_Sprite_TEMP.bgmPlaying && !X_Audio_Sprite_TEMP.bgmTrack ){\r
                                        X_Audio_Sprite_TEMP.bgmTrack = e.target;\r
@@ -399,11 +393,12 @@ function X_Audio_Sprite_handleEvent( e ){
                        };\r
                        break;\r
                \r
+               // TODO Android Firefox で アクティブ検出できない!\r
                case X_EVENT_VIEW_ACTIVATE :\r
                        console.log( '■ アクティブ' );\r
                        // track.play(); or iOS need touch??\r
                        tracks = X_Audio_Sprite_TEMP.pauseTracks;\r
-                       while( tracks.length ) tracks.pop().play();\r
+                       while( tracks.length ) tracks.pop().actualPlay();\r
                        break;\r
 \r
                case X_EVENT_VIEW_DEACTIVATE :\r
@@ -413,13 +408,30 @@ function X_Audio_Sprite_handleEvent( e ){
                        i      = tracks.length;\r
                        for( ; i; ){\r
                                track = tracks[ --i ];\r
-                               track.isPlaying() && X_Audio_Sprite_TEMP.pauseTracks.push( track.pause() );\r
+                               track.playing && X_Audio_Sprite_TEMP.pauseTracks.push( track ) && track.pause();\r
                        };\r
                        break;\r
                \r
                case X_EVENT_KILL_INSTANCE :\r
+                       \r
+                       while( X_Audio_Sprite_TEMP.tracks.length ){\r
+                               X_Audio_Sprite_TEMP.tracks.pop()[ 'kill' ]();\r
+                       };\r
+                       \r
+                       for( k in X_Audio_Sprite_TEMP.bgms ){\r
+                               delete X_Audio_Sprite_TEMP.bgms[ k ];\r
+                       };\r
+                       for( k in X_Audio_Sprite_TEMP.presets ){\r
+                               delete X_Audio_Sprite_TEMP.presets[ k ];\r
+                       };\r
+                       \r
+                       X_Audio_Sprite_TEMP.bgmTrack    = null;\r
+                       X_Audio_Sprite_TEMP.bgmPosition = 0;\r
+                       X_Audio_Sprite_TEMP.bgmName     = '';\r
+                       X_Audio_Sprite_TEMP.bgmLooped   = false;\r
+                       X_Audio_Sprite_TEMP.bgmPlaying  = false;\r
+                       \r
                        X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE ], this, X_Audio_Sprite_handleEvent );\r
-                       this.close();\r
                        break;\r
        };\r
 };\r