gaato/discord/voice does not have a README file

    AudioSource

    pub(open) trait AudioSource {
    async fn next_frame(Self) -> Bytes?
    }

    A source of pre-encoded 20 ms Opus frames. None marks end of stream.

    DaveBackend

    trait DaveBackend

    The private seam between gateway orchestration and the official libdave wrapper. Keeping this package-private lets white-box tests model protocol outcomes without making an alternate crypto provider part of the API.

    VoiceTransport

    pub(open) trait VoiceTransport {
    async fn recv(Self) -> VoiceFrame
    async fn send_text(Self, String) -> Unit
    async fn send_binary(Self, Bytes) -> Unit
    async fn close(Self, code~ : Int) -> Unit
    }

    The network seam used by VoiceGateway. Tests can provide an in-memory implementation without opening a WebSocket.

    VoiceUdp

    pub(open) trait VoiceUdp {
    async fn recv(Self, FixedArray[Byte]) -> Int
    async fn send(Self, Bytes) -> Unit
    async fn close(Self) -> Unit
    }

    UDP seam used by voice discovery and media transport.

    DaveError

    pub(all) suberror DaveError {
    DaveInvalid(reason~ : String)
    DaveUnavailable(reason~ : String)
    DaveInternal(reason~ : String)
    } derive(Eq,
    Debug
    )

    Errors reported while coordinating Discord's DAVE protocol.

    OggOpusError

    pub(all) suberror OggOpusError {
    InvalidOggPage(reason~ : String)
    InvalidOpusStream(reason~ : String)
    } derive(Eq,
    Debug
    )

    Errors raised while parsing Ogg pages and Opus stream headers.

    RtpError

    pub(all) suberror RtpError {
    InvalidRtpPacket(reason~ : String)
    } derive(Eq,
    Debug
    )

    Errors raised while validating an RTP packet.

    VoiceCryptoError

    pub(all) suberror VoiceCryptoError {
    NoCompatibleMode(modes~ : Array[String])
    ShimUnavailable(reason~ : String)
    InvalidSecretKey(length~ : Int)
    InvalidEncryptedPacket(reason~ : String)
    AuthenticationFailed(reason~ : String)
    AeadFailed(status~ : Int, reason~ : String)
    } derive(Eq,
    Debug
    )

    Errors raised by transport-mode negotiation and packet encryption.

    VoiceEnvelopeError

    pub(all) suberror VoiceEnvelopeError {
    InvalidTextFrame(reason~ : String)
    InvalidBinaryFrame(reason~ : String)
    } derive(Eq,
    Debug
    )

    A malformed JSON or binary voice gateway envelope.

    VoiceError

    pub(all) suberror VoiceError {
    MissingIntent(intent~ : String)
    JoinTimeout
    ShimUnavailable(reason~ : String)
    NoCompatibleMode(offered~ : Array[String])
    GatewayClosed(code~ : Int?)
    IpDiscoveryFailed(reason~ : String)
    Disconnected
    } derive(
    Debug
    )

    Errors surfaced while joining or operating a voice connection.

    VoiceTransportClosed

    pub(all) suberror VoiceTransportClosed {
    VoiceTransportClosed(code~ : Int?, reason~ : String)
    } derive(
    Debug
    )

    Raised when a voice transport is closed or cannot continue.

    VoiceUdpError

    pub(all) suberror VoiceUdpError {
    InvalidDiscoveryPacket(reason~ : String)
    IpDiscoveryFailed(attempts~ : Int, reason~ : String)
    } derive(Eq,
    Debug
    )

    Errors raised by voice UDP setup and IP discovery.

    DaveAction

    pub(all) enum DaveAction {
    SendJson(Json)
    SendBinary(op~ : Int, payload~ : Bytes)
    SwitchMediaContext(protocol_version~ : Int)
    } derive(Eq,
    Debug
    )

    Side effects requested by the DAVE gateway/MLS orchestration state machine.

    DaveCommitOutcome

    type DaveCommitOutcome derive(Eq,
    Debug
    )

    DaveMachine

    pub struct DaveMachine {
    // private fields
    }

    DAVE gateway/MLS orchestration. Networking remains outside this type.

    DaveMachine::active_protocol_version

    fn DaveMachine::active_protocol_version(self : DaveMachine) -> Int

    Return the protocol version currently selected for outbound media.

    DaveMachine::encrypt_opus_frame

    fn DaveMachine::encrypt_opus_frame(self : DaveMachine, ssrc~ : UInt, frame : Bytes) -> Bytes raise DaveError

    Encrypt one Opus frame. Passthrough is delegated to libdave as well, so the encryptor remains the sole owner of media-transition state.

    DaveMachine::handle

    fn DaveMachine::handle(self : DaveMachine, message : VoiceMessage) -> Array[DaveAction] raise DaveError

    Handle one decoded voice-gateway message and return transport actions.

    DaveMachine::new

    fn DaveMachine::new(protocol_version~ : Int, self_user_id~ : String, channel_id~ : UInt64, roster? : Array[String]) -> DaveMachine raise DaveError

    Create the production DAVE state machine backed by the official libdave wrapper. protocol_version is the version selected by the voice gateway.

    DaveRosterChange

    type DaveRosterChange derive(Eq,
    Debug
    )

    DaveWelcomeOutcome

    type DaveWelcomeOutcome derive(Eq,
    Debug
    )

    EncryptionMode

    pub(all) enum EncryptionMode {
    AeadAes256GcmRtpsize
    AeadXChaCha20Poly1305Rtpsize
    } derive(Eq,
    Debug
    )

    Discord voice transport encryption modes supported by this package.

    EncryptionMode::negotiate

    fn EncryptionMode::negotiate(modes : Array[String]) -> EncryptionMode raise VoiceCryptoError

    Select the preferred common Discord transport encryption mode.

    OggOpusSource

    pub struct OggOpusSource {
    // private fields
    }

    In-memory Ogg/Opus source. Opus packets must already represent 20 ms audio frames; this demuxer does not decode or resample them.

    OggOpusSource::channels

    fn OggOpusSource::channels(self : OggOpusSource) -> Int

    The channel count declared by the stream's OpusHead header.

    OggOpusSource::from_bytes

    fn OggOpusSource::from_bytes(bytes : Bytes) -> OggOpusSource raise OggOpusError

    Parse a complete in-memory Ogg Opus file into an audio source, validating its OpusHead/OpusTags headers.

    OggOpusSource::from_reader

    Open an Ogg/Opus source backed by an asynchronous reader. The constructor consumes and validates the OpusHead and OpusTags packets; audio packets are read lazily by AudioSource::next_frame.

    Example

    async test {
    let file = @fs.open("voice.ogg")
    defer file.close()
    let source = @voice.OggOpusSource::from_reader(file)
    let audio : &@voice.AudioSource = source
    while audio.next_frame() is Some(frame) {
    play_opus_frame(frame)
    }
    }

    OggOpusSource::next_frame

    async fn OggOpusSource::next_frame(self : OggOpusSource) -> Bytes?

    OggOpusSource::pre_skip

    fn OggOpusSource::pre_skip(self : OggOpusSource) -> Int

    Samples (at 48 kHz) to drop before playback, from the OpusHead header.

    OggOpusWriter

    pub struct OggOpusWriter {
    // private fields
    }

    Pure in-memory Ogg/Opus muxer. Header pages are available immediately from take_output; audio pages become available as packet or lacing limits are reached, and finish emits the final EOS page.

    OggOpusWriter::finish

    fn OggOpusWriter::finish(self : OggOpusWriter) -> Unit

    Flush remaining packets in a final EOS page. Repeated calls are no-ops.

    OggOpusWriter::new

    fn OggOpusWriter::new(channels? : Int, pre_skip? : Int, serial? : UInt, max_packets_per_page? : Int) -> OggOpusWriter

    Create an Ogg/Opus muxer and queue its OpusHead and OpusTags pages.

    Example

    async test {
    let writer = @voice.OggOpusWriter::new(channels=2, pre_skip=312)
    for frame in recorded_opus_frames() {
    writer.write_frame(frame)
    }
    writer.finish()
    let file = @fs.create("recording.ogg")
    defer file.close()
    file.write(writer.take_output())
    }

    Panics

    Panics if channels or pre_skip cannot be represented in an Opus header, or if max_packets_per_page is not positive.

    OggOpusWriter::take_output

    fn OggOpusWriter::take_output(self : OggOpusWriter) -> Bytes

    Drain all complete Ogg pages generated so far.

    OggOpusWriter::write_frame

    fn OggOpusWriter::write_frame(self : OggOpusWriter, opus : Bytes, samples? : Int) -> Unit raise OggOpusError

    Queue one complete Opus packet and advance the 48 kHz granule position.

    OggPacketReader

    pub struct OggPacketReader {
    // private fields
    }

    Streaming Ogg packet reassembler. Feed arbitrary chunks with push, then pull complete packets with next_packet.

    OggPacketReader::new

    Create an empty reader; feed it Ogg data with push and drain packets with next_packet.

    OggPacketReader::next_packet

    fn OggPacketReader::next_packet(self : OggPacketReader) -> Bytes? raise OggOpusError

    Return the next complete Ogg packet, or None when more input is needed.

    OggPacketReader::push

    fn OggPacketReader::push(self : OggPacketReader, bytes : Bytes) -> Unit

    Add bytes to the streaming input without requiring a page boundary.

    ReorderBuffer

    pub struct ReorderBuffer[T] {
    // private fields
    }

    A small RTP reorder window. The first packet establishes the expected sequence; later gaps are held until hold_ms elapses or eight packets are buffered.

    ReorderBuffer::new

    fn[T] ReorderBuffer::new(hold_ms? : Int) -> ReorderBuffer[T]

    Create an empty window that holds packets behind a sequence gap for up to hold_ms milliseconds.

    ReorderBuffer::push

    fn[T] ReorderBuffer::push(self : ReorderBuffer[T], seq~ : Int, arrival_ms~ : Int64, packet : T) -> Array[ReorderOutput[T]]

    Insert one RTP packet. Arrival time is supplied by the caller so timeout behavior is deterministic in tests.

    ReorderOutput

    pub(all) enum ReorderOutput[T] {
    Deliver(T)
    Lost(count~ : Int)
    } derive(Eq,
    Debug
    )

    Values produced while restoring RTP sequence order.

    RtpPacket

    pub(all) struct RtpPacket {
    sequence : UInt16
    timestamp : UInt
    ssrc : UInt
    header_len : Int
    header : Bytes
    payload : Bytes
    } derive(Eq,
    Debug
    )

    A parsed RTP packet with the rtpsize cleartext header separated.

    TransportCipher

    pub struct TransportCipher {
    // private fields
    }

    Stateful voice transport cipher. The sender counter wraps modulo 2^32; receivers reconstruct nonces from the packet suffix and need no counter.

    TransportCipher::new

    fn TransportCipher::new(mode : EncryptionMode, secret_key : Bytes) -> TransportCipher raise VoiceCryptoError

    Create a cipher for mode from the 32-byte session secret_key delivered by the voice gateway.

    TransportCipher::open

    fn TransportCipher::open(self : TransportCipher, packet : Bytes, header_len~ : Int) -> Bytes raise VoiceCryptoError

    Authenticate and decrypt a packet, returning header || plaintext.

    TransportCipher::seal

    fn TransportCipher::seal(self : TransportCipher, header~ : Bytes, plaintext : Bytes) -> Bytes raise VoiceCryptoError

    Encrypt an RTP payload and append the four-byte nonce suffix.

    VoiceConnection

    pub struct VoiceConnection {
    // private fields
    }

    High-level owner of voice gateway, UDP media, DAVE, sender, and receiver tasks. All background work is attached to the task group passed to start.

    VoiceConnection::disconnect

    async fn VoiceConnection::disconnect(self : VoiceConnection) -> Unit

    Leave the Discord voice state and tear down media transports. Repeated calls are harmless.

    VoiceConnection::latency_ms

    fn VoiceConnection::latency_ms(self : VoiceConnection) -> Int64?

    Latest voice gateway heartbeat round-trip in milliseconds, if measured.

    VoiceConnection::next_event

    async fn VoiceConnection::next_event(self : VoiceConnection) -> VoiceEvent

    Pull the next received media or voice membership event.

    VoiceConnection::play

    async fn VoiceConnection::play(self : VoiceConnection, source : &AudioSource) -> Unit

    Replace the current source. The old sender is asked to stop and flush its five silence frames before the latest source begins.

    VoiceConnection::set_speaking

    async fn VoiceConnection::set_speaking(self : VoiceConnection, flags : Int) -> Unit

    Send a Speaking (opcode 5) frame with the given flag bits. The playback loop manages this automatically; call it directly only for custom speaking indicators.

    VoiceConnection::start

    fn[X] VoiceConnection::start(group :
    TaskGroup
    [X], credentials : VoiceCredentials, user_id~ : String, channel_id~ : UInt64, leave~ : async () -> Unit, rejoin~ : async () -> VoiceCredentials, connector? : async (String) -> &VoiceTransport, udp_opener? : async (String, Int) -> &VoiceUdp, receive? : Bool, telemetry? : (VoiceTelemetry) -> Unit, sleeper? : async (Int) -> Unit, rand? :
    Rand
    ) -> VoiceConnection

    Start a voice connection and attach all of its tasks to group.

    VoiceConnection::state

    The current lifecycle state of this voice connection.

    VoiceConnection::stop

    async fn VoiceConnection::stop(self : VoiceConnection) -> Unit

    Stop the active source; the send loop emits five silence frames and clears the speaking flag.

    VoiceConnection::subscribe

    fn VoiceConnection::subscribe(self : VoiceConnection, user_id~ : String, end_after_silence_ms? : Int?) -> VoiceReceiveStream

    Subscribe to received Opus packets for one Discord user. With end_after_silence_ms, the first frame waits indefinitely and subsequent reads end the stream after the requested silence interval.

    Example

    async test {
    // Echo one speaker until they are silent for one second.
    connection.play(
    connection.subscribe(user_id="1234", end_after_silence_ms=Some(1000)),
    )

    // Or record the same stream into an Ogg/Opus file.
    let stream = connection.subscribe(user_id="1234")
    let audio : &@voice.AudioSource = stream
    let writer = @voice.OggOpusWriter::new(channels=2)
    while audio.next_frame() is Some(frame) {
    writer.write_frame(frame)
    }
    writer.finish()
    }

    VoiceConnection::wait_ready

    async fn VoiceConnection::wait_ready(self : VoiceConnection, timeout_ms? : Int) -> Unit raise VoiceError

    Wait until the current connection handshake reaches Ready.

    VoiceConnectionState

    pub(all) enum VoiceConnectionState {
    Connecting
    Ready
    Reconnecting
    Rejoining
    Closed(code~ : Int?)
    } derive(Eq,
    Debug
    )

    Public voice connection lifecycle.

    VoiceCredentials

    pub(all) struct VoiceCredentials {
    server_id : String
    session_id : String
    token : String
    endpoint : String
    } derive(Eq,
    Debug
    )

    Credentials supplied by the main Discord gateway voice-state handshake.

    VoiceEvent

    pub(all) enum VoiceEvent {
    OpusReceived(user_id~ : String?, ssrc~ : UInt, sequence~ : Int, timestamp~ : UInt, opus~ : Bytes)
    PacketsLost(user_id~ : String?, ssrc~ : UInt, count~ : Int)
    SpeakingChanged(user_id~ : String, ssrc~ : UInt, flags~ : Int)
    UserConnected(user_id~ : String)
    UserDisconnected(user_id~ : String)
    ConnectionReady
    ConnectionResumed
    } derive(Eq,
    Debug
    )

    Events emitted by a live voice connection.

    VoiceFrame

    pub(all) enum VoiceFrame {
    Text(String)
    Binary(Bytes)
    } derive(Eq,
    Debug
    )

    A complete WebSocket message received from the voice gateway.

    VoiceGateway

    pub struct VoiceGateway {
    // private fields
    }

    Voice gateway v8 driver. The caller-owned task group controls its lifetime; cancelling the group tears down connection and heartbeat tasks.

    VoiceGateway::close

    async fn VoiceGateway::close(self : VoiceGateway) -> Unit noraise

    Request graceful shutdown of the voice WebSocket.

    VoiceGateway::latency_ms

    fn VoiceGateway::latency_ms(self : VoiceGateway) -> Int64?

    Latest matched heartbeat round-trip time in milliseconds.

    VoiceGateway::next

    async fn VoiceGateway::next(self : VoiceGateway) -> VoiceGatewayEvent

    Pull the next voice gateway event. Blocks until one is available.

    VoiceGateway::send_binary

    async fn VoiceGateway::send_binary(self : VoiceGateway, op~ : Int, payload : Bytes) -> Unit

    Send a client-to-server DAVE binary envelope.

    VoiceGateway::send_json

    async fn VoiceGateway::send_json(self : VoiceGateway, payload : Json) -> Unit

    Send an arbitrary JSON voice gateway envelope.

    VoiceGateway::start

    fn[X] VoiceGateway::start(group :
    TaskGroup
    [X], server_id~ : String, user_id~ : String, session_id~ : String, token~ : String, endpoint~ : String, max_dave_protocol_version? : UInt16, select_protocol~ : async (UInt, String, Int, Array[String]) -> (String, Int, String), connector? : async (String) -> &VoiceTransport, queue_capacity? : Int, telemetry? : (VoiceGatewayEvent) -> Unit, sleeper? : async (Int) -> Unit, rand? :
    Rand
    ) -> VoiceGateway

    Spawn a voice gateway driver into group and return its handle. max_dave_protocol_version is advertised in Identify. It defaults to zero so low-level callers do not negotiate DAVE without an active backend; pass a supported maximum explicitly to enable it.

    VoiceGateway::state

    Current voice gateway lifecycle state.

    VoiceGatewayEvent

    pub(all) enum VoiceGatewayEvent {
    ReadyReceived
    SessionEstablished(mode~ : String, secret_key~ : Bytes, dave_protocol_version~ : Int)
    Message(VoiceMessage)
    Connected(resumed~ : Bool)
    Disconnected(code~ : Int?, resuming~ : Bool)
    ConnectFailed(reason~ : String)
    NeedsRejoin(code~ : Int?)
    FatallyClosed(code~ : Int)
    } derive(Eq,
    Debug
    )

    Events surfaced by VoiceGateway::next.

    VoiceGatewayState

    pub(all) enum VoiceGatewayState {
    Disconnected(reconnect_attempts~ : Int)
    Connecting
    Identifying
    SelectingProtocol
    Active
    Resuming
    FatallyClosed(code~ : Int)
    } derive(Eq,
    Debug
    )

    Voice gateway lifecycle state.

    VoiceMessage

    pub(all) enum VoiceMessage {
    Ready(ssrc~ : UInt, ip~ : String, port~ : Int, modes~ : Array[String])
    Hello(heartbeat_interval~ : Int)
    SessionDescription(mode~ : String, secret_key~ : Bytes, dave_protocol_version~ : Int)
    HeartbeatAck(nonce~ : Int64)
    Speaking(ssrc~ : UInt, user_id~ : String, flags~ : Int)
    ClientsConnect(user_ids~ : Array[String])
    ClientDisconnect(user_id~ : String)
    Resumed
    DavePrepareTransition(transition_id~ : Int, protocol_version~ : Int)
    DaveExecuteTransition(transition_id~ : Int)
    DavePrepareEpoch(epoch~ : Int, protocol_version~ : Int)
    DaveMlsExternalSender(payload~ : Bytes)
    DaveMlsProposals(payload~ : Bytes)
    DaveMlsAnnounceCommitTransition(transition_id~ : Int, commit~ : Bytes)
    DaveMlsWelcome(transition_id~ : Int, welcome~ : Bytes)
    Unknown(op~ : Int)
    } derive(Eq,
    Debug
    )

    A decoded voice gateway v8 message.

    VoiceReceiveStream

    pub struct VoiceReceiveStream {
    // private fields
    }

    A per-user stream of received Opus packets. Streams are created with VoiceConnection::subscribe and can be passed directly to play or read through the AudioSource trait.

    VoiceReceiveStream::close

    fn VoiceReceiveStream::close(self : VoiceReceiveStream) -> Unit

    End this stream and unregister it from its connection. Repeated calls are harmless, and a blocked next_frame wakes with None.

    VoiceReceiveStream::next_frame

    async fn VoiceReceiveStream::next_frame(self : VoiceReceiveStream) -> Bytes?

    VoiceReconnectPolicy

    pub(all) enum VoiceReconnectPolicy {
    Resume
    Rejoin
    Fatal
    } derive(Eq,
    Debug
    )

    Action after a voice WebSocket close: resume the session, rejoin from scratch, or give up because reconnecting cannot succeed.

    VoiceTelemetry

    pub(all) enum VoiceTelemetry {
    GatewayEvent(VoiceGatewayEvent)
    DaveMediaContextActivated(protocol_version~ : Int)
    DaveBinaryControlSent(opcode~ : Int, payload_bytes~ : Int)
    PacketDropped(reason~ : String)
    DaveEncryptDropped(reason~ : String)
    DaveDecryptDropped(user_id~ : String?, ssrc~ : UInt, count~ : Int, reason~ : String)
    } derive(Eq,
    Debug
    )

    Non-fatal diagnostics from the connection's gateway and media paths.

    SILENCE_FRAME

    let SILENCE_FRAME : Bytes

    Discord's canonical Opus silence frame.

    build_ip_discovery_request

    fn build_ip_discovery_request(ssrc : UInt) -> Bytes

    Build Discord's 74-byte voice IP discovery request.

    build_rtp_header

    fn build_rtp_header(sequence~ : UInt16, timestamp~ : UInt, ssrc~ : UInt) -> Bytes

    Build Discord's RTP header for a 20 ms Opus frame.

    connect_voice_websocket

    async fn connect_voice_websocket(url : String) -> &VoiceTransport

    Connect to a voice-gateway WebSocket. The caller supplies the complete v8 URL, normally wss://<endpoint>?v=8.

    discover_external_address

    async fn discover_external_address(udp : &VoiceUdp, ssrc : UInt, retries? : Int, timeout_ms? : Int) -> (String, Int)

    Run voice IP discovery, retrying only receive timeouts.

    encode_binary_client_frame

    fn encode_binary_client_frame(op : Int, payload : Bytes) -> Bytes

    Prefix a client-to-server binary DAVE payload with its one-byte opcode.

    encode_heartbeat

    fn encode_heartbeat(t~ : Int64, seq_ack~ : Int) -> Json

    Voice gateway Heartbeat (opcode 3) payload carrying the nonce and last acknowledged server sequence.

    encode_identify

    fn encode_identify(server_id~ : String, user_id~ : String, session_id~ : String, token~ : String, max_dave_protocol_version? : UInt16) -> Json

    Voice gateway Identify (opcode 0) payload, advertising the selected maximum DAVE protocol version. It defaults to zero so low-level callers do not advertise DAVE without an active backend; pass a supported maximum explicitly to enable negotiation.

    encode_invalid_commit_welcome

    fn encode_invalid_commit_welcome(transition_id~ : Int) -> Json

    DAVE Invalid Commit/Welcome (opcode 31) payload asking the server to reset the group after a rejected MLS message.

    encode_resume

    fn encode_resume(server_id~ : String, session_id~ : String, token~ : String, seq_ack~ : Int) -> Json

    Voice gateway Resume (opcode 7) payload for reattaching to an existing session.

    encode_select_protocol

    fn encode_select_protocol(address~ : String, port~ : Int, mode~ : String) -> Json

    Voice gateway Select Protocol (opcode 1) payload announcing the discovered UDP address and chosen encryption mode.

    encode_speaking

    fn encode_speaking(ssrc~ : UInt, flags~ : Int, delay? : Int) -> Json

    Voice gateway Speaking (opcode 5) payload for the sender's SSRC.

    encode_transition_ready

    fn encode_transition_ready(transition_id~ : Int) -> Json

    DAVE Transition Ready (opcode 23) payload acknowledging an announced protocol transition.

    open_voice_udp

    async fn open_voice_udp(ip : String, port : Int) -> &VoiceUdp

    Open a connected UDP socket for a Discord voice server.

    parse_binary_frame

    fn parse_binary_frame(bytes : Bytes) -> (VoiceMessage, Int?) raise VoiceEnvelopeError

    Decode a server-to-client binary DAVE frame. Its first two bytes are the big-endian v8 sequence number and the third byte is the opcode.

    parse_ip_discovery_response

    fn parse_ip_discovery_response(bytes : Bytes, expected_ssrc~ : UInt) -> (String, Int) raise VoiceUdpError

    Parse Discord's 74-byte voice IP discovery response.

    parse_rtp_packet

    fn parse_rtp_packet(bytes : Bytes) -> RtpPacket raise RtpError

    Parse an RTP v2 packet and retain extension data in payload.

    parse_text_frame

    fn parse_text_frame(text : String) -> (VoiceMessage, Int?) raise VoiceEnvelopeError

    Decode a JSON voice gateway message and return its optional top-level buffered-resume sequence number.

    rtpsize_header_len

    fn rtpsize_header_len(bytes : Bytes) -> Int

    Return the cleartext RTP header length used as AEAD associated data.

    run_send_loop

    async fn run_send_loop(source : &AudioSource, cipher : TransportCipher, udp : &VoiceUdp, gateway : VoiceGateway, ssrc~ : UInt, initial_sequence? : UInt16, initial_timestamp? : UInt, stop? :
    Ref
    [Bool], frame_duration_ms? : Int, dave? : DaveMachine, on_dave_error? : (String) -> Unit) -> Unit

    Internal paced sender used by the M4 connection driver.

    shim_available

    fn shim_available() -> Bool

    Whether a compatible transport-only ABI v3 voice shim is available.

    shim_unavailable_reason

    fn shim_unavailable_reason() -> String?

    Explain why the native voice shim could not be loaded.

    voice_on_close

    fn voice_on_close(code : Int?, has_session : Bool) -> VoiceReconnectPolicy

    Classify a voice WebSocket close code. A resumable transport failure still requires a fresh join when no established voice session exists.