docs: function() {
        var self = this;
        var args = arguments;
        var rate, id;
  
        // Determine the values based on arguments.
        if (args.length === 0) {
          // We will simply return the current rate of the first node.
          id = self._sounds[0]._id;
        } else if (args.length === 1) {
          // First check if this is an ID, and if not, assume it is a new rate value.
          var ids = self._getSoundIds();
          var index = ids.indexOf(args[0]);
          if (index >= 0) {
            id = parseInt(args[0], 10);
          } else {
            rate = parseFloat(args[0]);
          }
        } else if (args.length === 2) {
          rate = parseFloat(args[0]);
          id = parseInt(args[1], 10);
        }
  
        // Update the playback rate or return the current value.
        var sound;
        if (typeof rate === 'number') {
          // If the sound hasn't loaded, add it to the load queue to change playback rate when capable.
          if (self._state !== 'loaded' || self._playLock) {
            self._queue.push({
              event: 'rate',
              action: function() {
                self.rate.apply(self, args);
              }
            });
  
            return self;
          }
  
          // Set the group rate.
          if (typeof id === 'undefined') {
            self._rate = rate;
          }
  
          // Update one or all volumes.
          id = self._getSoundIds(id);
          for (var i=0; i<id.length; i++) {
            // Get the sound.
            sound = self._soundById(id[i]);
  
            if (sound) {
              // Keep track of our position when the rate changed and update the playback
              // start position so we can properly adjust the seek position for time elapsed.
              if (self.playing(id[i])) {
                sound._rateSeek = self.seek(id[i]);
                sound._playStart = self._webAudio ? Howler.ctx.currentTime : sound._playStart;
              }
              sound._rate = rate;
  
              // Change the playback rate.
              if (self._webAudio && sound._node && sound._node.bufferSource) {
                sound._node.bufferSource.playbackRate.setValueAtTime(rate, Howler.ctx.currentTime);
              } else if (sound._node) {
                sound._node.playbackRate = rate;
              }
  
              // Reset the timers.
              var seek = self.seek(id[i]);
              var duration = ((self._sprite[sound._sprite][0] + self._sprite[sound._sprite][1]) / 1000) - seek;
              var timeout = (duration * 1000) / Math.abs(sound._rate);
  
              // Start a new end timer if sound is already playing.
              if (self._endTimers[id[i]] || !sound._paused) {
                self._clearTimer(id[i]);
                self._endTimers[id[i]] = setTimeout(self._ended.bind(self, sound), timeout);
              }
  
              self._emit('rate', sound._id);
            }
          }
        } else {
          sound = self._soundById(id);
          return sound ? sound._rate : self._rate;
        }
  
        return self;
      }