@4players/odin-nodejs 0.7.3 → 0.8.0
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.
- package/README.md +9 -1
- package/binding.gyp +60 -58
- package/cppsrc/odinclient.cpp +10 -1
- package/cppsrc/odinmedia.cpp +1 -1
- package/cppsrc/odinroom.cpp +3 -26
- package/cppsrc/odinroom.h +0 -1
- package/index.d.ts +6 -0
- package/libs/bin/linux/arm64/libodin_static.a +0 -0
- package/libs/bin/linux/ia32/libodin_static.a +0 -0
- package/libs/bin/linux/x64/libodin_static.a +0 -0
- package/libs/bin/macos/arm64/libodin_static.a +0 -0
- package/libs/bin/macos/x64/libodin_static.a +0 -0
- package/libs/bin/windows/arm64/odin_static.lib +0 -0
- package/libs/bin/windows/ia32/odin_static.lib +0 -0
- package/libs/bin/windows/x64/odin_static.lib +0 -0
- package/libs/include/odin.h +106 -102
- package/odin.client.d.ts +5 -5
- package/odin.media.d.ts +8 -6
- package/odin.room.d.ts +16 -18
- package/package.json +4 -3
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/darwin-x64/node.napi.node +0 -0
- package/tests/sending-audio/index.js +30 -13
- package/prebuilds/linux-x64/node.napi.node +0 -0
package/README.md
CHANGED
|
@@ -3,7 +3,15 @@
|
|
|
3
3
|
Native Node JS bindings for the ODIN SDK. It is based on the [ODIN Native SDK](https://github.com/4Players/odin-sdk) and
|
|
4
4
|
wraps the C++ code into a Node JS module.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Check out documentation and guides at [developers.4players.io](https://www.4players.io/odin/sdk/nodejs).
|
|
7
|
+
|
|
8
|
+
## Beta!
|
|
9
|
+
|
|
10
|
+
**This SDK is currently in beta. This means that the API is not final and might change in the future. It's also not ready
|
|
11
|
+
for production use as there might be bugs, memory leaks or other issues.** But it's good enough for testing AI
|
|
12
|
+
integration, recording or other interesting use cases.
|
|
13
|
+
|
|
14
|
+
If you have any questions or feedback, please reach out to us at our [Discord Server](https://4np.de/discord).
|
|
7
15
|
|
|
8
16
|
## ODIN Node JS compared to Web SDK
|
|
9
17
|
|
package/binding.gyp
CHANGED
|
@@ -1,61 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"<(module_root_dir)/libs/include"
|
|
26
|
-
],
|
|
27
|
-
}],
|
|
28
|
-
["OS=='win'", {
|
|
29
|
-
"defines": [
|
|
30
|
-
"_HAS_EXCEPTIONS=1"
|
|
31
|
-
],
|
|
32
|
-
"msvs_settings": {
|
|
33
|
-
"VCCLCompilerTool": {
|
|
34
|
-
"ExceptionHandling": 1
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
'runtime_library': [
|
|
38
|
-
"<(module_root_dir)/libs/bin/windows/<(target_arch)/odin_static.lib"
|
|
39
|
-
],
|
|
40
|
-
'include_dirs': [
|
|
41
|
-
"<!@(node -p \"require('node-addon-api').include\")",
|
|
42
|
-
"<(module_root_dir)/libs/include"
|
|
43
|
-
],
|
|
44
|
-
}],
|
|
45
|
-
["OS=='mac'", {
|
|
46
|
-
'xcode_settings': {
|
|
47
|
-
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
|
48
|
-
'CLANG_CXX_LIBRARY': 'libc++',
|
|
49
|
-
'MACOSX_DEPLOYMENT_TARGET': '10.12',
|
|
50
|
-
},
|
|
51
|
-
'libraries': [
|
|
52
|
-
"<(module_root_dir)/libs/bin/macos/<(target_arch)/libodin_static.a"
|
|
53
|
-
],
|
|
54
|
-
'include_dirs': [
|
|
55
|
-
"<!@(node -p \"require('node-addon-api').include\")",
|
|
56
|
-
"<(module_root_dir)/libs/include"
|
|
57
|
-
],
|
|
58
|
-
}],
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "odin",
|
|
5
|
+
"sources": [
|
|
6
|
+
"cppsrc/binding.cpp",
|
|
7
|
+
"cppsrc/odinbindings.cpp",
|
|
8
|
+
"cppsrc/odinclient.cpp",
|
|
9
|
+
"cppsrc/odinroom.cpp",
|
|
10
|
+
"cppsrc/odinmedia.cpp",
|
|
11
|
+
"cppsrc/utilities.cpp"
|
|
12
|
+
],
|
|
13
|
+
"include_dirs": [
|
|
14
|
+
"<!@(node -p \"require('node-addon-api').include\")",
|
|
15
|
+
"<(module_root_dir)/libs/include"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": [
|
|
18
|
+
"<!(node -p \"require('node-addon-api').gyp\")"
|
|
19
|
+
],
|
|
20
|
+
"conditions": [
|
|
21
|
+
["OS=='linux'", {
|
|
22
|
+
"libraries": [
|
|
23
|
+
"-L<(module_root_dir)/libs/bin/linux/<(target_arch)",
|
|
24
|
+
"-lodin_static"
|
|
59
25
|
]
|
|
60
|
-
|
|
26
|
+
}],
|
|
27
|
+
["OS=='mac'", {
|
|
28
|
+
"libraries": [
|
|
29
|
+
"-L<(module_root_dir)/libs/bin/macos/<(target_arch)",
|
|
30
|
+
"-lodin_static",
|
|
31
|
+
]
|
|
32
|
+
}],
|
|
33
|
+
["OS=='win'", {
|
|
34
|
+
"msvs_settings": {
|
|
35
|
+
"VCCLCompilerTool": {
|
|
36
|
+
"AdditionalOptions": [ "/MD" ],
|
|
37
|
+
},
|
|
38
|
+
"VCLinkerTool": {
|
|
39
|
+
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
"libraries": [
|
|
43
|
+
"<(module_root_dir)/libs/bin/windows/<(target_arch)/odin_static.lib",
|
|
44
|
+
"-lws2_32",
|
|
45
|
+
"-lbcrypt",
|
|
46
|
+
"-lucrt",
|
|
47
|
+
"-lvcruntime",
|
|
48
|
+
"-lwinmm",
|
|
49
|
+
"-lntdll"
|
|
50
|
+
]
|
|
51
|
+
}]
|
|
52
|
+
],
|
|
53
|
+
"defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ],
|
|
54
|
+
"cflags!": [ "-fno-exceptions" ],
|
|
55
|
+
"cflags_cc!": [ "-fno-exceptions" ],
|
|
56
|
+
"xcode_settings": {
|
|
57
|
+
"GCC_ENABLE_CPP_EXCEPTIONS": "NO",
|
|
58
|
+
"CLANG_CXX_LIBRARY": "libc++",
|
|
59
|
+
"MACOSX_DEPLOYMENT_TARGET": "10.12",
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
]
|
|
61
63
|
}
|
package/cppsrc/odinclient.cpp
CHANGED
|
@@ -72,7 +72,12 @@ OdinClient::OdinClient(const Napi::CallbackInfo& info) : Napi::ObjectWrap<OdinCl
|
|
|
72
72
|
printf("Odin NodeJS Addon: Initializing Odin runtime (%s) with sample rate %f and %d channels\n", ODIN_VERSION, _sampleRate, _numChannels);
|
|
73
73
|
#endif
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
// Create a OdinAudioStreamConfig struct to configure the audio stream
|
|
76
|
+
OdinAudioStreamConfig config;
|
|
77
|
+
config.sample_rate = _sampleRate;
|
|
78
|
+
config.channel_count = _numChannels;
|
|
79
|
+
|
|
80
|
+
odin_startup_ex(ODIN_VERSION, config);
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
/**
|
|
@@ -141,6 +146,8 @@ Napi::Value OdinClient::CreateRoom(const Napi::CallbackInfo &info) {
|
|
|
141
146
|
if (!generator)
|
|
142
147
|
{
|
|
143
148
|
Napi::TypeError::New(env, "Failed to initialize token generator, invalid access key").ThrowAsJavaScriptException();
|
|
149
|
+
odin_token_generator_destroy(generator);
|
|
150
|
+
return env.Undefined();
|
|
144
151
|
}
|
|
145
152
|
|
|
146
153
|
/*
|
|
@@ -151,6 +158,8 @@ Napi::Value OdinClient::CreateRoom(const Napi::CallbackInfo &info) {
|
|
|
151
158
|
if (odin_is_error(error))
|
|
152
159
|
{
|
|
153
160
|
Napi::TypeError::New(env, "Creating access token failed").ThrowAsJavaScriptException();
|
|
161
|
+
odin_token_generator_destroy(generator);
|
|
162
|
+
return env.Undefined();
|
|
154
163
|
}
|
|
155
164
|
|
|
156
165
|
/*
|
package/cppsrc/odinmedia.cpp
CHANGED
|
@@ -232,7 +232,7 @@ void OdinMedia::SendData(const Napi::CallbackInfo &info) {
|
|
|
232
232
|
Napi::Float32Array array = info[0].As<Napi::Float32Array>();
|
|
233
233
|
|
|
234
234
|
#ifdef DEBUG
|
|
235
|
-
printf("
|
|
235
|
+
printf("Sent %d bytes of audio data\n", (int)array.ElementLength());
|
|
236
236
|
#endif
|
|
237
237
|
|
|
238
238
|
OdinReturnCode result = odin_audio_push_data(_mediaStreamHandle, array.Data(), array.ElementLength());
|
package/cppsrc/odinroom.cpp
CHANGED
|
@@ -331,7 +331,6 @@ Napi::Object OdinRoom::Init(Napi::Env env, Napi::Object exports) {
|
|
|
331
331
|
Napi::Function func = DefineClass(env, "OdinRoom", {
|
|
332
332
|
InstanceMethod<&OdinRoom::Join>("join", static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
|
|
333
333
|
InstanceMethod<&OdinRoom::UpdatePeerUserData>("updateOwnUserData", static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
|
|
334
|
-
InstanceMethod<&OdinRoom::UpdateRoomUserData>("updateRoomUserData", static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
|
|
335
334
|
InstanceMethod<&OdinRoom::SendMessage>("sendMessage", static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
|
|
336
335
|
InstanceMethod<&OdinRoom::SetEventListener>("setEventListener", static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
|
|
337
336
|
InstanceMethod<&OdinRoom::AddEventListener>("addEventListener", static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
|
|
@@ -381,7 +380,7 @@ void OdinRoom::Join(const Napi::CallbackInfo &info) {
|
|
|
381
380
|
|
|
382
381
|
if (info.Length() > 1) {
|
|
383
382
|
Napi::Uint8Array data = info[1].As<Napi::Uint8Array>();
|
|
384
|
-
OdinReturnCode error =
|
|
383
|
+
OdinReturnCode error = odin_room_update_peer_user_data(_roomHandle, data.Data(), data.ByteLength());
|
|
385
384
|
if (odin_is_error(error))
|
|
386
385
|
{
|
|
387
386
|
Napi::TypeError::New(env, "Setting initial room peer data failed").ThrowAsJavaScriptException();
|
|
@@ -475,7 +474,7 @@ void OdinRoom::UpdatePeerUserData(const Napi::CallbackInfo &info) {
|
|
|
475
474
|
|
|
476
475
|
Napi::Uint8Array data = info[0].As<Napi::Uint8Array>();
|
|
477
476
|
|
|
478
|
-
OdinReturnCode error =
|
|
477
|
+
OdinReturnCode error = odin_room_update_peer_user_data(_roomHandle, data.Data(), data.ByteLength());
|
|
479
478
|
|
|
480
479
|
if (odin_is_error(error))
|
|
481
480
|
{
|
|
@@ -483,28 +482,6 @@ void OdinRoom::UpdatePeerUserData(const Napi::CallbackInfo &info) {
|
|
|
483
482
|
}
|
|
484
483
|
}
|
|
485
484
|
|
|
486
|
-
/**
|
|
487
|
-
* Updates the room user data. Requires an array of bytes as a parameter.
|
|
488
|
-
* @param info
|
|
489
|
-
* @return
|
|
490
|
-
*/
|
|
491
|
-
void OdinRoom::UpdateRoomUserData(const Napi::CallbackInfo &info) {
|
|
492
|
-
Napi::Env env = info.Env();
|
|
493
|
-
|
|
494
|
-
if (info.Length() != 1 || !info[0].IsTypedArray()) {
|
|
495
|
-
Napi::TypeError::New(env, "Data as byte array expected").ThrowAsJavaScriptException();
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
Napi::Uint8Array data = info[0].As<Napi::Uint8Array>();
|
|
499
|
-
|
|
500
|
-
OdinReturnCode error = odin_room_update_user_data(_roomHandle, OdinUserDataTarget_Room, data.Data(), data.ByteLength());
|
|
501
|
-
|
|
502
|
-
if (odin_is_error(error))
|
|
503
|
-
{
|
|
504
|
-
OdinUtilities::ThrowNapiException(env, error, "Failed to update room user data");
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
485
|
/**
|
|
509
486
|
* Sends a message to the room. Requires an array of bytes as a parameter and optinally a list of peer ids to send to.
|
|
510
487
|
* Please note: If the list is NULL the message will be sent to all peers in the room. If the list is not NULL the message
|
|
@@ -544,7 +521,7 @@ void OdinRoom::SendMessage(const Napi::CallbackInfo &info) {
|
|
|
544
521
|
|
|
545
522
|
if (odin_is_error(error))
|
|
546
523
|
{
|
|
547
|
-
OdinUtilities::ThrowNapiException(env, error, "Failed to
|
|
524
|
+
OdinUtilities::ThrowNapiException(env, error, "Failed to send message");
|
|
548
525
|
}
|
|
549
526
|
}
|
|
550
527
|
|
package/cppsrc/odinroom.h
CHANGED
|
@@ -47,7 +47,6 @@ private:
|
|
|
47
47
|
void Close(const Napi::CallbackInfo& info);
|
|
48
48
|
void Join(const Napi::CallbackInfo& info);
|
|
49
49
|
void UpdatePeerUserData(const Napi::CallbackInfo &info);
|
|
50
|
-
void UpdateRoomUserData(const Napi::CallbackInfo &info);
|
|
51
50
|
void SendMessage(const Napi::CallbackInfo &info);
|
|
52
51
|
void SetEventListener(const Napi::CallbackInfo &info);
|
|
53
52
|
void AddEventListener(const Napi::CallbackInfo &info);
|
package/index.d.ts
CHANGED
|
@@ -2,4 +2,10 @@ export * from "./odin.client";
|
|
|
2
2
|
export * from "./odin.room";
|
|
3
3
|
export * from "./odin.media";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Generates an access token for a room and user ID. You can use this to join a room with a custom access token.
|
|
7
|
+
* @param accessKey - The access key to use for this client. You can get one from https://developers.4players.io
|
|
8
|
+
* @param roomId - The ID of the room to create.
|
|
9
|
+
* @param userId - The ID of the user
|
|
10
|
+
*/
|
|
5
11
|
export declare function generateAccessToken(accessKey: string, roomId: string, userId: string): string;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/libs/include/odin.h
CHANGED
|
@@ -10,23 +10,7 @@
|
|
|
10
10
|
#include <stdint.h>
|
|
11
11
|
#include <stdlib.h>
|
|
12
12
|
|
|
13
|
-
#define ODIN_VERSION "1.4
|
|
14
|
-
|
|
15
|
-
#define Frame_SAMPLE_RATE 48000
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Supported channel layouts in audio functions.
|
|
19
|
-
*/
|
|
20
|
-
typedef enum OdinChannelLayout {
|
|
21
|
-
/**
|
|
22
|
-
* Samples are sequential
|
|
23
|
-
*/
|
|
24
|
-
OdinChannelLayout_Mono,
|
|
25
|
-
/**
|
|
26
|
-
* Channels are interleaved
|
|
27
|
-
*/
|
|
28
|
-
OdinChannelLayout_Stereo,
|
|
29
|
-
} OdinChannelLayout;
|
|
13
|
+
#define ODIN_VERSION "1.6.4"
|
|
30
14
|
|
|
31
15
|
/**
|
|
32
16
|
* Known types of a media stream.
|
|
@@ -134,25 +118,11 @@ typedef enum OdinTokenAudience {
|
|
|
134
118
|
} OdinTokenAudience;
|
|
135
119
|
|
|
136
120
|
/**
|
|
137
|
-
*
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
*/
|
|
143
|
-
OdinUserDataTarget_Peer,
|
|
144
|
-
/**
|
|
145
|
-
* Global user data for the room
|
|
146
|
-
*/
|
|
147
|
-
OdinUserDataTarget_Room,
|
|
148
|
-
} OdinUserDataTarget;
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* A pointer to a local ODIN token generator used to generate signed room tokens based based on an
|
|
152
|
-
* access key. Please note, that access keys are your the unique authentication keys to be used to
|
|
153
|
-
* generate room tokens for accessing the ODIN server network. For your own security, we strongly
|
|
154
|
-
* recommend that you _NEVER_ put an access key in your client code and generate room tokens on a
|
|
155
|
-
* server.
|
|
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.
|
|
156
126
|
*/
|
|
157
127
|
typedef struct OdinTokenGenerator OdinTokenGenerator;
|
|
158
128
|
|
|
@@ -164,6 +134,20 @@ typedef struct OdinTokenGenerator OdinTokenGenerator;
|
|
|
164
134
|
*/
|
|
165
135
|
typedef uint32_t OdinReturnCode;
|
|
166
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Audio stream configuration.
|
|
139
|
+
*/
|
|
140
|
+
typedef struct OdinAudioStreamConfig {
|
|
141
|
+
/**
|
|
142
|
+
* The number of samples per second in hertz (between 8000 and 192000)
|
|
143
|
+
*/
|
|
144
|
+
uint32_t sample_rate;
|
|
145
|
+
/**
|
|
146
|
+
* The number of channels for the new audio stream (between 1 and 2)
|
|
147
|
+
*/
|
|
148
|
+
uint8_t channel_count;
|
|
149
|
+
} OdinAudioStreamConfig;
|
|
150
|
+
|
|
167
151
|
/**
|
|
168
152
|
* Internal handle identifier for an ODIN room to interact with.
|
|
169
153
|
*/
|
|
@@ -491,20 +475,6 @@ typedef struct OdinApmConfig {
|
|
|
491
475
|
bool gain_controller;
|
|
492
476
|
} OdinApmConfig;
|
|
493
477
|
|
|
494
|
-
/**
|
|
495
|
-
* Audio stream configuration.
|
|
496
|
-
*/
|
|
497
|
-
typedef struct OdinAudioStreamConfig {
|
|
498
|
-
/**
|
|
499
|
-
* The number of samples per second in hertz (between 8000 and 192000)
|
|
500
|
-
*/
|
|
501
|
-
uint32_t sample_rate;
|
|
502
|
-
/**
|
|
503
|
-
* The number of channels for the new audio stream (between 1 and 2)
|
|
504
|
-
*/
|
|
505
|
-
uint8_t channel_count;
|
|
506
|
-
} OdinAudioStreamConfig;
|
|
507
|
-
|
|
508
478
|
/**
|
|
509
479
|
* Audio stream statistics.
|
|
510
480
|
*/
|
|
@@ -583,30 +553,30 @@ size_t odin_error_format(OdinReturnCode error, char *buf, size_t buf_len);
|
|
|
583
553
|
bool odin_is_error(OdinReturnCode code);
|
|
584
554
|
|
|
585
555
|
/**
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
* and shutdown
|
|
589
|
-
*
|
|
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.
|
|
590
561
|
*
|
|
591
|
-
* Note:
|
|
562
|
+
* Note: Utilize `ODIN_VERSION` to supply the `version` argument.
|
|
592
563
|
*/
|
|
593
564
|
bool odin_startup(const char *version);
|
|
594
565
|
|
|
595
566
|
/**
|
|
596
|
-
*
|
|
597
|
-
* for audio output. This is ref-counted
|
|
598
|
-
* application.
|
|
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.
|
|
599
570
|
*
|
|
600
|
-
* Note:
|
|
571
|
+
* Note: Ensure consistent settings are used on successive invocations of this function.
|
|
601
572
|
*/
|
|
602
|
-
bool odin_startup_ex(const char *version,
|
|
603
|
-
uint32_t output_sample_rate,
|
|
604
|
-
enum OdinChannelLayout output_channel_layout);
|
|
573
|
+
bool odin_startup_ex(const char *version, struct OdinAudioStreamConfig output_config);
|
|
605
574
|
|
|
606
575
|
/**
|
|
607
|
-
*
|
|
608
|
-
* the application.
|
|
609
|
-
*
|
|
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.
|
|
610
580
|
*/
|
|
611
581
|
void odin_shutdown(void);
|
|
612
582
|
|
|
@@ -639,13 +609,13 @@ OdinReturnCode odin_room_set_event_callback(OdinRoomHandle room,
|
|
|
639
609
|
void *extra_data);
|
|
640
610
|
|
|
641
611
|
/**
|
|
642
|
-
* Sets the scaling
|
|
643
|
-
*
|
|
644
|
-
* a unit circle
|
|
645
|
-
*
|
|
646
|
-
*
|
|
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.
|
|
647
617
|
*
|
|
648
|
-
* Note:
|
|
618
|
+
* Note: It's crucial to maintain consistent scaling across all client applications.
|
|
649
619
|
*/
|
|
650
620
|
OdinReturnCode odin_room_set_position_scale(OdinRoomHandle room, float scale);
|
|
651
621
|
|
|
@@ -679,28 +649,26 @@ OdinReturnCode odin_room_peer_id(OdinRoomHandle room, uint64_t *out_peer_id);
|
|
|
679
649
|
OdinReturnCode odin_room_connection_stats(OdinRoomHandle room, struct OdinConnectionStats *stats);
|
|
680
650
|
|
|
681
651
|
/**
|
|
682
|
-
* Updates the custom user data for
|
|
683
|
-
*
|
|
684
|
-
* individual peer and even globally for the room if needed.
|
|
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.
|
|
685
654
|
*
|
|
686
655
|
* Note: Use this before calling `odin_room_join` to set initial peer user data upon connect.
|
|
687
656
|
*/
|
|
688
|
-
OdinReturnCode
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
size_t user_data_length);
|
|
657
|
+
OdinReturnCode odin_room_update_peer_user_data(OdinRoomHandle room,
|
|
658
|
+
const uint8_t *user_data,
|
|
659
|
+
size_t user_data_length);
|
|
692
660
|
|
|
693
661
|
/**
|
|
694
|
-
* Updates the
|
|
695
|
-
*
|
|
696
|
-
* based on unit circles with a radius of `1.0`. This is
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
*
|
|
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`.
|
|
700
668
|
*
|
|
701
669
|
* Note: Use this before calling `odin_room_join` to set the initial peer position upon connect.
|
|
702
670
|
*/
|
|
703
|
-
OdinReturnCode odin_room_update_position(OdinRoomHandle room, float x, float y);
|
|
671
|
+
OdinReturnCode odin_room_update_position(OdinRoomHandle room, float x, float y, float z);
|
|
704
672
|
|
|
705
673
|
/**
|
|
706
674
|
* Sends arbitrary data to a list of target peers over the ODIN server. If `NULL` is specified, the
|
|
@@ -725,12 +693,12 @@ OdinReturnCode odin_room_add_media(OdinRoomHandle room, OdinMediaStreamHandle me
|
|
|
725
693
|
OdinReturnCode odin_room_configure_apm(OdinRoomHandle room, struct OdinApmConfig config);
|
|
726
694
|
|
|
727
695
|
/**
|
|
728
|
-
* Creates a new audio stream, which can be added to a room and send data over it.
|
|
696
|
+
* Creates a new audio input stream, which can be added to a room and send data over it.
|
|
729
697
|
*/
|
|
730
698
|
OdinMediaStreamHandle odin_audio_stream_create(struct OdinAudioStreamConfig config);
|
|
731
699
|
|
|
732
700
|
/**
|
|
733
|
-
* Creates a new video stream, which can be added to a room and send data over it.
|
|
701
|
+
* Creates a new video input stream, which can be added to a room and send data over it.
|
|
734
702
|
*
|
|
735
703
|
* Note: Video streams are not supported yet.
|
|
736
704
|
*/
|
|
@@ -760,21 +728,45 @@ OdinReturnCode odin_media_stream_peer_id(OdinMediaStreamHandle stream, uint64_t
|
|
|
760
728
|
*/
|
|
761
729
|
enum OdinMediaStreamType odin_media_stream_type(OdinMediaStreamHandle stream);
|
|
762
730
|
|
|
731
|
+
/**
|
|
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.
|
|
735
|
+
*/
|
|
736
|
+
OdinReturnCode odin_media_stream_pause(OdinMediaStreamHandle stream);
|
|
737
|
+
|
|
738
|
+
/**
|
|
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.
|
|
742
|
+
*/
|
|
743
|
+
OdinReturnCode odin_media_stream_resume(OdinMediaStreamHandle stream);
|
|
744
|
+
|
|
763
745
|
/**
|
|
764
746
|
* Sends data to the audio stream. The data has to be interleaved [-1, 1] float data.
|
|
765
747
|
*/
|
|
766
748
|
OdinReturnCode odin_audio_push_data(OdinMediaStreamHandle stream, const float *buf, size_t buf_len);
|
|
767
749
|
|
|
768
750
|
/**
|
|
769
|
-
* Reads audio data from the specified `OdinMediaStreamHandle`. This will return audio data in
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
* Note: `out_channel_layout` is reserved for future use.
|
|
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.
|
|
773
753
|
*/
|
|
774
754
|
OdinReturnCode odin_audio_read_data(OdinMediaStreamHandle stream,
|
|
775
755
|
float *out_buffer,
|
|
776
756
|
size_t out_buffer_len);
|
|
777
757
|
|
|
758
|
+
/**
|
|
759
|
+
* Returns the number of samples available in the audio buffer of an output `OdinMediaStreamHandle`.
|
|
760
|
+
*/
|
|
761
|
+
OdinReturnCode odin_audio_data_len(OdinMediaStreamHandle stream);
|
|
762
|
+
|
|
763
|
+
/**
|
|
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.
|
|
767
|
+
*/
|
|
768
|
+
OdinReturnCode odin_audio_reset(OdinMediaStreamHandle stream);
|
|
769
|
+
|
|
778
770
|
/**
|
|
779
771
|
* Retrieves statistics for the specified `OdinMediaStreamHandle`.
|
|
780
772
|
*
|
|
@@ -784,9 +776,9 @@ OdinReturnCode odin_audio_stats(OdinMediaStreamHandle stream, struct OdinAudioSt
|
|
|
784
776
|
|
|
785
777
|
/**
|
|
786
778
|
* Reads up to `out_buffer_len` samples from the given streams and mixes them into the `out_buffer`.
|
|
787
|
-
* All audio streams will be read based on
|
|
788
|
-
* accordingly. After the call the `out_buffer_len` will contain
|
|
789
|
-
* actually been read and mixed into `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`.
|
|
790
782
|
*
|
|
791
783
|
* If enabled this will also apply any audio processing to the output stream and feed back required
|
|
792
784
|
* data to the internal audio processing pipeline which requires a final mix.
|
|
@@ -803,6 +795,17 @@ OdinReturnCode odin_audio_mix_streams(OdinRoomHandle room,
|
|
|
803
795
|
*/
|
|
804
796
|
OdinReturnCode odin_audio_process_reverse(OdinRoomHandle room, float *buffer, size_t buffer_len);
|
|
805
797
|
|
|
798
|
+
/**
|
|
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.
|
|
806
|
+
*/
|
|
807
|
+
OdinReturnCode odin_audio_set_stream_delay(OdinRoomHandle room, uint64_t delay_ms);
|
|
808
|
+
|
|
806
809
|
/**
|
|
807
810
|
* Creates a new ODIN resampler instance. This is intended for situations where your audio pipeline
|
|
808
811
|
* doesn't support 48 kHz.
|
|
@@ -834,28 +837,29 @@ OdinReturnCode odin_resampler_process(OdinResamplerHandle resampler,
|
|
|
834
837
|
OdinReturnCode odin_resampler_destroy(OdinResamplerHandle resampler);
|
|
835
838
|
|
|
836
839
|
/**
|
|
837
|
-
* Creates a new access key
|
|
838
|
-
* long Base64
|
|
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.
|
|
839
843
|
*/
|
|
840
844
|
OdinReturnCode odin_access_key_generate(char *buf, size_t buf_len);
|
|
841
845
|
|
|
842
846
|
/**
|
|
843
|
-
*
|
|
844
|
-
*
|
|
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.
|
|
845
849
|
*/
|
|
846
850
|
OdinReturnCode odin_access_key_id(const char *access_key, char *out_key_id, size_t out_key_id_len);
|
|
847
851
|
|
|
848
852
|
/**
|
|
849
|
-
*
|
|
850
|
-
* curve
|
|
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.
|
|
851
855
|
*/
|
|
852
856
|
OdinReturnCode odin_access_key_public_key(const char *access_key,
|
|
853
857
|
char *out_public_key,
|
|
854
858
|
size_t out_public_key_len);
|
|
855
859
|
|
|
856
860
|
/**
|
|
857
|
-
*
|
|
858
|
-
* curve
|
|
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.
|
|
859
863
|
*/
|
|
860
864
|
OdinReturnCode odin_access_key_secret_key(const char *access_key,
|
|
861
865
|
char *out_secret_key,
|
package/odin.client.d.ts
CHANGED
|
@@ -7,16 +7,16 @@ import {OdinRoom} from "./odin.room";
|
|
|
7
7
|
export declare class OdinClient {
|
|
8
8
|
/**
|
|
9
9
|
* Creates a new instance of a client with an access key.
|
|
10
|
-
* @param accessKey
|
|
11
|
-
* @param sampleRate
|
|
12
|
-
* @param channelCount
|
|
10
|
+
* @param accessKey - The access key to use for this client. You can get one from https://developers.4players.io
|
|
11
|
+
* @param sampleRate - The sample rate of the audio stream (between 8000 and 48000)
|
|
12
|
+
* @param channelCount - The number of channels of the audio stream (1 or 2)
|
|
13
13
|
*/
|
|
14
14
|
constructor(accessKey: string, sampleRate?: number, channelCount?: number);
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Creates a new local room instance with the given ID and user ID. Use join to connect to that room.
|
|
18
|
-
* @param roomId
|
|
19
|
-
* @param userId
|
|
18
|
+
* @param roomId - The ID of the room to create.
|
|
19
|
+
* @param userId - The ID of the user to create the room for.
|
|
20
20
|
*/
|
|
21
21
|
createRoom(roomId: string, userId: string): OdinRoom;
|
|
22
22
|
}
|
package/odin.media.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {OdinRoom} from "./odin.room";
|
|
1
|
+
import {OdinAPMSettings, OdinRoom} from "./odin.room";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The OdinMedia class. Represents a local media stream added to the room - i.e. a microphone, another audio stream like files.
|
|
@@ -7,11 +7,12 @@ import {OdinRoom} from "./odin.room";
|
|
|
7
7
|
export declare class OdinMedia {
|
|
8
8
|
/**
|
|
9
9
|
* Creates a new instance of a media object. Don't create OdinMedia directly, use `createAudioStream` from OdinRoom instead.
|
|
10
|
-
* @param room
|
|
11
|
-
* @param sampleRate
|
|
12
|
-
* @param channelCount
|
|
10
|
+
* @param room - The room to add the media to.
|
|
11
|
+
* @param sampleRate - The sample rate of the audio stream (between 8000 and 48000)
|
|
12
|
+
* @param channelCount - The number of channels of the audio stream (1 or 2)
|
|
13
|
+
* @param options - Optional configuration options for Odin Audio Processing Module (APM).
|
|
13
14
|
*/
|
|
14
|
-
constructor(room: OdinRoom, sampleRate: number, channelCount: number);
|
|
15
|
+
constructor(room: OdinRoom, sampleRate: number, channelCount: number, options?: OdinAPMSettings);
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Closes the local audio stream and removed the media from the room
|
|
@@ -22,12 +23,13 @@ export declare class OdinMedia {
|
|
|
22
23
|
* Sends audio data to the room. The data must be in the format specified when creating the media as a 32-bit float array.
|
|
23
24
|
* Samples need to be between -1 and 1. Audio data needs to be sent in regular intervals, otherwise the audio will be sound
|
|
24
25
|
* interrupted. See the example for more details.
|
|
25
|
-
* @param data
|
|
26
|
+
* @param data - A 32-bit float array containing the audio data.
|
|
26
27
|
*/
|
|
27
28
|
sendAudioData(data: Float32Array): void;
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Gets the ID of the media.
|
|
32
|
+
* @returns The ID of the media.
|
|
31
33
|
*/
|
|
32
34
|
get id(): string;
|
|
33
35
|
}
|
package/odin.room.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {OdinMedia} from "./odin.media";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Defines available Odin events
|
|
5
|
+
*/
|
|
3
6
|
declare interface OdinEvents {
|
|
4
7
|
/**
|
|
5
8
|
* Fired when the local user connected to the room (successfully joined).
|
|
@@ -399,55 +402,49 @@ export declare interface OdinAPMSettings {
|
|
|
399
402
|
export declare class OdinRoom {
|
|
400
403
|
/**
|
|
401
404
|
* Creates a new instance of a room with a token. Use OdinClient if you don't want to manage tokens yourself.
|
|
402
|
-
* @param token
|
|
405
|
+
* @param token - The token to use for this room.
|
|
403
406
|
*/
|
|
404
407
|
constructor(token: string);
|
|
405
408
|
|
|
406
409
|
/**
|
|
407
410
|
* Joins the room with the given gateway URL and optional user data.
|
|
408
|
-
* @param gatewayUrl
|
|
409
|
-
* @param userData
|
|
411
|
+
* @param gatewayUrl - The gateway URL to connect to. Use gateway.odin.4players.io if you are unsure.
|
|
412
|
+
* @param userData - The user data to send to the room. This can be used to identify the user.
|
|
410
413
|
*/
|
|
411
414
|
join(gatewayUrl: string, userData?: Uint8Array): void;
|
|
412
415
|
|
|
413
416
|
/**
|
|
414
417
|
* Sends a message to the room.
|
|
415
|
-
* @param message
|
|
416
|
-
* @param peerIdList
|
|
418
|
+
* @param message - The message to send as a byte array.
|
|
419
|
+
* @param peerIdList - The list of peer IDs to send the message to. If this is undefined, the message will be sent to all peers. If the list is defined and empty an error will be thrown.
|
|
417
420
|
*/
|
|
418
421
|
sendMessage(message: Uint8Array, peerIdList?: number[]): void;
|
|
419
422
|
|
|
420
423
|
/**
|
|
421
424
|
* Adds an event listener to the room for specific events.
|
|
422
|
-
* @param
|
|
423
|
-
* @param
|
|
425
|
+
* @param eventName - The event to listen for (see keys of OdinEvents for possible values)
|
|
426
|
+
* @param handler - The callback to call when the event is fired.
|
|
424
427
|
*/
|
|
425
428
|
addEventListener<Event extends keyof OdinEvents>(eventName: Event, handler: OdinEvents[Event]): void;
|
|
426
429
|
|
|
427
430
|
/**
|
|
428
431
|
* Removes an event listener from the room for specific events.
|
|
429
|
-
* @param
|
|
432
|
+
* @param eventName - The event to remove the listener from (see keys of OdinEvents for possible values)
|
|
430
433
|
*/
|
|
431
434
|
removeEventListener<Event extends keyof OdinEvents>(eventName: Event): void;
|
|
432
435
|
|
|
433
436
|
/**
|
|
434
437
|
* Sets a global event listener that received all events, this can be helpful for debugging. Please use addEventListener instead for production code.
|
|
435
|
-
* @param callback
|
|
438
|
+
* @param callback - The callback to call when the event is fired.
|
|
436
439
|
*/
|
|
437
440
|
setEventListener(callback: (data: OdinEventPayload) => void): void;
|
|
438
441
|
|
|
439
442
|
/**
|
|
440
443
|
* Updates the peer user data of the local peer
|
|
441
|
-
* @param userData
|
|
444
|
+
* @param userData - The new user data to set.
|
|
442
445
|
*/
|
|
443
446
|
updateOwnUserData(userData: Uint8Array): void;
|
|
444
447
|
|
|
445
|
-
/**
|
|
446
|
-
* Updates the room user data (for all peers)
|
|
447
|
-
* @param userData {Uint8Array} The new user data to set.
|
|
448
|
-
*/
|
|
449
|
-
updateRoomUserData(userData: Uint8Array): void;
|
|
450
|
-
|
|
451
448
|
/**
|
|
452
449
|
* Closes the room and disconnects from the server.
|
|
453
450
|
*/
|
|
@@ -466,8 +463,9 @@ export declare class OdinRoom {
|
|
|
466
463
|
/**
|
|
467
464
|
* Creates a local audio stream and adds it to the room. An OdinMedia object will be returned that allows you to send
|
|
468
465
|
* audio data.
|
|
469
|
-
* @param sampleRate
|
|
470
|
-
* @param channels
|
|
466
|
+
* @param sampleRate - The sample rate of the audio stream. Can be between 8000 and 48000.
|
|
467
|
+
* @param channels - The number of channels of the audio stream. Can be 1 or 2.
|
|
468
|
+
* @returns The OdinMedia object that allows you to send audio data.
|
|
471
469
|
*/
|
|
472
470
|
createAudioStream(sampleRate: number, channels: number, apmSettings?: OdinAPMSettings): OdinMedia;
|
|
473
471
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4players/odin-nodejs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "NodeJS bindings for the ODIN SDK. Use for AI enhanced human interactions, content moderation and audio processing features in a backend.",
|
|
5
5
|
"main": "index.cjs",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"node-gyp": "^9.3.1",
|
|
35
|
-
"prebuildify": "^5.0.1"
|
|
35
|
+
"prebuildify": "^5.0.1",
|
|
36
|
+
"typedoc": "^0.23.28"
|
|
36
37
|
},
|
|
37
38
|
"engines": {
|
|
38
39
|
"node": ">=18"
|
|
Binary file
|
|
Binary file
|
|
@@ -21,7 +21,7 @@ const userData = {
|
|
|
21
21
|
version: "0.1"
|
|
22
22
|
}
|
|
23
23
|
const data = new TextEncoder().encode(JSON.stringify(userData));
|
|
24
|
-
const odinClient = new OdinClient(accessKey,
|
|
24
|
+
const odinClient = new OdinClient(accessKey, 48000, 2);
|
|
25
25
|
const room = odinClient.createRoom(roomName, userName);
|
|
26
26
|
|
|
27
27
|
// Join the room
|
|
@@ -30,9 +30,7 @@ room.join("gateway.odin.4players.io", data);
|
|
|
30
30
|
// Send a message to the room
|
|
31
31
|
const message = {
|
|
32
32
|
kind: 'message',
|
|
33
|
-
payload:
|
|
34
|
-
text: 'Hello, I am a music bot and will stream some music to you.'
|
|
35
|
-
}
|
|
33
|
+
payload: 'Hello, I am a music bot and will stream some music to you.'
|
|
36
34
|
}
|
|
37
35
|
room.sendMessage(new TextEncoder().encode(JSON.stringify(message)));
|
|
38
36
|
|
|
@@ -41,29 +39,48 @@ const sendMusic = async (media) => {
|
|
|
41
39
|
// Prepare our MP3 decoder and load the sample file
|
|
42
40
|
const audioBuffer = await decode(fs.readFileSync('./santa.mp3'));
|
|
43
41
|
|
|
44
|
-
// Print our some info about the audio file
|
|
45
|
-
console.log(audioBuffer);
|
|
46
|
-
|
|
47
42
|
// Create a stream that will match the settings of the file
|
|
48
|
-
const audioBufferStream = new AudioBufferStream({
|
|
43
|
+
const audioBufferStream = new AudioBufferStream({
|
|
44
|
+
channels: audioBuffer.numberOfChannels,
|
|
45
|
+
sampleRate: audioBuffer.sampleRate,
|
|
46
|
+
float: true,
|
|
47
|
+
bitDepth: 32,
|
|
48
|
+
chunkLength: 960 // 960 bytes every 20ms - might be doubled (1920) depending on the sample rate
|
|
49
|
+
});
|
|
49
50
|
|
|
50
|
-
//
|
|
51
|
+
// Create a queue to store the chunks of audio data
|
|
52
|
+
const queue = [];
|
|
53
|
+
|
|
54
|
+
// Whenever the stream has data, add it to the queue
|
|
51
55
|
audioBufferStream.on('data', (data) => {
|
|
52
|
-
const floats = new Float32Array(new Uint8Array(data).buffer)
|
|
53
|
-
|
|
56
|
+
const floats = new Float32Array(new Uint8Array(data).buffer);
|
|
57
|
+
queue.push(floats);
|
|
54
58
|
});
|
|
55
59
|
|
|
60
|
+
// Start a timer to send audio data at regular intervals
|
|
61
|
+
const interval = setInterval(() => {
|
|
62
|
+
if (queue.length > 0) {
|
|
63
|
+
const chunk = queue.shift();
|
|
64
|
+
media.sendAudioData(chunk);
|
|
65
|
+
} else {
|
|
66
|
+
// If there's no more data to send, stop the timer
|
|
67
|
+
clearInterval(interval);
|
|
68
|
+
audioBufferStream.end();
|
|
69
|
+
console.log("Audio finished");
|
|
70
|
+
}
|
|
71
|
+
}, 20); // Send a chunk every 20ms
|
|
72
|
+
|
|
56
73
|
audioBufferStream.write(audioBuffer);
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
// Create a media stream in the room - it will return an OdinMedia instance that we can use to send data to ODIN
|
|
60
|
-
const media = room.createAudioStream(
|
|
77
|
+
const media = room.createAudioStream(48000, 2);
|
|
61
78
|
console.log(media);
|
|
62
79
|
console.log("MEDIA-ID:", media.id);
|
|
63
80
|
|
|
64
81
|
// Start the stream and send the music to ODIN
|
|
65
82
|
sendMusic(media).then(() => {
|
|
66
|
-
console.log("
|
|
83
|
+
console.log("Started sending audio");
|
|
67
84
|
});
|
|
68
85
|
|
|
69
86
|
// Wait until the user presses a key to stop
|
|
Binary file
|