Skip to main content

Overview

This is the core client API implemented in Rust and exported to native C libraries. These libraries are the low-level building blocks for our high-level SDKs like Unity SDK or Unreal SDK.

Please check out our public Github repository for source code and a CLI application example.

Usage

Quick Start

The Core SDK now uses a Connection Pool to manage connections efficiently. The following example demonstrates how to initialize the SDK, create a connection pool, and join a room.

#include <stdio.h>
#include "odin.h"

int main(int argc, const char *argv[])
{
// 1. Initialize the SDK
odin_initialize(ODIN_VERSION);

// 2. Configure the Connection Pool
// 'on_rpc' is the callback for receiving events from the server
OdinConnectionPoolSettings settings = {
.on_datagram = NULL,
.on_rpc = NULL,
.user_data = NULL
};

OdinConnectionPool *pool;
odin_connection_pool_create(settings, &pool);

// 3. Create a room and join
OdinRoom *room;
odin_room_create(pool, "<SERVER_URL>", "<TOKEN>", &room);

// ... Main loop or application logic ...
getchar();

// 4. Cleanup
odin_room_free(room);
odin_connection_pool_free(pool);
odin_shutdown();

return 0;
}

Authentication

To enter a room, an authentication token is required. ODIN uses signed JSON Web Tokens (JWT). Use the OdinTokenGenerator to create these tokens locally for testing, or generate them on your backend.

OdinTokenGenerator *generator;
odin_token_generator_create("<ACCESS_KEY>", &generator);

char token[512];
// Payload usually contains "rid" (room ID) and "uid" (user ID)
const char *payload = "{\"rid\": \"my-room\", \"uid\": \"user-1\"}";
odin_token_generator_sign(generator, payload, token, sizeof(token));

odin_token_generator_free(generator);
Security Note

Your Access Key is a sensitive credential. Do not embed it in your client-side code in production. Use a backend service to issue tokens.

Event Handling (RPC)

The ODIN Core SDK uses an event-driven architecture based on RPC (Remote Procedure Calls). Events such as users joining, media starting, or messages received are delivered as MessagePack encoded data to the on_rpc callback defined in your connection pool settings.

To handle these events, you must:

  1. Register an on_rpc callback in OdinConnectionPoolSettings.
  2. Deserialize the bytes payload using a MessagePack library (and/or JSON parser).
  3. Process the event based on its structure.

See Event Structures for a detailed reference of the available event schemas.

void on_rpc(uint64_t room_ref, const uint8_t *bytes, uint32_t bytes_length, void *user_data) {
// 1. Deserialize MessagePack to JSON
// 2. Inspect 'kind' or event type
// 3. Handle logic (e.g., UI updates, stream setup)
}

Audio Talk-Status Events

For performance-critical talk-status specific updates (Voice Activity Detection), you can register direct callbacks on encoders and decoders using odin_encoder_set_event_callback and odin_decoder_set_event_callback.

void on_decoder_event(OdinDecoder* decoder, OdinAudioEvents events, void* user_data) {
if (events & ODIN_AUDIO_EVENTS_IS_SILENT_CHANGED) {
bool silent = odin_decoder_is_silent(decoder);
printf("Peer %s speaking\n", silent ? "stopped" : "started");
}
}

Media Streams

ODIN uses an explicit signaling mechanism to manage media streams. You must send RPC commands to the server to Start, Stop, Pause, or Resume media.

Starting Media

To transmit audio, you must first create an audio stream (likely initializing your microphone) and then signal the room that you are starting media.

// Example: Sending a "StartMedia" RPC
// Payload: { "media_id": <id>, "properties": { "kind": "audio" } }
// Wraps in command structure as defined in your application protocol
// Then send via odin_room_send_rpc

For a complete implementation of audio capture and media signaling, refer to the Minimal Client Sample.

Audio Processing

The Audio Processing Module (APM) handles echo cancellation, noise suppression, and gain control. You can configure it by applying an OdinApmConfig to your audio pipeline.

OdinApmConfig apm_config = {
.voice_activity_detection = true,
.voice_activity_detection_attack_probability = 0.9,
.voice_activity_detection_release_probability = 0.8,
.echo_canceller = true,
.noise_suppression_level = OdinNoiseSuppressionLevel_Moderate,
.gain_controller = true,
.gain_controller_version = ODIN_GAIN_CONTROLLER_VERSION_V2 // Use V2 for improved quality
};

// Apply to your pipeline (implementation depends on your encoder setup)

User Data & Messages

Arbitrary data updates (User Data) and Messages are also handled via RPC commands (UpdatePeer, SendMessage). Sending a message to all peers involves sending a SendMessage RPC command with your binary payload.

See Event Structures for the MessageReceived event format.