@4players/odin-nodejs 0.10.3 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/LICENSE +21 -0
  3. package/README.md +603 -44
  4. package/binding.gyp +29 -13
  5. package/cppsrc/binding.cpp +3 -6
  6. package/cppsrc/odinbindings.cpp +9 -45
  7. package/cppsrc/odincipher.cpp +92 -0
  8. package/cppsrc/odincipher.h +32 -0
  9. package/cppsrc/odinclient.cpp +19 -158
  10. package/cppsrc/odinclient.h +2 -5
  11. package/cppsrc/odinmedia.cpp +144 -186
  12. package/cppsrc/odinmedia.h +51 -18
  13. package/cppsrc/odinroom.cpp +675 -635
  14. package/cppsrc/odinroom.h +76 -26
  15. package/cppsrc/utilities.cpp +11 -81
  16. package/cppsrc/utilities.h +25 -140
  17. package/index.cjs +829 -0
  18. package/index.d.ts +3 -4
  19. package/libs/bin/linux/arm64/libodin.so +0 -0
  20. package/libs/bin/linux/arm64/libodin_crypto.so +0 -0
  21. package/libs/bin/linux/ia32/libodin.so +0 -0
  22. package/libs/bin/linux/ia32/libodin_crypto.so +0 -0
  23. package/libs/bin/linux/x64/libodin.so +0 -0
  24. package/libs/bin/linux/x64/libodin_crypto.so +0 -0
  25. package/{prebuilds/darwin-x64/node.napi.node → libs/bin/macos/universal/libodin.dylib} +0 -0
  26. package/libs/bin/macos/universal/libodin_crypto.dylib +0 -0
  27. package/libs/bin/windows/arm64/odin.dll +0 -0
  28. package/libs/bin/windows/arm64/odin.lib +0 -0
  29. package/libs/bin/windows/arm64/odin_crypto.dll +0 -0
  30. package/libs/bin/windows/arm64/odin_crypto.lib +0 -0
  31. package/libs/bin/windows/ia32/odin.dll +0 -0
  32. package/libs/bin/windows/ia32/odin.lib +0 -0
  33. package/libs/bin/windows/ia32/odin_crypto.dll +0 -0
  34. package/libs/bin/windows/ia32/odin_crypto.lib +0 -0
  35. package/libs/bin/windows/x64/odin.dll +0 -0
  36. package/libs/bin/windows/x64/odin.lib +0 -0
  37. package/libs/bin/windows/x64/odin_crypto.dll +0 -0
  38. package/libs/bin/windows/x64/odin_crypto.lib +0 -0
  39. package/libs/include/odin.h +665 -567
  40. package/libs/include/odin_crypto.h +46 -0
  41. package/odin.cipher.d.ts +31 -0
  42. package/odin.media.d.ts +69 -19
  43. package/odin.room.d.ts +348 -7
  44. package/package.json +5 -4
  45. package/prebuilds/{darwin-arm64/node.napi.node → darwin-x64+arm64/libodin.dylib} +0 -0
  46. package/prebuilds/darwin-x64+arm64/libodin_crypto.dylib +0 -0
  47. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  48. package/prebuilds/linux-x64/libodin.so +0 -0
  49. package/prebuilds/linux-x64/libodin_crypto.so +0 -0
  50. package/prebuilds/linux-x64/node.napi.node +0 -0
  51. package/prebuilds/win32-x64/node.napi.node +0 -0
  52. package/prebuilds/win32-x64/odin.dll +0 -0
  53. package/prebuilds/win32-x64/odin_crypto.dll +0 -0
  54. package/scripts/postbuild.cjs +133 -0
  55. package/tests/audio-recording/README.md +97 -12
  56. package/tests/audio-recording/index.js +238 -130
  57. package/tests/connection-test/README.md +97 -0
  58. package/tests/connection-test/index.js +273 -0
  59. package/tests/lifecycle/test-room-cycle.js +169 -0
  60. package/tests/sending-audio/README.md +178 -9
  61. package/tests/sending-audio/canBounce.mp3 +0 -0
  62. package/tests/sending-audio/index.js +250 -87
  63. package/tests/sending-audio/test-kiss-api.js +149 -0
  64. package/tests/sending-audio/test-loop-audio.js +142 -0
  65. package/CMakeLists.txt +0 -25
  66. package/libs/bin/linux/arm64/libodin_static.a +0 -0
  67. package/libs/bin/linux/ia32/libodin_static.a +0 -0
  68. package/libs/bin/linux/x64/libodin_static.a +0 -0
  69. package/libs/bin/macos/arm64/libodin_static.a +0 -0
  70. package/libs/bin/macos/x64/libodin_static.a +0 -0
  71. package/libs/bin/windows/arm64/odin_static.lib +0 -0
  72. package/libs/bin/windows/ia32/odin_static.lib +0 -0
  73. package/libs/bin/windows/x64/odin_static.lib +0 -0
@@ -10,373 +10,327 @@
10
10
  #include <stdint.h>
11
11
  #include <stdlib.h>
12
12
 
13
- #define ODIN_VERSION "1.6.4"
13
+ #define ODIN_VERSION "1.8.2"
14
14
 
15
15
  /**
16
- * Known types of a media stream.
17
- *
18
- * Note: Video streams are not supported yet.
16
+ * Defines known error codes returned by ODIN functions.
19
17
  */
