public function close()
    {
        $deferred = new Deferred();

        if (! $this->ready) {
            $deferred->reject(new \Exception('Voice Client is not connected.'));

            return $deferred->promise();
        }

        $this->stop();
        $this->setSpeaking(false);
        $this->ready = false;

        $this->mainSend([
            'op' => Op::OP_VOICE_STATE_UPDATE,
            'd'  => [
                'guild_id'   => $this->channel->guild_id,
                'channel_id' => null,
                'self_mute'  => true,
                'self_deaf'  => true,
            ],
        ]);

        $this->client->close();
        $this->voiceWebsocket->close();

        $this->heartbeat_interval = null;
        $this->loop->cancelTimer($this->heartbeat);
        $this->loop->cancelTimer($this->udpHeartbeat);
        $this->heartbeat      = null;
        $this->udpHeartbeat   = null;
        $this->seq            = 0;
        $this->timestamp      = 0;
        $this->sentLoginFrame = false;
        $this->startTime      = null;
        $this->streamTime     = 0;
        $this->speakingStatus = new Collection([], 'ssrc');

        $this->emit('close');

        $deferred->resolve();

        return $deferred->promise();
    }