docs: function(from, to, len, id) {
        var self = this;
  
        // If the sound hasn't loaded, add it to the load queue to fade when capable.
        if (self._state !== 'loaded' || self._playLock) {
          self._queue.push({
            event: 'fade',
            action: function() {
              self.fade(from, to, len, id);
            }
          });
  
          return self;
        }
  
        // Make sure the to/from/len values are numbers.
        from = parseFloat(from);
        to = parseFloat(to);
        len = parseFloat(len);
  
        // Set the volume to the start position.
        self.volume(from, id);
  
        // Fade the volume of one or all sounds.
        var ids = self._getSoundIds(id);
        for (var i=0; i<ids.length; i++) {
          // Get the sound.
          var sound = self._soundById(ids[i]);
  
          // Create a linear fade or fall back to timeouts with HTML5 Audio.
          if (sound) {
            // Stop the previous fade if no sprite is being used (otherwise, volume handles this).
            if (!id) {
              self._stopFade(ids[i]);
            }
  
            // If we are using Web Audio, let the native methods do the actual fade.
            if (self._webAudio && !sound._muted) {
              var currentTime = Howler.ctx.currentTime;
              var end = currentTime + (len / 1000);
              sound._volume = from;
              sound._node.gain.setValueAtTime(from, currentTime);
              sound._node.gain.linearRampToValueAtTime(to, end);
            }
  
            self._startFadeInterval(sound, from, to, len, ids[i], typeof id === 'undefined');
          }
        }
  
        return self;
      }