20
- typedef enum OdinMediaStreamType {
18
+ typedef enum OdinError {
21
19
  /**
22
- * Media stream is of type audio
20
+ * Operation completed successfully
23
21
  */
24
- OdinMediaStreamType_Audio,
22
+ ODIN_ERROR_SUCCESS = 0,
25
23
  /**
26
- * Media stream is of type video
24
+ * No data available
27
25
  */
28
- OdinMediaStreamType_Video,
26
+ ODIN_ERROR_NO_DATA = 1,
29
27
  /**
30
- * Media stream is invalid
28
+ * The runtime initialization failed
31
29
  */
32
- OdinMediaStreamType_Invalid,
33
- } OdinMediaStreamType;
34
-
35
- /**
36
- * Valid levels for aggressiveness of the noise suppression. A higher level will reduce the noise
37
- * level at the expense of a higher speech distortion.
38
- */
39
- typedef enum OdinNoiseSuppressionLevel {
30
+ ODIN_ERROR_INITIALIZATION_FAILED = -1,
40
31
  /**
41
- * Noise suppression is disabled
32
+ * The specified API version is not supported
42
33
  */
43
- OdinNoiseSuppressionLevel_None,
34
+ ODIN_ERROR_UNSUPPORTED_VERSION = -2,
44
35
  /**
45
- * Use low suppression (6 dB)
36
+ * The object is in an unexpected state
46
37
  */
47
- OdinNoiseSuppressionLevel_Low,
38
+ ODIN_ERROR_UNEXPECTED_STATE = -3,
48
39
  /**
49
- * Use moderate suppression (12 dB)
40
+ * The object is closed
50
41
  */
51
- OdinNoiseSuppressionLevel_Moderate,
42
+ ODIN_ERROR_CLOSED = -4,
52
43
  /**
53
- * Use high suppression (18 dB)
44
+ * A mandatory argument is null
54
45
  */
55
- OdinNoiseSuppressionLevel_High,
46
+ ODIN_ERROR_ARGUMENT_NULL = -11,
56
47
  /**
57
- * Use very high suppression (21 dB)
48
+ * A provided argument is too small
58
49
  */
59
- OdinNoiseSuppressionLevel_VeryHigh,
60
- } OdinNoiseSuppressionLevel;
61
-
62
- /**
63
- * All valid connection states for an ODIN room.
64
- */
65
- typedef enum OdinRoomConnectionState {
50
+ ODIN_ERROR_ARGUMENT_TOO_SMALL = -12,
66
51
  /**
67
- * Connection is being established
52
+ * A provided argument is out of the expected bounds
68
53
  */
69
- OdinRoomConnectionState_Connecting,
54
+ ODIN_ERROR_ARGUMENT_OUT_OF_BOUNDS = -13,
70
55
  /**
71
- * Connection is established
56
+ * A provided string argument is not valid UTF-8
72
57
  */
73
- OdinRoomConnectionState_Connected,
74
- /**
75
- * Connection is being closed
76
- */
77
- OdinRoomConnectionState_Disconnecting,
78
- /**
79
- * Connection is closed
80
- */
81
- OdinRoomConnectionState_Disconnected,
82
- } OdinRoomConnectionState;
83
-
84
- /**
85
- * Possible reasons for connection state changes of an ODIN room.
86
- */
87
- typedef enum OdinRoomConnectionStateChangeReason {
88
- /**
89
- * Connection state change was initiated by the user
90
- */
91
- OdinRoomConnectionStateChangeReason_ClientRequested,
92
- /**
93
- * Connection state change was initiated by the server (e.g. peer was kicked)
94
- */
95
- OdinRoomConnectionStateChangeReason_ServerRequested,
96
- /**
97
- * Connection state change was caused by a timeout
98
- */
99
- OdinRoomConnectionStateChangeReason_ConnectionLost,
100
- } OdinRoomConnectionStateChangeReason;
101
-
102
- /**
103
- * Valid audiences for ODIN room tokens.
104
- */
105
- typedef enum OdinTokenAudience {
58
+ ODIN_ERROR_ARGUMENT_INVALID_STRING = -14,
106
59
  /**
107
- * JWT has no audience
60
+ * A provided handle argument is invalid
108
61
  */
109
- OdinTokenAudience_None,
62
+ ODIN_ERROR_ARGUMENT_INVALID_HANDLE = -15,
110
63
  /**
111
- * JWT is accepted the ODIN gateway
64
+ * A provided identifier argument is invalid
112
65
  */
113
- OdinTokenAudience_Gateway,
66
+ ODIN_ERROR_ARGUMENT_INVALID_ID = -16,
114
67
  /**
115
- * JWT is accepted by the ODIN server
68
+ * The provided version is invalid
116
69
  */
117
- OdinTokenAudience_Sfu,
118
- } OdinTokenAudience;
119
-
120
- /**
121
- * A pointer to a local ODIN token generator, employed for generating signed room tokens predicated
122
- * on an access key. Be aware that access keys serve as your unique authentication keys, requisite
123
- * for generating room tokens to access the ODIN server network. To ensure your security, it's
124
- * strongly recommended that you _NEVER_ embed an access key within your client code, and instead
125
- * generate room tokens on a server.
126
- */
127
- typedef struct OdinTokenGenerator OdinTokenGenerator;
128
-
129
- /**
130
- * A numeric code returned by ODIN function calls. Use `odin_is_error` to determine whether the
131
- * code represents an error or an actual result value.
132
- *
133
- * Note: Use `odin_error_format` to get a human readable string to represent error codes.
134
- */
135
- typedef uint32_t OdinReturnCode;
136
-
137
- /**
138
- * Audio stream configuration.
139
- */
140
- typedef struct OdinAudioStreamConfig {
70
+ ODIN_ERROR_INVALID_VERSION = -21,
141
71
  /**
142
- * The number of samples per second in hertz (between 8000 and 192000)
72
+ * The provided access key is invalid
143
73
  */
144
- uint32_t sample_rate;
74
+ ODIN_ERROR_INVALID_ACCESS_KEY = -22,
145
75
  /**
146
- * The number of channels for the new audio stream (between 1 and 2)
76
+ * The provided gateway/server address is invalid
147
77
  */
148
- uint8_t channel_count;
149
- } OdinAudioStreamConfig;
150
-
151
- /**
152
- * Internal handle identifier for an ODIN room to interact with.
153
- */
154
- typedef size_t OdinRoomHandle;
155
-
156
- /**
157
- * Internal handle identifier for an ODIN audio/video stream used to send/receive data.
158
- */
159
- typedef size_t OdinMediaStreamHandle;
160
-
161
- /**
162
- * All the different events emitted from an ODIN room.
163
- */
164
- typedef enum OdinEventTag {
78
+ ODIN_ERROR_INVALID_URI = -23,
165
79
  /**
166
- * Emitted after joining once initial room information was processed
80
+ * The provided token is invalid
167
81
  */
168
- OdinEvent_Joined,
82
+ ODIN_ERROR_INVALID_TOKEN = -24,
169
83
  /**
170
- * Emitted when other peers joined the room
84
+ * The provided effect is not compatible to the expected effect type
171
85
  */
172
- OdinEvent_PeerJoined,
86
+ ODIN_ERROR_INVALID_EFFECT = -25,
173
87
  /**
174
- * Emitted when other peers left the room
88
+ * The provided MessagePack encoded bytes are invalid
175
89
  */
176
- OdinEvent_PeerLeft,
90
+ ODIN_ERROR_INVALID_MSG_PACK = -26,
177
91
  /**
178
- * Emitted when other peers updated their user data
92
+ * The provided JSON string invalid
179
93
  */
180
- OdinEvent_PeerUserDataChanged,
94
+ ODIN_ERROR_INVALID_JSON = -27,
181
95
  /**
182
- * Emitted when other peers started a media stream
96
+ * The provided token does not grant access to the requested room
183
97
  */
184
- OdinEvent_MediaAdded,
98
+ ODIN_ERROR_TOKEN_ROOM_REJECTED = -31,
185
99
  /**
186
- * Emitted when other peers stopped a media stream
100
+ * The token is missing a customer identifier
187
101
  */
188
- OdinEvent_MediaRemoved,
102
+ ODIN_ERROR_TOKEN_MISSING_CUSTOMER = -32,
189
103
  /**
190
- * Emitted whenever data is sent/received over any known media
104
+ * The audio processing module reported an error
191
105
  */
192
- OdinEvent_MediaActiveStateChanged,
106
+ ODIN_ERROR_AUDIO_PROCESSING_FAILED = -41,
193
107
  /**
194
- * Emitted when other peers changed the global user data of the room itself
108
+ * The setup process of the Opus audio codec reported an error
195
109
  */
196
- OdinEvent_RoomUserDataChanged,
110
+ ODIN_ERROR_AUDIO_CODEC_CREATION_FAILED = -42,
197
111
  /**
198
- * Emitted when the internal room connection state of the ODIN client changed
112
+ * Encoding of an audio packet failed
199
113
  */
200
- OdinEvent_RoomConnectionStateChanged,
114
+ ODIN_ERROR_AUDIO_ENCODING_FAILED = -43,
201
115
  /**
202
- * Emitted when others peers sent arbitrary data
116
+ * Decoding of an audio packet failed
203
117
  */
204
- OdinEvent_MessageReceived,
205
- } OdinEventTag;
118
+ ODIN_ERROR_AUDIO_DECODING_FAILED = -44,
119
+ } OdinError;
206
120
 
207
- typedef struct OdinEvent_JoinedData {
208
- /**
209
- * Name of the joined room (null-terminated)
210
- */
211
- const char *room_id;
212
- /**
213
- * Length of the room name
214
- */
215
- size_t room_id_len;
121
+ /**
122
+ * Audio-related events emitted by encoders and decoders. These values act as bitflags and
123
+ * can be combined to filter or report multiple events.
124
+ */
125
+ typedef enum OdinAudioEvents {
216
126
  /**
217
- * Byte array with arbitrary user data of the room
127
+ * Triggered when the silence state changes.
218
128
  */
219
- const uint8_t *room_user_data;
129
+ ODIN_AUDIO_EVENTS_IS_SILENT_CHANGED = 1,
220
130
  /**
221
- * Length of the room user data array
131
+ * Enables all available audio events.
222
132
  */
223
- size_t room_user_data_len;
133
+ ODIN_AUDIO_EVENTS_ALL = -1,
134
+ } OdinAudioEvents;
135
+
136
+ /**
137
+ * Valid levels for aggressiveness of the noise suppression. A higher level will reduce the noise
138
+ * level at the expense of a higher speech distortion.
139
+ */
140
+ typedef enum OdinNoiseSuppressionLevel {
224
141
  /**
225
- * Identifier of the customer the room is assigned to (nul-terminated)
142
+ * Noise suppression is disabled
226
143
  */
227
- const char *customer;
144
+ ODIN_NOISE_SUPPRESSION_LEVEL_NONE,
228
145
  /**
229
- * Length of the customer identifier
146
+ * Use low suppression (6 dB)
230
147
  */
231
- size_t customer_len;
148
+ ODIN_NOISE_SUPPRESSION_LEVEL_LOW,
232
149
  /**
233
- * Own peer ID assigned by the server
150
+ * Use moderate suppression (12 dB)
234
151
  */
235
- uint64_t own_peer_id;
152
+ ODIN_NOISE_SUPPRESSION_LEVEL_MODERATE,
236
153
  /**
237
- * Own user identifier of the peer specified during authentication (null-terminated)
154
+ * Use high suppression (18 dB)
238
155
  */
239
- const char *own_user_id;
156
+ ODIN_NOISE_SUPPRESSION_LEVEL_HIGH,
240
157
  /**
241
- * Length of the own user identifier
158
+ * Use very high suppression (21 dB)
242
159
  */
243
- size_t own_user_id_len;
244
- } OdinEvent_JoinedData;
160
+ ODIN_NOISE_SUPPRESSION_LEVEL_VERY_HIGH,
161
+ } OdinNoiseSuppressionLevel;
245
162
 
246
- typedef struct OdinEvent_PeerJoinedData {
247
- /**
248
- * ID of the peer
249
- */
250
- uint64_t peer_id;
251
- /**
252
- * Byte array with arbitrary user data of the peer
253
- */
254
- const uint8_t *peer_user_data;
163
+ /**
164
+ * Available versions of the automatic gain controller (AGC) to be used. This adjusts the audio
165
+ * signal's amplitude to reach a target level, helping to maintain a consistent output.
166
+ */
167
+ typedef enum OdinGainControllerVersion {
255
168
  /**
256
- * Length of the room user data array
169
+ * AGC is disabled; the signal is not modified
257
170
  */
258
- size_t peer_user_data_len;
171
+ ODIN_GAIN_CONTROLLER_VERSION_NONE,
259
172
  /**
260
- * User identifier of the peer specified during authentication (null-terminated)
173
+ * Legacy AGC with adaptive digital gain control and a limiter
261
174
  */
262
- const char *user_id;
175
+ ODIN_GAIN_CONTROLLER_VERSION_V1,
263
176
  /**
264
- * Length of the user identifier
177
+ * Enhanced AGC with improved digital processing and an input volume controller
265
178
  */
266
- size_t user_id_len;
267
- } OdinEvent_PeerJoinedData;
179
+ ODIN_GAIN_CONTROLLER_VERSION_V2,
180
+ } OdinGainControllerVersion;
268
181
 
269
- typedef struct OdinEvent_PeerLeftData {
270
- /**
271
- * ID of the peer
272
- */
273
- uint64_t peer_id;
274
- } OdinEvent_PeerLeftData;
275
-
276
- typedef struct OdinEvent_PeerUserDataChangedData {
182
+ /**
183
+ * Defines the types of audio pipeline effects available.
184
+ */
185
+ typedef enum OdinEffectType {
277
186
  /**
278
- * ID of the peer
187
+ * Voice Activity Detection (VAD) effect for detecting active speech segments in an audio stream
279
188
  */
280
- uint64_t peer_id;
189
+ ODIN_EFFECT_TYPE_VAD,
281
190
  /**
282
- * Byte array with arbitrary user data of the peer
191
+ * Audio Processing Module (APM) effect to apply audio enhancements like noise suppression
283
192
  */
284
- const uint8_t *peer_user_data;
193
+ ODIN_EFFECT_TYPE_APM,
285
194
  /**
286
- * Length of the room user data array
195
+ * Custom user-defined audio processing effect that can be integrated into the audio pipeline
287
196
  */
288
- size_t peer_user_data_len;
289
- } OdinEvent_PeerUserDataChangedData;
197
+ ODIN_EFFECT_TYPE_CUSTOM,
198
+ } OdinEffectType;
290
199
 
291
- typedef struct OdinEvent_MediaAddedData {
292
- /**
293
- * ID of the peer this media belongs to
294
- */
295
- uint64_t peer_id;
296
- /**
297
- * Handle identifier of the new audio/video stream
298
- */
299
- OdinMediaStreamHandle media_handle;
300
- } OdinEvent_MediaAddedData;
200
+ /**
201
+ * An opaque type representing an ODIN connection pool, which encapsulates the internal management
202
+ * of all connections used by the clients. It is responsible for creating, retrieving and managing
203
+ * communication channels, handling room join requests and processing associated authorization and
204
+ * connection state changes. The connection pool ensures thread-safe access and coordinated shutdown
205
+ * of active connections. Additionally, it allows joining multiple rooms through the same connection
206
+ * by performing transparent connection sharing if possible.
207
+ */
208
+ typedef struct OdinConnectionPool OdinConnectionPool;
301
209
 
302
- typedef struct OdinEvent_MediaRemovedData {
303
- /**
304
- * ID of the peer this media belongs to
305
- */
306
- uint64_t peer_id;
307
- /**
308
- * Handle identifier of the audio/video stream
309
- */
310
- OdinMediaStreamHandle media_handle;
311
- } OdinEvent_MediaRemovedData;
210
+ /**
211
+ * Represents a decoder for media streams from remote voice chat clients, which encapsulates all
212
+ * the components required to process incoming audio streams. It includes an egress resampler for
213
+ * sample rate conversion, an Opus decoder for decompressing audio data, and a customizable audio
214
+ * pipeline that enables the application of effects to modify the raw audio samples.
215
+ *
216
+ * Encoder operations are thread-safe and the same encoder handle may be accessed concurrently
217
+ * from multiple threads.
218
+ */
219
+ typedef struct OdinDecoder OdinDecoder;
312
220
 
313
- typedef struct OdinEvent_MediaActiveStateChangedData {
314
- /**
315
- * ID of the peer this media belongs to
316
- */
317
- uint64_t peer_id;
318
- /**
319
- * Handle identifier of the audio/video stream
320
- */
321
- OdinMediaStreamHandle media_handle;
322
- /**
323
- * Indicator for whether or not the media is sending/receiving data
324
- */
325
- bool active;
326
- } OdinEvent_MediaActiveStateChangedData;
221
+ /**
222
+ * Represents an encoder for local media streams, which encapsulates the components required to
223
+ * process outgoing audio streams captured from local sources (e.g. a microphone). It includes
224
+ * an ingress resampler for sample rate conversion, an Opus encoder for compressing the audio
225
+ * data and a customizable audio pipeline that allows the application of effects to modify the
226
+ * raw audio samples before transmission.
227
+ *
228
+ * Encoder operations are thread-safe and the same encoder handle may be accessed concurrently
229
+ * from multiple threads.
230
+ */
231
+ typedef struct OdinEncoder OdinEncoder;
327
232
 
328
- typedef struct OdinEvent_RoomUserDataChangedData {
329
- /**
330
- * Byte array with arbitrary user data of the room
331
- */
332
- const uint8_t *room_user_data;
333
- /**
334
- * Length of the room user data array
335
- */
336
- size_t room_user_data_len;
337
- } OdinEvent_RoomUserDataChangedData;
233
+ /**
234
+ * A highly dynamic audio processing chain that manages a thread-safe collection of filters like
235
+ * voice activity detection, echo cancellation, noise suppression and even custom effects. This
236
+ * allows sequential processing and real-time modification of audio streams through operations
237
+ * like insertion, removal, reordering and configuration updates.
238
+ */
239
+ typedef struct OdinPipeline OdinPipeline;
338
240
 
339
- typedef struct OdinEvent_RoomConnectionStateChangedData {
340
- /**
341
- * Status of the room connection
342
- */
343
- enum OdinRoomConnectionState state;
344
- /**
345
- * Reason for this update
346
- */
347
- enum OdinRoomConnectionStateChangeReason reason;
348
- } OdinEvent_RoomConnectionStateChangedData;
241
+ /**
242
+ * An opaque type representing an ODIN room, which manages by the underlying connection through
243
+ * a shared connection pool. This abstraction provides a high-level interface for joining rooms,
244
+ * managing persistent state and sending/receiving data, making it easier to integrate room-based
245
+ * interactions into your application.
246
+ */
247
+ typedef struct OdinRoom OdinRoom;
349
248
 
350
- typedef struct OdinEvent_MessageReceivedData {
351
- /**
352
- * ID of the peer who sent this message
353
- */
354
- uint64_t peer_id;
355
- /**
356
- * Byte array with arbitrary data received
357
- */
358
- const uint8_t *data;
359
- /**
360
- * Length of the data array
361
- */
362
- size_t data_len;
363
- } OdinEvent_MessageReceivedData;
249
+ /**
250
+ * A struct for generating ODIN tokens, employed for generating signed room tokens predicated on
251
+ * an access key. Be aware that access keys serve as your unique authentication keys, requisite for
252
+ * generating room tokens to access the ODIN server network. To ensure your security, it's strongly
253
+ * recommended that you _NEVER_ embed an access key within your client code, and instead generate
254
+ * room tokens on a server.
255
+ */
256
+ typedef struct OdinTokenGenerator OdinTokenGenerator;
364
257
 
365
- typedef struct OdinEvent {
366
- OdinEventTag tag;
367
- union {
368
- OdinEvent_JoinedData joined;
369
- OdinEvent_PeerJoinedData peer_joined;
370
- OdinEvent_PeerLeftData peer_left;
371
- OdinEvent_PeerUserDataChangedData peer_user_data_changed;
372
- OdinEvent_MediaAddedData media_added;
373
- OdinEvent_MediaRemovedData media_removed;
374
- OdinEvent_MediaActiveStateChangedData media_active_state_changed;
375
- OdinEvent_RoomUserDataChangedData room_user_data_changed;
376
- OdinEvent_RoomConnectionStateChangedData room_connection_state_changed;
377
- OdinEvent_MessageReceivedData message_received;
378
- };
379
- } OdinEvent;
258
+ /**
259
+ * Settings for configuring connection pools to define a set of callback functions that a connection
260
+ * pool uses to notify the application about incoming events. The `on_datagram` callback is invoked
261
+ * when a voice packet is received, providing the internal id of the associated ODIN room handle, the
262
+ * sender media ID, the audio data buffer and a user-defined pointer for contextual information.
263
+ * Similarly, the `on_rpc` callback is triggered for all incoming RPCs. This structure enables flexible
264
+ * integration of custom handling logic across all of your connection pools.
265
+ */
266
+ typedef struct OdinConnectionPoolSettings {
267
+ /**
268
+ * Mandatory callback for incoming voice packets
269
+ */
270
+ void (*on_datagram)(uint64_t room_ref,
271
+ uint16_t media_id,
272
+ const uint8_t *bytes,
273
+ uint32_t bytes_length,
274
+ void *user_data);
275
+ /**
276
+ * Mandatory callback for incoming messages/events
277
+ */
278
+ void (*on_rpc)(uint64_t room_ref, const uint8_t *bytes, uint32_t bytes_length, void *user_data);
279
+ /**
280
+ * Optional user-defined data pointer, passed to all callbacks to provide a context or state
281
+ */
282
+ void *user_data;
283
+ } OdinConnectionPoolSettings;
284
+
285
+ /**
286
+ * Optional, pluggable encryption module for room communications. An cipher can be attached to an
287
+ * ODIN room handle on creation to enable customizable, end-to-end encryption (E2EE). When enabled,
288
+ * it intercepts data right before transmission and immediately after reception, allowing custom
289
+ * processing of datagrams, messages and custom peer user data. The structure provides a suite of
290
+ * callback functions for initialization, cleanup, event handling and encryption/decryption tasks,
291
+ * along with parameters to adjust for any additional capacity overhead.
292
+ */
293
+ typedef struct OdinCipher {
294
+ void (*init)(struct OdinCipher *cipher, struct OdinRoom *room);
295
+ void (*free)(struct OdinCipher *cipher);
296
+ void (*on_event)(struct OdinCipher *cipher, const unsigned char *bytes, uint32_t length);
297
+ int32_t (*encrypt_datagram)(struct OdinCipher *cipher,
298
+ const unsigned char *plaintext,
299
+ uint32_t plaintext_length,
300
+ unsigned char *ciphertext,
301
+ uint32_t ciphertext_capacity);
302
+ int32_t (*decrypt_datagram)(struct OdinCipher *cipher,
303
+ uint64_t peer_id,
304
+ const unsigned char *ciphertext,
305
+ uint32_t ciphertext_length,
306
+ unsigned char *plaintext,
307
+ uint32_t plaintext_capacity);
308
+ int32_t (*encrypt_message)(struct OdinCipher *cipher,
309
+ const unsigned char *plaintext,
310
+ uint32_t plaintext_length,
311
+ unsigned char *ciphertext,
312
+ uint32_t ciphertext_capacity);
313
+ int32_t (*decrypt_message)(struct OdinCipher *cipher,
314
+ uint64_t peer_id,
315
+ const unsigned char *ciphertext,
316
+ uint32_t ciphertext_length,
317
+ unsigned char *plaintext,
318
+ uint32_t plaintext_capacity);
319
+ int32_t (*encrypt_user_data)(struct OdinCipher *cipher,
320
+ const unsigned char *plaintext,
321
+ uint32_t plaintext_length,
322
+ unsigned char *ciphertext,
323
+ uint32_t ciphertext_capacity);
324
+ int32_t (*decrypt_user_data)(struct OdinCipher *cipher,
325
+ uint64_t peer_id,
326
+ const unsigned char *ciphertext,
327
+ uint32_t ciphertext_length,
328
+ unsigned char *plaintext,
329
+ uint32_t plaintext_capacity);
330
+ uint32_t additional_capacity_datagram;
331
+ uint32_t additional_capacity_message;
332
+ uint32_t additional_capacity_user_data;
333
+ } OdinCipher;
380
334
 
