Voice: Updated README

This commit is contained in:
diamondburned (Forefront) 2020-04-24 20:14:06 -07:00
parent ccf4c69801
commit f2d93fe2ba
3 changed files with 32 additions and 41 deletions

View File

@ -16,47 +16,48 @@ the stored `*Voice` instance
---
* The **library** sends a [Voice State Update](https://discordapp.com/developers/docs/topics/voice-connections#retrieving-voice-server-information-gateway-voice-state-update-example)
to the **Discord Gateway**
to the **Discord Gateway**.
* The **library** waits until it receives a [Voice Server Update](https://discordapp.com/developers/docs/topics/voice-connections#retrieving-voice-server-information-example-voice-server-update-payload)
from the **Discord Gateway**
* Once a *Voice Server Update* event is received, a new connection is opened to the **Discord Voice Gateway**
from the **Discord Gateway**.
* Once a *Voice Server Update* event is received, a new connection is opened to the **Discord Voice Gateway**.
---
* When the connection is opened an [Identify Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload)
or [Resume Event](https://discordapp.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload)
is sent to the **Discord Voice Gateway** depending on if the **library** is reconnecting
* The **Discord Voice Gateway** should respond with a [Hello Event](https://discordapp.com/developers/docs/topics/voice-connections#heartbeating-example-hello-payload-since-v3)
which will be used to create a new `*gateway.Pacemaker` and start sending heartbeats to the **Discord Voice Gateway**
* The **Discord Voice Gateway** will first send a [Hello Event](https://discordapp.com/developers/docs/topics/voice-connections#heartbeating-example-hello-payload-since-v3)
which will be used to create a new `*heart.PacemakerLoop` and start sending heartbeats to the **Discord Voice Gateway**.
* Afterwards, an [Identify Command](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload)
or [Resume Command](https://discordapp.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload)
is sent to the **Discord Voice Gateway** depending on whether or not the **library** is reconnecting.
---
* The **Discord Voice Gateway** should also respond with a [Ready Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload)
once the connection is opened, providing the required information to connect to a **Voice Server**
* The **Discord Voice Gateway** should then respond with a [Ready Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload)
once the connection is opened, providing the required information to connect to a **Voice Server**.
* Using the information provided in the *Ready Event*, a new UDP connection is opened to the **Voice Server**
and [IP Discovery](https://discordapp.com/developers/docs/topics/voice-connections#ip-discovery) occurs
and [IP Discovery](https://discordapp.com/developers/docs/topics/voice-connections#ip-discovery) occurs.
* After *IP Discovery* returns the **Application**'s external ip and port it connected to the **Voice Server**
with, the **library** sends a [Select Protocol Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload)
to the **Discord Voice Gateway**
to the **Discord Voice Gateway**.
* The **library** waits until it receives a [Session Description Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-session-description-payload)
from the **Discord Voice Gateway**
from the **Discord Voice Gateway**.
* Once the *Session Description Event* is received, [Speaking Events](https://discordapp.com/developers/docs/topics/voice-connections#speaking-example-speaking-payload)
and **Voice Packets** can begin to be sent to the **Discord Voice Gateway** and **Voice Server** respectively
and **Voice Packets** can begin to be sent to the **Discord Voice Gateway** and **Voice Server** respectively.
## Usage
* The **application** would get a new `*Voice` instance by calling `NewVoice()` and keep it
stored for when it needs to open voice connections
stored for when it needs to open voice connections.
* When the **application** wants to connect to a voice channel they would call `JoinChannel()` on
the stored `*Voice` instance
the stored `*Voice` instance.
* `JoinChannel()` will block as it follows the [Connection Flow](#connection-flow), returning an
`error` if one occurs and a `*Connection` if it was successful
* The **application** should now call `*Connection#Speaking()` with the wanted [voice flag](https://discordapp.com/developers/docs/topics/voice-connections#speaking)
(`Microphone`, `Soundshare`, `Priority`)
* The **application** can now send **Voice Packets** to the `*Connection#OpusSend` channel
which will be sent to the **Voice Server**
`error` if one occurs and a `*voice.Session` if it was successful.
* The **application** should now call `(*voice.Session).Speaking()` with the wanted [voice flag](https://discordapp.com/developers/docs/topics/voice-connections#speaking)
(`voicegateway.Microphone`, `voicegateway.Soundshare`, or `voicegateway.Priority`).
* The **application** can now send **Voice Packets** using the `(*voice.Session).Write()` method
which will be sent to the **Voice Server**. `(*voice.Session)` also implements `io.Writer`.
* When the **application** wants to stop sending **Voice Packets** they should call
`*Connection#StopSpeaking()`, any required voice cleanup (closing streams, etc), then
`*Connection#Disconnect()`
`(*voice.Session).StopSpeaking()`, then any required voice cleanup (closing streams, etc.), then
`(*voice.Session).Disconnect()`
## Examples
###### Coming SoonTM
Check the integration tests at [voice/integration_test.go](https://github.com/diamondburned/arikawa/blob/master/voice/integration_test.go).

View File

@ -1,11 +0,0 @@
package voice
// https://discordapp.com/developers/docs/topics/voice-connections#encrypting-and-sending-voice
type Packet struct {
Version byte // Single byte value of 0x80 - 1 byte
Type byte // Single byte value of 0x78 - 1 byte
Sequence uint16 // Unsigned short (big endian) - 4 bytes
Timestamp uint32 // Unsigned integer (big endian) - 4 bytes
SSRC uint32 // Unsigned integer (big endian) - 4 bytes
Opus []byte // Binary data
}

View File

@ -86,7 +86,8 @@ func DialConnection(addr string, ssrc uint32) (*Connection, error) {
}
func (c *Connection) Start(secret *[32]byte) {
header := [12]byte{
// https://discordapp.com/developers/docs/topics/voice-connections#encrypting-and-sending-voice
packet := [12]byte{
0: 0x80, // Version + Flags
1: 0x78, // Payload Type
// [2:4] // Sequence
@ -94,7 +95,7 @@ func (c *Connection) Start(secret *[32]byte) {
}
// Write SSRC to the header.
binary.BigEndian.PutUint32(header[8:12], c.ssrc) // SSRC
binary.BigEndian.PutUint32(packet[8:12], c.ssrc) // SSRC
// 50 sends per second, 960 samples each at 48kHz
frequency := time.NewTicker(time.Millisecond * 20)
@ -120,15 +121,15 @@ func (c *Connection) Start(secret *[32]byte) {
}
// Write a new sequence.
binary.BigEndian.PutUint16(header[2:4], c.sequence)
binary.BigEndian.PutUint16(packet[2:4], c.sequence)
c.sequence++
binary.BigEndian.PutUint32(header[4:8], c.timestamp)
binary.BigEndian.PutUint32(packet[4:8], c.timestamp)
c.timestamp += 960 // Samples
copy(c.nonce[:], header[:])
copy(c.nonce[:], packet[:])
toSend := secretbox.Seal(header[:], b, &c.nonce, secret)
toSend := secretbox.Seal(packet[:], b, &c.nonce, secret)
select {
case <-frequency.C: