dist/howler.js
function(sound) {
      var self = this;
      var sprite = sound._sprite;

      // If we are using IE and there was network latency we may be clipping
      // audio before it completes playing. Lets check the node to make sure it
      // believes it has completed, before ending the playback.
      if (!self._webAudio && sound._node && !sound._node.paused && !sound._node.ended && sound._node.currentTime < sound._stop) {
        setTimeout(self._ended.bind(self, sound), 100);
        return self;
      }

      // Should this sound loop?
      var loop = !!(sound._loop || self._sprite[sprite][2]);

      // Fire the ended event.
      self._emit('end', sound._id);

      // Restart the playback for HTML5 Audio loop.
      if (!self._webAudio && loop) {
        self.stop(sound._id, true).play(sound._id);
      }

      // Restart this timer if on a Web Audio loop.
      if (self._webAudio && loop) {
        self._emit('play', sound._id);
        sound._seek = sound._start || 0;
        sound._rateSeek = 0;
        sound._playStart = Howler.ctx.currentTime;

        var timeout = ((sound._stop - sound._start) * 1000) / Math.abs(sound._rate);
        self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
      }

      // Mark the node as paused.
      if (self._webAudio && !loop) {
        sound._paused = true;
        sound._ended = true;
        sound._seek = sound._start || 0;
        sound._rateSeek = 0;
        self._clearTimer(sound._id);

        // Clean up the buffer source.
        self._cleanBuffer(sound._node);

        // Attempt to auto-suspend AudioContext if no sounds are still playing.
        Howler._autoSuspend();
      }

      // When using a sprite, end the track.
      if (!self._webAudio && !loop) {
        self.stop(sound._id, true);
      }

      return self;
    }
function(sound) {
      var self = this;
      var sprite = sound._sprite;

      // If we are using IE and there was network latency we may be clipping
      // audio before it completes playing. Lets check the node to make sure it
      // believes it has completed, before ending the playback.
      if (!self._webAudio && sound._node && !sound._node.paused && !sound._node.ended && sound._node.currentTime < sound._stop) {
        setTimeout(self._ended.bind(self, sound), 100);
        return self;
      }

      // Should this sound loop?
      var loop = !!(sound._loop || self._sprite[sprite][2]);

      // Fire the ended event.
      self._emit('end', sound._id);

      // Restart the playback for HTML5 Audio loop.
      if (!self._webAudio && loop) {
        self.stop(sound._id, true).play(sound._id);
      }

      // Restart this timer if on a Web Audio loop.
      if (self._webAudio && loop) {
        self._emit('play', sound._id);
        sound._seek = sound._start || 0;
        sound._rateSeek = 0;
        sound._playStart = Howler.ctx.currentTime;

        var timeout = ((sound._stop - sound._start) * 1000) / Math.abs(sound._rate);
        self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
      }

      // Mark the node as paused.
      if (self._webAudio && !loop) {
        sound._paused = true;
        sound._ended = true;
        sound._seek = sound._start || 0;
        sound._rateSeek = 0;
        self._clearTimer(sound._id);

        // Clean up the buffer source.
        self._cleanBuffer(sound._node);

        // Attempt to auto-suspend AudioContext if no sounds are still playing.
        Howler._autoSuspend();
      }

      // When using a sprite, end the track.
      if (!self._webAudio && !loop) {
        self.stop(sound._id, true);
      }

      return self;
    }
function ( sound ) { var self = this ; var sprite = sound . _sprite ; // If we are using IE and there was network latency we may be clipping // audio before it completes playing. Lets check the node to make sure it // believes it has completed, before ending the playback. if ( ! self . _webAudio && sound . _node && ! sound . _node . paused && ! sound . _node . ended && sound . _node . currentTime < sound . _stop ) { setTimeout ( self . _ended . bind ( self , sound ) , 100 ) ; return self ; } // Should this sound loop? var loop = ! ! ( sound . _loop || self . _sprite [ sprite ] [ 2 ] ) ; // Fire the ended event. self . _emit ( 'end' , sound . _id ) ; // Restart the playback for HTML5 Audio loop. if ( ! self . _webAudio && loop ) { self . stop ( sound . _id , true ) . play ( sound . _id ) ; } // Restart this timer if on a Web Audio loop. if ( self . _webAudio && loop ) { self . _emit ( 'play' , sound . _id ) ; sound . _seek = sound . _start || 0 ; sound . _rateSeek = 0 ; sound . _playStart = Howler . ctx . currentTime ; var timeout = ( ( sound . _stop - sound . _start ) * 1000 ) / Math . abs ( sound . _rate ) ; self . _endTimers [ sound . _id ] = setTimeout ( self . _ended . bind ( self , sound ) , timeout ) ; } // Mark the node as paused. if ( self . _webAudio && ! loop ) { sound . _paused = true ; sound . _ended = true ; sound . _seek = sound . _start || 0 ; sound . _rateSeek = 0 ; self . _clearTimer ( sound . _id ) ; // Clean up the buffer source. self . _cleanBuffer ( sound . _node ) ; // Attempt to auto-suspend AudioContext if no sounds are still playing. Howler . _autoSuspend ( ) ; } // When using a sprite, end the track. if ( ! self . _webAudio && ! loop ) { self . stop ( sound . _id , true ) ; } return self ; }
Fired when playback ends at the end of the duration.
@param  {Sound} sound The sound object to work with.
@return {Howl}
Fired when playback ends at the end of the duration .