381
335
  /**
382
336
  * Statistics for the underlying connection of a room.
@@ -386,26 +340,26 @@ typedef struct OdinConnectionStats {
386
340
  * The amount of outgoing UDP datagrams observed
387
341
  */
388
342
  uint64_t udp_tx_datagrams;
389
- /**
390
- * The amount of outgoing acknowledgement frames observed
391
- */
392
- uint64_t udp_tx_acks;
393
343
  /**
394
344
  * The total amount of bytes which have been transferred inside outgoing UDP datagrams
395
345
  */
396
346
  uint64_t udp_tx_bytes;
397
347
  /**
398
- * The amount of incoming UDP datagrams observed
348
+ * The the packet loss percentage of outgoing UDP datagrams
399
349
  */
400
- uint64_t udp_rx_datagrams;
350
+ float udp_tx_loss;
401
351
  /**
402
- * The amount of incoming acknowledgement frames observed
352
+ * The amount of incoming UDP datagrams observed
403
353
  */
404
- uint64_t udp_rx_acks;
354
+ uint64_t udp_rx_datagrams;
405
355
  /**
406
356
  * The total amount of bytes which have been transferred inside incoming UDP datagrams
407
357
  */
408
358
  uint64_t udp_rx_bytes;
359
+ /**
360
+ * The the packet loss percentage of incoming UDP datagrams
361
+ */
362
+ float udp_rx_loss;
409
363
  /**
410
364
  * Current congestion window of the connection
411
365
  */
@@ -421,480 +375,624 @@ typedef struct OdinConnectionStats {
421
375
  } OdinConnectionStats;
422
376
 
423
377
  /**
424
- * Per-room configuration of the ODIN audio processing module which provides a variety of smart
425
- * enhancement algorithms.
378
+ * Audio decoder jitter statistics.
426
379
  */
427
- typedef struct OdinApmConfig {
380
+ typedef struct OdinDecoderJitterStats {
428
381
  /**
429
- * Enables or disables voice activity detection (VAD)
382
+ * The total number of packets seen by the medias jitter buffer.
430
383
  */
431
- bool voice_activity_detection;
384
+ uint32_t packets_total;
432
385
  /**
433
- * Voice probability value when the VAD should engage
386
+ * The number of packets available in the medias jitter buffer.
434
387
  */
435
- float voice_activity_detection_attack_probability;
388
+ uint32_t packets_buffered;
436
389
  /**
437
- * Voice probability value when the VAD should disengage
390
+ * The number of packets processed by the medias jitter buffer.
438
391
  */
439
- float voice_activity_detection_release_probability;
392
+ uint32_t packets_processed;
440
393
  /**
441
- * Enables or disables the input volume gate
394
+ * The number of packets dropped because they seemed to arrive too early.
442
395
  */
443
- bool volume_gate;
396
+ uint32_t packets_arrived_too_early;
444
397
  /**
445
- * Root mean square power (dBFS) when the volume gate should engage
398
+ * The number of packets dropped because they seemed to arrive too late.
446
399
  */
447
- float volume_gate_attack_loudness;
400
+ uint32_t packets_arrived_too_late;
448
401
  /**
449
- * Root mean square power (dBFS) when the volume gate should disengage
402
+ * The number of packets dropped due to a jitter buffer reset.
450
403
  */
451
- float volume_gate_release_loudness;
404
+ uint32_t packets_dropped;
452
405
  /**
453
- * Enable or disable echo cancellation
406
+ * The number of packets marked as invalid.
454
407
  */
455
- bool echo_canceller;
408
+ uint32_t packets_invalid;
456
409
  /**
457
- * Enable or disable high pass filtering
410
+ * The number of packets marked as duplicates.
458
411
  */
459
- bool high_pass_filter;
412
+ uint32_t packets_repeated;
460
413
  /**
461
- * Enable or disable the pre amplifier
414
+ * The number of packets marked as lost during transmission.
462
415
  */
463
- bool pre_amplifier;
416
+ uint32_t packets_lost;
417
+ } OdinDecoderJitterStats;
418
+
419
+ /**
420
+ * A callback invoked when the decoder reports one or more audio events.
421
+ */
422
+ typedef void (*OdinDecoderEventCallback)(struct OdinDecoder *decoder,
423
+ enum OdinAudioEvents events,
424
+ void *user_data);
425
+
426
+ /**
427
+ * A callback invoked when the encoder reports one or more audio events.
428
+ */
429
+ typedef void (*OdinEncoderEventCallback)(struct OdinEncoder *encoder,
430
+ enum OdinAudioEvents events,
431
+ void *user_data);
432
+
433
+ /**
434
+ * Sensitivity parameters for ODIN voice activity detection module configuration.
435
+ */
436
+ typedef struct OdinSensitivityConfig {
464
437
  /**
465
- * Set the aggressiveness of the suppression
438
+ * Indicates whether the sensitivity configuration is enabled
466
439
  */
467
- enum OdinNoiseSuppressionLevel noise_suppression_level;
440
+ bool enabled;
468
441
  /**
469
- * Enable or disable the transient suppressor
442
+ * The threshold at which the trigger should engage
470
443
  */
471
- bool transient_suppressor;
444
+ float attack_threshold;
472
445
  /**
473
- * Enable or disable the gain controller
446
+ * The threshold at which the trigger should disengage
474
447
  */
475
- bool gain_controller;
476
- } OdinApmConfig;
448
+ float release_threshold;
449
+ } OdinSensitivityConfig;
477
450
 
478
451
  /**
479
- * Audio stream statistics.
452
+ * Pipeline configuration of the ODIN voice activity detection module, which offers advanced
453
+ * algorithms to accurately determine when to start or stop transmitting audio data.
480
454
  */
481
- typedef struct OdinAudioStreamStats {
455
+ typedef struct OdinVadConfig {
482
456
  /**
483
- * The total number of packets seen by the medias jitter buffer.
457
+ * When enabled, ODIN will analyze the audio input signal using smart voice detection algorithm
458
+ * to determine the presence of speech. You can define both the probability required to start
459
+ * and stop transmitting.
484
460
  */
485
- uint32_t packets_total;
461
+ struct OdinSensitivityConfig voice_activity;
486
462
  /**
487
- * The number of packets processed by the medias jitter buffer.
463
+ * When enabled, ODIN will measure the volume of the input audio signal, thus deciding when a
464
+ * user is speaking loud enough to transmit voice data. You can define both the root-mean-square
465
+ * power (dBFS) for when the gate should engage and disengage.
488
466
  */
489
- uint32_t packets_processed;
490
- /**
491
- * The number of packets dropped because they seemed to arrive too early.
492
- */
493
- uint32_t packets_arrived_too_early;
467
+ struct OdinSensitivityConfig volume_gate;
468
+ } OdinVadConfig;
469
+
470
+ /**
471
+ * Pipeline configuration of the ODIN audio processing module which provides a variety of smart
472
+ * enhancement algorithms.
473
+ */
474
+ typedef struct OdinApmConfig {
494
475
  /**
495
- * The number of packets dropped because they seemed to arrive too late.
476
+ * When enabled the echo canceller will try to subtract echoes, reverberation, and unwanted
477
+ * added sounds from the audio input signal. Note, that you need to process the reverse audio
478
+ * stream, also known as the loopback data to be used in the ODIN echo canceller.
496
479
  */
497
- uint32_t packets_arrived_too_late;
480
+ bool echo_canceller;
498
481
  /**
499
- * The number of packets dropped due to a jitter buffer reset.
482
+ * When enabled, the high-pass filter will remove low-frequency content from the input audio
483
+ * signal, thus making it sound cleaner and more focused.
500
484
  */
501
- uint32_t packets_dropped;
485
+ bool high_pass_filter;
502
486
  /**
503
- * The number of packets marked as invalid.
487
+ * When enabled, the transient suppressor will try to detect and attenuate keyboard clicks.
504
488
  */
505
- uint32_t packets_invalid;
489
+ bool transient_suppressor;
506
490
  /**
507
- * The number of packets marked as duplicates.
491
+ * When enabled, the noise suppressor will remove distracting background noise from the input
492
+ * audio signal. You can control the aggressiveness of the suppression. Increasing the level
493
+ * will reduce the noise level at the expense of a higher speech distortion.
508
494
  */
509
- uint32_t packets_repeated;
495
+ enum OdinNoiseSuppressionLevel noise_suppression_level;
510
496
  /**
511
- * The number of packets marked as lost during transmission.
497
+ * When enabled, the gain controller will bring the input audio signal to an appropriate range
498
+ * when it's either too loud or too quiet.
512
499
  */
513
- uint32_t packets_lost;
514
- } OdinAudioStreamStats;
515
-
516
- typedef size_t OdinResamplerHandle;
500
+ enum OdinGainControllerVersion gain_controller_version;
501
+ } OdinApmConfig;
517
502
 
518
503
  /**
519
- * Options for ODIN room tokens.
504
+ * Defines the signature for custom effect callbacks in an ODIN audio pipeline. The callback
505
+ * receives a pointer to a buffer of audio samples, the number of samples in the buffer, a
506
+ * pointer to a flag indicating whether the audio is silent. This allows for custom, in-place
507
+ * processing of an audio stream.
520
508
  */
521
- typedef struct OdinTokenOptions {
522
- /**
523
- * Customer identifier (you should _NOT_ set this unless connecting directly to an ODIN server)
524
- */
525
- const char *customer;
526
- /**
527
- * Audience of the token
528
- */
529
- enum OdinTokenAudience audience;
530
- /**
531
- * Token lifetime in seconds
532
- */
533
- uint64_t lifetime;
534
- } OdinTokenOptions;
509
+ typedef void (*OdinCustomEffectCallback)(float *samples,
510
+ uint32_t samples_count,
511
+ bool *is_silent,
512
+ const void *user_data);
535
513
 
536
514
  #ifdef __cplusplus
537
515
  extern "C" {
538
516
  #endif // __cplusplus
539
517
 
540
518
  /**
541
- * Formats an ODIN return code into a human readable string representation for use in logging and
542
- * diagnostics. If `buf` is `NULL` this functions simply returns the required buffer length to
543
- * store the output buffer.
519
+ * Initializes the internal ODIN client runtime with a specified version number, ensuring the correct
520
+ * header file is employed. The majority of the API functions hinge on an active ODIN runtime.
521
+ *
522
+ * Note: Utilize `ODIN_VERSION` to supply the `version` argument.
544
523
  */
545
- size_t odin_error_format(OdinReturnCode error, char *buf, size_t buf_len);
524
+ enum OdinError odin_initialize(const char *version);
546
525
 
547
526
  /**
548
- * Checks whether the code returned from ODIN function calls represents an error or an actual
549
- * result. This is used to easier work with certain functions that might return an error or a
550
- * valid result like `odin_audio_data_len`.
551
- * Internally this simply does `(code >> 29) > 0`.
527
+ * Shuts down the internal ODIN runtime including all active connection pools. It is advisable to
528
+ * invoke this function prior to terminating your application.
552
529
  */
553
- bool odin_is_error(OdinReturnCode code);
530
+ void odin_shutdown(void);
554
531
 
555
532
  /**
556
- * Initializes the internal ODIN client runtime with optimized settings for audio output, ensuring
557
- * the correct API header file is employed. This operation is ref-counted, necessitating paired
558
- * invocations of startup and shutdown within your application. The majority of the API functions
559
- * hinge on an active ODIN runtime, with the sole exception of `access_key` and `token_generator`
560
- * related functions.
561
- *
562
- * Note: Utilize `ODIN_VERSION` to supply the `version` argument.
533
+ * Returns the error message from the last occurred error, if available. If no error is present,
534
+ * an empty string is returned.
563
535
  */
564
- bool odin_startup(const char *version);
536
+ const char *odin_error_get_last_error(void);
565
537
 
566
538
  /**
567
- * Initializes the internal ODIN client runtime, permitting the specification of sample rate and
568
- * channel layout for audio output. This operation is ref-counted, necessitating paired invocations
569
- * of startup and shutdown within your application.
570
- *
571
- * Note: Ensure consistent settings are used on successive invocations of this function.
539
+ * Resets the last error message by clearing the error buffer.
572
540
  */
573
- bool odin_startup_ex(const char *version, struct OdinAudioStreamConfig output_config);
541
+ void odin_error_reset_last_error(void);
574
542
 
575
543
  /**
576
- * Shuts down the internal ODIN runtime. It is advisable to invoke this function prior to
577
- * terminating the application. Post invocation, all `odin_*` methods will cease to function
578
- * immediately, provided the internal ref-count has descended to zero. Refer to `odin_startup`
579
- * for additional details.
544
+ * Initializes a new ODIN connection pool with the given settings and outputs a pointer to the
545
+ * newly created connection pool. The connection pool is intended to manage multiple connections
546
+ * efficiently.
580
547
  */
581
- void odin_shutdown(void);
548
+ enum OdinError odin_connection_pool_create(struct OdinConnectionPoolSettings settings,
549
+ struct OdinConnectionPool **out_connection_pool);
582
550
 
583
551
  /**
584
- * Creates a new ODIN room handle in an unconnected state and returns its handle identifier. This
585
- * will return `0` when the internal ODIN client runtime is not initialized using `odin_startup`
586
- * or has already been terminated using `odin_shutdown`.
552
+ * Frees the specified ODIN connection pool and releases the resources associated with it. If the
553
+ * connection pool is currently active, it will be properly shut down before being freed.
587
554
  */
588
- OdinRoomHandle odin_room_create(void);
555
+ void odin_connection_pool_free(struct OdinConnectionPool *connection_pool);
556
+
557
+ /**
558
+ * Creates a new ODIN room with default parameters. This basic variant requires only the connection
559
+ * pool, the address of an ODIN gateway/server and a JSON Web Token (JWT) for user authentication.
560
+ * On success, it returns the created room handle and immediately triggers asynchronous connection
561
+ * establishment, allowing the local peer to join the room.
562
+ *
563
+ * NOTE: For advanced configuration, see `odin_room_create_ex`.
564
+ */
565
+ enum OdinError odin_room_create(struct OdinConnectionPool *connection_pool,
566
+ const char *uri,
567
+ const char *token,
568
+ struct OdinRoom **out_room);
569
+
570
+ /**
571
+ * Creates a new ODIN room with advanced parameters. In addition to the parameters required by the
572
+ * basic variant, this function accepts an optional room name to select a specific room when the
573
+ * token contains multiple room names (`odin_room_create` simply uses the first room name from the
574
+ * authentication token). It also allows specifying initial peer user data as a byte array and a
575
+ * 3-element float array representing 3D coordinates used for server-side voice packet culling.
576
+ * Additionally, an optional ODIN cipher plugin can be provided to enable end-to-end encryption
577
+ * of room communications. On success, it returns the created room handle and triggers asynchronous
578
+ * connection establishment, allowing the local peer to join the room.
579
+ */
580
+ enum OdinError odin_room_create_ex(struct OdinConnectionPool *connection_pool,
581
+ const char *uri,
582
+ const char *token,
583
+ const char *room_name,
584
+ const unsigned char *user_data,
585
+ uint32_t user_data_length,
586
+ const float position[3],
587
+ struct OdinCipher *cipher,
588
+ struct OdinRoom **out_room);
589
589
 
590
590
  /**
591
591
  * Closes the specified ODIN room handle, thus making our own peer leave the room on the server
592
592
  * and closing the connection if needed.
593
593
  */
594
- OdinReturnCode odin_room_close(OdinRoomHandle room);
594
+ void odin_room_close(struct OdinRoom *room);
595
595
 
596
596
  /**
597
- * Destroys the specified ODIN room handle.
597
+ * Retrieves the unique handle identifier for the specified room. Returns `0` if the room is invalid.
598
598
  */
599
- OdinReturnCode odin_room_destroy(OdinRoomHandle room);
599
+ uint64_t odin_room_get_ref(struct OdinRoom *room);
600
600
 
601
601
  /**
602
- * Sets the event callback on the the specified `OdinRoomHandle`. Generally this should be called
603
- * _once_ before joining a room.
602
+ * Retrieves the name from the specified room.
604
603
  */
605
- OdinReturnCode odin_room_set_event_callback(OdinRoomHandle room,
606
- void (*callback)(OdinRoomHandle room,
607
- const struct OdinEvent *event,
608
- void *extra_data),
609
- void *extra_data);
604
+ enum OdinError odin_room_get_name(struct OdinRoom *room,
605
+ char *out_value,
606
+ uint32_t *out_value_length);
610
607
 
611
608
  /**
612
- * Sets the scaling factor for coordinates supplied to `odin_room_update_position`, facilitating
613
- * adaptation to your game's unique coordinate system requirements. Peers are visible to each other
614
- * only within a unit circle of radius `1.0`. When altering a peer's position, ensure the position
615
- * is scaled such that the maximum distance remains one or less. This scaling can be performed
616
- * manually or by specifying the multiplicative scale here.
617
- *
618
- * Note: It's crucial to maintain consistent scaling across all client applications.
609
+ * Retrieves the underlying connection identifier associated with the room, or `0` if no valid
610
+ * connection exists.
619
611
  */
620
- OdinReturnCode odin_room_set_position_scale(OdinRoomHandle room, float scale);
612
+ uint64_t odin_room_get_connection_id(struct OdinRoom *room);
621
613
 
622
614
  /**
623
- * Joins a room on an ODIN server. This function takes an URL to an ODIN gateway and a signed room
624
- * token obtained externally that authorizes the client to establish the connection. Unless you're
625
- * hosting your own servers, always use gateway running at `https://gateway.odin.4players.io`.
615
+ * Retrieves detailed connection statistics for the specified room, filling the provided structure
616
+ * with data such as the number of transmitted/received datagrams, bytes, packet loss percentage,
617
+ * congestion window information and round-trip time.
626
618
  */
627
- OdinReturnCode odin_room_join(OdinRoomHandle room, const char *url, const char *token);
619
+ enum OdinError odin_room_get_connection_stats(struct OdinRoom *room,
620
+ struct OdinConnectionStats *out_stats);
628
621
 
629
622
  /**
630
- * Retrieves the room ID (e.g. the name of the room) from the specified `OdinRoomHandle`.
623
+ * Flushes the local peer's user data by re-sending it to the server, ensuring that the latest
624
+ * data is synchronized across all connected peers. This function does NOT need to be invoked
625
+ * manually. It is typically used internally by an ODIN cipher after encryption key rotations
626
+ * to update and maintain data consistency.
631
627
  */
632
- OdinReturnCode odin_room_id(OdinRoomHandle room, char *out_id, size_t out_id_len);
628
+ enum OdinError odin_room_resend_user_data(struct OdinRoom *room);
633
629
 
634
630
  /**
635
- * Retrieves the identifier of the customer the room is assigned to from the specified `OdinRoomHandle`.
631
+ * Sends a MessagePack encoded RPC message to the server for the specified room.
636
632
  */
637
- OdinReturnCode odin_room_customer(OdinRoomHandle room,
638
- char *out_customer,
639
- size_t out_customer_len);
633
+ enum OdinError odin_room_send_rpc(struct OdinRoom *room,
634
+ const uint8_t *bytes,
635
+ uint32_t bytes_length);
640
636
 
641
637
  /**
642
- * Retrieves your own peer ID from the specified `OdinRoomHandle`.
638
+ * Sends a MessagePack encoded RPC message using a local loopback mechanism. It bypasses
639
+ * the normal network transmission by directly invoking the RPC callback configured in
640
+ * the connection pool settings. It is useful for emitting synthetic events for testing
641
+ * and internal processing without involving the network layer.
643
642
  */
644
- OdinReturnCode odin_room_peer_id(OdinRoomHandle room, uint64_t *out_peer_id);
643
+ enum OdinError odin_room_send_loopback_rpc(struct OdinRoom *room,
644
+ const uint8_t *bytes,
645
+ uint32_t bytes_length);
645
646
 
646
647
  /**
647
- * Retrieves statistics for the underlying connection of the specified `OdinRoomHandle`.
648
+ * Sends an encoded voice packet to the server for the specified room.
648
649
  */
649
- OdinReturnCode odin_room_connection_stats(OdinRoomHandle room, struct OdinConnectionStats *stats);
650
+ enum OdinError odin_room_send_datagram(struct OdinRoom *room,
651
+ const uint8_t *bytes,
652
+ uint32_t bytes_length);
650
653
 
651
654
  /**
652
- * Updates the custom user data for your own peer. All user data is synced automatically, which
653
- * allows storing of arbitrary information for each individual peer.
654
- *
655
- * Note: Use this before calling `odin_room_join` to set initial peer user data upon connect.
655
+ * Destroys the specified ODIN room handle.
656
+ */
657
+ void odin_room_free(struct OdinRoom *room);
658
+
659
+ /**
660
+ * Creates a new instance of an ODIN decoder with default settings used to process the remote
661
+ * media stream specified with the `media_id` parameter. The resulting decoder encapsulates an
662
+ * egress resampler using the given sample rate and channel layout.
656
663
  */
657
- OdinReturnCode odin_room_update_peer_user_data(OdinRoomHandle room,
658
- const uint8_t *user_data,
659
- size_t user_data_length);
664
+ enum OdinError odin_decoder_create(uint16_t media_id,
665
+ uint32_t sample_rate,
666
+ bool stereo,
667
+ struct OdinDecoder **out_decoder);
660
668
 
661
669
  /**
662
- * Updates the three-dimensional position of the current peer within the specified `OdinRoomHandle`.
663
- * The server utilizes the provided coordinates to perform automatic culling among peers in the same
664
- * room, based on unit circles with a radius of `1.0`. This feature is particularly beneficial in
665
- * scenarios involving a large number of peers within the same room, enabling peers to interact or
666
- * 'see' each other only when in close proximity. To modify the distance sensitivity for position
667
- * updates, use `odin_room_set_position_scale`.
670
+ * Creates a new instance of an ODIN decoder with extended configuration options for processing
671
+ * a remote media stream specified by the `media_id` parameter. Like `odin_decoder_create`, this
672
+ * function initializes a decoder with an embedded egress resampler using the provided sample
673
+ * rate and channel layout. However, this extended version allows you to customize the jitter
674
+ * handling by specifying the number of packets to use in calculating the base jitter.
668
675
  *
669
- * Note: Use this before calling `odin_room_join` to set the initial peer position upon connect.
676
+ * The base jitter is computed as the product of the number of packets and the duration of a
677
+ * single packet, which corresponds to 20ms in 90kHz units. Setting `base_jitter_packets` to `2`
678
+ * will yield a base jitter of 40ms. Adjusting this parameter can affect how the decoder handles
679
+ * variations in packet arrival times and performs loss concealment during periods of silence or
680
+ * packet loss.
670
681
  */
671
- OdinReturnCode odin_room_update_position(OdinRoomHandle room, float x, float y, float z);
682
+ enum OdinError odin_decoder_create_ex(uint16_t media_id,
683
+ uint32_t sample_rate,
684
+ bool stereo,
685
+ uint8_t base_jitter_packets,
686
+ struct OdinDecoder **out_decoder);
672
687
 
673
688
  /**
674
- * Sends arbitrary data to a list of target peers over the ODIN server. If `NULL` is specified, the
675
- * message will be sent to all other peers in the same room.
689
+ * Returns a pointer to the internal ODIN audio pipeline instance used by the given decoder.
676
690
  */
677
- OdinReturnCode odin_room_send_message(OdinRoomHandle room,
678
- const uint64_t *peer_id_list,
679
- size_t peer_id_list_size,
680
- const uint8_t *data,
681
- size_t data_length);
691
+ const struct OdinPipeline *odin_decoder_get_pipeline(struct OdinDecoder *decoder);
682
692
 
683
693
  /**
684
- * Adds a specified `OdinMediaStreamHandle` to the room. Please note, that this can only be done
685
- * _once_ on a given media. Trying to do it more than once will return an error on subsequent calls
686
- * to this function.
694
+ * Pushes an incoming datagram to the specified decoder for processing.
687
695
  */
688
- OdinReturnCode odin_room_add_media(OdinRoomHandle room, OdinMediaStreamHandle media);
696
+ enum OdinError odin_decoder_push(struct OdinDecoder *decoder,
697
+ const uint8_t *datagram,
698
+ uint32_t datagram_length);
689
699
 
690
700
  /**
691
- * Configures the ODIN audio processing module on the room with the specified config.
701
+ * Retrieves a block of processed audio samples from the decoder's buffer. The samples are
702
+ * interleaved floating-point values in the range [-1, 1] and are written into the provided
703
+ * output buffer. A flag is also set to indicate if the output is silent.
692
704
  */
693
- OdinReturnCode odin_room_configure_apm(OdinRoomHandle room, struct OdinApmConfig config);
705
+ enum OdinError odin_decoder_pop(struct OdinDecoder *decoder,
706
+ float *out_samples,
707
+ uint32_t out_samples_count,
708
+ bool *out_is_silent);
694
709
 
695
710
  /**
696
- * Creates a new audio input stream, which can be added to a room and send data over it.
711
+ * Collects and returns jitter statistics for the specified decoder.
697
712
  */
698
- OdinMediaStreamHandle odin_audio_stream_create(struct OdinAudioStreamConfig config);
713
+ enum OdinError odin_decoder_get_jitter_stats(struct OdinDecoder *decoder,
714
+ struct OdinDecoderJitterStats *out_stats);
699
715
 
700
716
  /**
701
- * Creates a new video input stream, which can be added to a room and send data over it.
702
- *
703
- * Note: Video streams are not supported yet.
717
+ * Returns whether the decoder is currently processing silence. This reflects the internal
718
+ * silence detection state of the decoder, which updates as audio is processed. If the
719
+ * provided handle is invalid, the function returns `true` for safety.
704
720
  */
705
- OdinMediaStreamHandle odin_video_stream_create(void);
721
+ bool odin_decoder_is_silent(struct OdinDecoder *decoder);
706
722
 
707
723
  /**
708
- * Destroys the specified `OdinMediaStreamHandle`, after which you will no longer be able to
709
- * receive or send any data over it. If the media is currently 'attached' to a room it will be
710
- * removed.
724
+ * Registers a callback to receive decoder audio events. The `filter` determines which event
725
+ * types will trigger the callback, allowing selective handling. Any previously registered
726
+ * callback is replaced. The callback is invoked with the decoder handle, the combined event
727
+ * bitmask and the supplied `user_data`.
711
728
  */
712
- OdinReturnCode odin_media_stream_destroy(OdinMediaStreamHandle stream);
729
+ enum OdinError odin_decoder_set_event_callback(struct OdinDecoder *decoder,
730
+ enum OdinAudioEvents filter,
731
+ OdinDecoderEventCallback callback,
732
+ void *user_data);
713
733
 
714
734
  /**
715
- * Retrieves the media ID of the specified `OdinMediaStreamHandle`.
735
+ * Frees the resources associated with the specified decoder.
716
736
  */
717
- OdinReturnCode odin_media_stream_media_id(OdinMediaStreamHandle stream, uint16_t *out_media_id);
737
+ void odin_decoder_free(struct OdinDecoder *decoder);
718
738
 
719
739
  /**
720
- * Retrieves the peer ID of the specified `OdinMediaStreamHandle`.
740
+ * Creates a new ODIN encoder instance with default settings used to encode audio captured from
741
+ * local sources, such as a microphone. The encoder encapsulates an ingress resampler using the
742
+ * given sample rate and channel layout.
721
743
  */
722
- OdinReturnCode odin_media_stream_peer_id(OdinMediaStreamHandle stream, uint64_t *out_peer_id);
744
+ enum OdinError odin_encoder_create(uint32_t sample_rate,
745
+ bool stereo,
746
+ struct OdinEncoder **out_encoder);
723
747
 
724
748
  /**
725
- * Returns the type of the specified media stream.
726
- *
727
- * Note: This function will always return `OdinMediaStreamType_Audio` at the moment.
749
+ * Creates a new ODIN encoder instance for local media streams with extended codec configuration
750
+ * parameters. In addition to the sample rate and stereo configuration, it allows specification
751
+ * of whether the application is intended for VoIP, a target bitrate and the encoder's expected
752
+ * packet loss percentage.
728
753
  */
729
- enum OdinMediaStreamType odin_media_stream_type(OdinMediaStreamHandle stream);
754
+ enum OdinError odin_encoder_create_ex(uint32_t sample_rate,
755
+ bool stereo,
756
+ bool application_voip,
757
+ uint32_t bitrate_kbps,
758
+ uint8_t packet_loss_perc,
759
+ struct OdinEncoder **out_encoder);
730
760
 
731
761
  /**
732
- * Instructs the server to pause the specified `OdinMediaStreamHandle`, ceasing the reception of
733
- * data. This operation essentially communicates a server-side mute request from the client, thus
734
- * indicating a desire to halt packet reception for this media stream.
762
+ * Returns a pointer to the internal ODIN audio pipeline instance used by the given encoder.
735
763
  */
736
- OdinReturnCode odin_media_stream_pause(OdinMediaStreamHandle stream);
764
+ const struct OdinPipeline *odin_encoder_get_pipeline(struct OdinEncoder *encoder);
737
765
 
738
766
  /**
739
- * Instructs the server to resume the specified output `OdinMediaStreamHandle`, re-initiating the
740
- * reception of data. This operation essentially communicates a server-side unmute request from the
741
- * client, indicating a desire to restart packet reception for this media stream.
767
+ * Pushes raw audio samples to the encoder for processing. The provided audio samples, which
768
+ * must be interleaved floating-point values in the range [-1, 1], are processed through the
769
+ * encoder's pipeline, allowing any configured effects to be applied prior to encoding.
742
770
  */
743
- OdinReturnCode odin_media_stream_resume(OdinMediaStreamHandle stream);
771
+ enum OdinError odin_encoder_push(struct OdinEncoder *encoder,
772
+ const float *samples,
773
+ uint32_t samples_count);
744
774
 
745
775
  /**
746
- * Sends data to the audio stream. The data has to be interleaved [-1, 1] float data.
776
+ * Retrieves an encoded datagram from the encoder's buffer. It can optionally consider multiple
777
+ * media IDs for processing, which can be useful when you're sending a voice packet to more than
778
+ * one room. The encoded data is written to the provided output buffer. Each datagram can include
779
+ * up to 4 media IDs. These IDs are drawn from the pool assigned by the server when joining a room,
780
+ * enabling a single datagram to be routed across multiple rooms.
747
781
  */
748
- OdinReturnCode odin_audio_push_data(OdinMediaStreamHandle stream, const float *buf, size_t buf_len);
782
+ enum OdinError odin_encoder_pop(struct OdinEncoder *encoder,
783
+ const uint16_t *media_ids,
784
+ uint32_t media_ids_length,
785
+ uint8_t *out_datagram,
786
+ uint32_t *out_datagram_length);
749
787
 
750
788
  /**
751
- * Reads audio data from the specified `OdinMediaStreamHandle`. This will return audio data in the
752
- * format specified when calling `odin_startup_ex` or 48 kHz interleaved by default.
789
+ * Returns whether the encoder is currently processing silence. This reflects the internal
790
+ * silence detection state of the encoder, which updates as audio is processed. If the
791
+ * provided handle is invalid, the function returns `true` for safety.
753
792
  */
754
- OdinReturnCode odin_audio_read_data(OdinMediaStreamHandle stream,
755
- float *out_buffer,
756
- size_t out_buffer_len);
793
+ bool odin_encoder_is_silent(struct OdinEncoder *encoder);
757
794
 
758
795
  /**
759
- * Returns the number of samples available in the audio buffer of an output `OdinMediaStreamHandle`.
796
+ * Registers a callback to receive encoder audio events. The `filter` determines which event
797
+ * types will trigger the callback, allowing selective handling. Any previously registered
798
+ * callback is replaced. The callback is invoked with the encoder handle, the combined event
799
+ * bitmask and the supplied `user_data`.
760
800
  */
761
- OdinReturnCode odin_audio_data_len(OdinMediaStreamHandle stream);
801
+ enum OdinError odin_encoder_set_event_callback(struct OdinEncoder *encoder,
802
+ enum OdinAudioEvents filter,
803
+ OdinEncoderEventCallback callback,
804
+ void *user_data);
762
805
 
763
806
  /**
764
- * Resets the specified `OdinMediaStreamHandle` to its initial state, restoring it to its default
765
- * configuration. This operation resets the internal Opus encoder/decoder, ensuring a clean state.
766
- * Additionally, it clears internal buffers, providing a fresh start.
807
+ * Frees the resources associated with the specified encoder.
767
808
  */
768
- OdinReturnCode odin_audio_reset(OdinMediaStreamHandle stream);
809
+ void odin_encoder_free(struct OdinEncoder *encoder);
769
810
 
770
811
  /**
771
- * Retrieves statistics for the specified `OdinMediaStreamHandle`.
772
- *
773
- * Note: This will only work for output streams.
812
+ * Inserts a Voice Activity Detection (VAD) effect into the audio pipeline at the specified
813
+ * index and returns a unique effect identifier.
774
814
  */
775
- OdinReturnCode odin_audio_stats(OdinMediaStreamHandle stream, struct OdinAudioStreamStats *stats);
815
+ enum OdinError odin_pipeline_insert_vad_effect(const struct OdinPipeline *pipeline,
816
+ uint32_t index,
817
+ uint32_t *out_effect_id);
776
818
 
777
819
  /**
778
- * Reads up to `out_buffer_len` samples from the given streams and mixes them into the `out_buffer`.
779
- * All audio streams will be read based on the sample rate you chose when initializing the ODIN runtime
780
- * so make sure to allocate the buffer accordingly. After the call the `out_buffer_len` will contain
781
- * the amount of samples that have actually been read and mixed into `out_buffer`.
782
- *
783
- * If enabled this will also apply any audio processing to the output stream and feed back required
784
- * data to the internal audio processing pipeline which requires a final mix.
820
+ * Retrieves the configuration for a VAD effect identified by `effect_id` from the specified
821
+ * audio pipeline.
785
822
  */
786
- OdinReturnCode odin_audio_mix_streams(OdinRoomHandle room,
787
- const OdinMediaStreamHandle *streams,
788
- size_t stream_count,
789
- float *out_buffer,
790
- size_t out_buffer_len);
823
+ enum OdinError odin_pipeline_get_vad_config(const struct OdinPipeline *pipeline,
824
+ uint32_t effect_id,
825
+ struct OdinVadConfig *out_config);
791
826
 
792
827
  /**
793
- * Processes the reverse audio stream, also known as the loopback data to be used in the ODIN echo
794
- * canceller. This should only be done if you are _NOT_ using `odin_audio_mix_streams`.
828
+ * Updates the configuration settings of the VAD effect identified by `effect_id` in the specified
829
+ * audio pipeline.
795
830
  */
796
- OdinReturnCode odin_audio_process_reverse(OdinRoomHandle room, float *buffer, size_t buffer_len);
831
+ enum OdinError odin_pipeline_set_vad_config(const struct OdinPipeline *pipeline,
832
+ uint32_t effect_id,
833
+ const struct OdinVadConfig *config);
797
834
 
798
835
  /**
799
- * Sets the delay estimate for the reverse stream used in the ODIN echo cancellation. This function
800
- * is important in scenarios where the audio output and the audio input are not synchronized. An
801
- * accurate delay value ensures that the echo canceller can correctly align the two audio streams,
802
- * resulting in effective echo cancellation.
803
- *
804
- * Improper delay values may lead to poor echo cancellation and thus degrade the quality of the
805
- * audio communication.
836
+ * Inserts an Audio Processing Module (APM) effect into the audio pipeline at the specified index
837
+ * and returns a unique effect identifier.
838
+ */
839
+ enum OdinError odin_pipeline_insert_apm_effect(const struct OdinPipeline *pipeline,
840
+ uint32_t index,
841
+ uint32_t playback_sample_rate,
842
+ bool playback_stereo,
843
+ uint32_t *out_effect_id);
844
+
845
+ /**
846
+ * Retrieves the configuration for an APM effect identified by `effect_id` from the specified
847
+ * audio pipeline.
806
848
  */
807
- OdinReturnCode odin_audio_set_stream_delay(OdinRoomHandle room, uint64_t delay_ms);
849
+ enum OdinError odin_pipeline_get_apm_config(const struct OdinPipeline *pipeline,
850
+ uint32_t effect_id,
851
+ struct OdinApmConfig *out_config);
808
852
 
809
853
  /**
810
- * Creates a new ODIN resampler instance. This is intended for situations where your audio pipeline
811
- * doesn't support 48 kHz.
854
+ * Updates the configuration settings of the APM effect identified by `effect_id` in the specified
855
+ * audio pipeline.
856
+ */
857
+ enum OdinError odin_pipeline_set_apm_config(const struct OdinPipeline *pipeline,
858
+ uint32_t effect_id,
859
+ const struct OdinApmConfig *config);
860
+
861
+ /**
862
+ * Updates the specified APM effect's sample buffer for processing the reverse (playback) audio
863
+ * stream. The provided samples must be interleaved float values in the range [-1, 1]. The delay
864
+ * parameter is used to align the reverse stream processing with the forward (capture) stream.
865
+ * The delay can be expressed as:
866
+ *
867
+ * `delay = (t_render - t_analyze) + (t_process - t_capture)`
812
868
  *
813
- * Note: One resampler should be used exclusively per audio stream.
869
+ * where:
870
+ * - `t_render` is the time the first sample of the same frame is rendered by the audio hardware.
871
+ * - `t_analyze` is the time the frame is processed in the reverse stream.
872
+ * - `t_capture` is the time the first sample of a frame is captured by the audio hardware.
873
+ * - `t_process` is the time the frame is processed in the forward stream.
814
874
  */
815
- OdinResamplerHandle odin_resampler_create(uint32_t from_rate,
816
- uint32_t to_rate,
817
- uint16_t channel_count);
875
+ enum OdinError odin_pipeline_update_apm_playback(const struct OdinPipeline *pipeline,
876
+ uint32_t effect_id,
877
+ const float *samples,
878
+ uint32_t samples_count,
879
+ uint64_t delay_ms);
818
880
 
819
881
  /**
820
- * Resamples a single chunk of audio. If the ODIN resampler instance was created with multiple
821
- * channels, the data is assumed to be interleaved. The `output_capacity` argument also serves as
822
- * an out parameter when the provided capacity wasn't enough to fulfill the resample request, in
823
- * which case this function will write the minimum required buffer size into the given variable.
824
- * On success, the written size for the processed sample is returned in both, the return value
825
- * and the `output_capacity` out parameter.
882
+ * Inserts a user-defined custom effect at the specified index in the audio pipeline. The effect
883
+ * is implemented via a callback function and associated user data. A unique effect identifier
884
+ * is returned.
826
885
  */
827
- OdinReturnCode odin_resampler_process(OdinResamplerHandle resampler,
828
- const float *input,
829
- size_t input_len,
830
- float *output,
831
- size_t *output_capacity);
886
+ enum OdinError odin_pipeline_insert_custom_effect(const struct OdinPipeline *pipeline,
887
+ uint32_t index,
888
+ OdinCustomEffectCallback callback,
889
+ const void *user_data,
890
+ uint32_t *out_effect_id);
832
891
 
833
892
  /**
834
- * Destroys the given ODIN resampler instance. After this call, all attempts to use this handle
835
- * will fail.
893
+ * Returns the unique effect identifier from an audio pipeline corresponding to the effect located
894
+ * at the specified index.
836
895
  */
837
- OdinReturnCode odin_resampler_destroy(OdinResamplerHandle resampler);
896
+ enum OdinError odin_pipeline_get_effect_id(const struct OdinPipeline *pipeline,
897
+ uint32_t index,
898
+ uint32_t *out_effect_id);
838
899
 
839
900
  /**
840
- * Creates a new access key crucial for signing tokens, facilitating access to an ODIN server. An
841
- * access key is a 44-character long Base64 String, embodying a version identifier, random bytes,
842
- * and a checksum.
901
+ * Searches the specified audio pipeline for the effect with the specified `effect_id` and returns
902
+ * its current index.
903
+ */
904
+ enum OdinError odin_pipeline_get_effect_index(const struct OdinPipeline *pipeline,
905
+ uint32_t effect_id,
906
+ uint32_t *out_index);
907
+
908
+ /**
909
+ * Obtains the effect type (VAD, APM, or Custom) for the effect identified by `effect_id`.
910
+ */
911
+ enum OdinError odin_pipeline_get_effect_type(const struct OdinPipeline *pipeline,
912
+ uint32_t effect_id,
913
+ enum OdinEffectType *out_effect_type);
914
+
915
+ /**
916
+ * Retrieves the total number of effects currently in the audio pipeline.
843
917
  */
844
- OdinReturnCode odin_access_key_generate(char *buf, size_t buf_len);
918
+ uint32_t odin_pipeline_get_effect_count(const struct OdinPipeline *pipeline);
845
919
 
846
920
  /**
847
- * Extracts the key ID from a specified access key. The key ID is embedded in room tokens, enabling
848
- * the identification of the corresponding public key required for verification.
921
+ * Reorders the audio pipeline by moving the effect with the specified `effect_id` to a new index.
849
922
  */
850
- OdinReturnCode odin_access_key_id(const char *access_key, char *out_key_id, size_t out_key_id_len);
923
+ enum OdinError odin_pipeline_move_effect(const struct OdinPipeline *pipeline,
924
+ uint32_t effect_id,
925
+ size_t new_index);
851
926
 
852
927
  /**
853
- * Extracts the public key from a specified access key. The public key, derived from the Ed25519
854
- * curve, must be shared with _4Players_ to enable verification of a generated room token.
928
+ * Deletes the effect identified by `effect_id` from the specified audio pipeline.
855
929
  */
856
- OdinReturnCode odin_access_key_public_key(const char *access_key,
857
- char *out_public_key,
858
- size_t out_public_key_len);
930
+ enum OdinError odin_pipeline_remove_effect(const struct OdinPipeline *pipeline, uint32_t effect_id);
859
931
 
860
932
  /**
861
- * Extracts the private key from a specified access key. The private key, rooted in the Ed25519
862
- * curve, is utilized to sign a generated room token for accessing the ODIN network.
933
+ * Creates a new token generator using the specified ODIN access key. If no access key is provided,
934
+ * a new one will be generated.
863
935
  */
864
- OdinReturnCode odin_access_key_secret_key(const char *access_key,
865
- char *out_secret_key,
866
- size_t out_secret_key_len);
936
+ enum OdinError odin_token_generator_create(const char *access_key,
937
+ struct OdinTokenGenerator **out_token_generator);
867
938
 
868
939
  /**
869
- * Creates a new token generator instance.
940
+ * Frees the specified token generator and releases the resources associated with it.
941
+ */
942
+ void odin_token_generator_free(struct OdinTokenGenerator *token_generator);
943
+
944
+ /**
945
+ * Retrieves the ODIN access key used by the specified token generator. An ODIN access key is a 44
946
+ * character long Base64-String that consists of an internal version number, a set of random bytes
947
+ * and a checksum.
870
948
  */
871
- struct OdinTokenGenerator *odin_token_generator_create(const char *access_key);
949
+ enum OdinError odin_token_generator_get_access_key(struct OdinTokenGenerator *token_generator,
950
+ char *out_access_key,
951
+ uint32_t *out_access_key_length);
872
952
 
873
953
  /**
874
- * Destroys an existing token generator instance.
954
+ * Extracts the public key from the access key used by the specified token generator. The public
955
+ * key, derived from the Ed25519 curve, must be shared with _4Players_ to enable verification of
956
+ * a generated room token.
875
957
  */
876
- void odin_token_generator_destroy(struct OdinTokenGenerator *generator);
958
+ enum OdinError odin_token_generator_get_public_key(struct OdinTokenGenerator *token_generator,
959
+ char *out_public_key,
960
+ uint32_t *out_public_key_length);
877
961
 
878
962
  /**
879
- * Generates a signed JWT, which can be used by an ODIN client to join a room.
963
+ * Extracts the key ID from the access key used by the specified token generator. The key ID is
964
+ * embedded in room tokens, enabling the identification of the corresponding public key required
965
+ * for verification.
880
966
  */
881
- OdinReturnCode odin_token_generator_create_token(struct OdinTokenGenerator *generator,
882
- const char *room_id,
883
- const char *user_id,
884
- char *out_token,
885
- size_t out_token_len);
967
+ enum OdinError odin_token_generator_get_key_id(struct OdinTokenGenerator *token_generator,
968
+ char *out_key_id,
969
+ uint32_t *out_key_id_length);
886
970
 
887
971
  /**
888
- * Generates a signed JWT such as `odin_token_generator_create_token` and allows passing a custom
889
- * set of `OdinTokenOptions` for advanced use-cases.
972
+ * Signs the provided body using the key ID and access key stored in the token generator to sign
973
+ * the provided body, creating a JSON Web Token (JWT). The EdDSA (Ed25519) algorithm is used for
974
+ * the digital signature.
890
975
  */
891
- OdinReturnCode odin_token_generator_create_token_ex(struct OdinTokenGenerator *generator,
892
- const char *room_id,
893
- const char *user_id,
894
- const struct OdinTokenOptions *options,
895
- char *out_token,
896
- size_t out_token_len);
976
+ enum OdinError odin_token_generator_sign(struct OdinTokenGenerator *token_generator,
977
+ const char *body,
978
+ char *out_token,
979
+ uint32_t *out_token_length);
980
+
981
+ /**
982
+ * Helper function to deserialize MessagePack encoded data and convert it into a JSON string.
983
+ */
984
+ enum OdinError odin_rpc_bytes_to_json(const uint8_t *bytes,
985
+ uint32_t bytes_length,
986
+ char *out_json,
987
+ uint32_t *out_json_length);
988
+
989
+ /**
990
+ * Helper function to convert a JSON string into a MessagePack encoded byte array.
991
+ */
992
+ enum OdinError odin_rpc_json_to_bytes(const char *json,
993
+ uint8_t *out_bytes,
994
+ uint32_t *out_bytes_length);
897
995
 
898
996
  #ifdef __cplusplus
899
- } // extern "C"
900
- #endif // __cplusplus
997
+ } // extern "C"
998
+ #endif // __cplusplus