@cloudfort/callum-voice 0.0.3

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.
@@ -0,0 +1,493 @@
1
+ "use strict";
2
+ // Copyright Cloudfort. All Rights Reserved.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.VoiceClient = void 0;
5
+ const VoiceClientState_1 = require("./VoiceClientState");
6
+ // ── Constants ────────────────────────────────────────────────────────
7
+ const SPEAKING_CHECK_INTERVAL_MS = 80;
8
+ const SPEAKING_RMS_THRESHOLD = 0.012;
9
+ const PEER_RING_CAPACITY = 96000; // ~2s at 48 kHz
10
+ function createPeerState(peerId) {
11
+ return {
12
+ peerId,
13
+ isSpeaking: false,
14
+ rmsLevel: 0,
15
+ ring: new Int16Array(PEER_RING_CAPACITY),
16
+ writePos: 0,
17
+ length: 0,
18
+ };
19
+ }
20
+ function peerEnqueue(peer, samples) {
21
+ if (peer.length + samples.length > PEER_RING_CAPACITY) {
22
+ const drop = peer.length + samples.length - PEER_RING_CAPACITY;
23
+ peer.length -= drop;
24
+ }
25
+ for (let i = 0; i < samples.length; i++) {
26
+ peer.ring[(peer.writePos + i) % PEER_RING_CAPACITY] = samples[i];
27
+ }
28
+ peer.writePos = (peer.writePos + samples.length) % PEER_RING_CAPACITY;
29
+ peer.length += samples.length;
30
+ }
31
+ function peerComputeRms(peer) {
32
+ const count = Math.min(peer.length, 480); // ~10ms at 48 kHz
33
+ if (count === 0)
34
+ return 0;
35
+ let sum = 0;
36
+ const start = (peer.writePos - count + PEER_RING_CAPACITY) % PEER_RING_CAPACITY;
37
+ for (let i = 0; i < count; i++) {
38
+ const v = peer.ring[(start + i) % PEER_RING_CAPACITY] / 32768.0;
39
+ sum += v * v;
40
+ }
41
+ return Math.sqrt(sum / count);
42
+ }
43
+ function peerClear(peer) {
44
+ peer.writePos = 0;
45
+ peer.length = 0;
46
+ peer.isSpeaking = false;
47
+ peer.rmsLevel = 0;
48
+ }
49
+ // ── VoiceClient ──────────────────────────────────────────────────────
50
+ /**
51
+ * Cross-platform voice-chat client for React Native.
52
+ *
53
+ * Connects to the Go voice service over WebSocket, captures microphone audio
54
+ * via a native audio engine, and plays back remote peer audio.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const client = new VoiceClient(createVoiceConfig({
59
+ * server: 'callem.cloudfort.ir',
60
+ * apiKey: 'vc_live_...',
61
+ * peerId: 'user_123',
62
+ * }));
63
+ *
64
+ * client.setListener({
65
+ * onConnected: () => console.log('Connected!'),
66
+ * onPeerSpeaking: (id) => console.log(`${id} is speaking`),
67
+ * });
68
+ *
69
+ * await client.connect();
70
+ * await client.joinRoom('game_room_1');
71
+ * await client.enableMic();
72
+ * ```
73
+ */
74
+ class VoiceClient {
75
+ constructor(config) {
76
+ this.listener = null;
77
+ this.ws = null;
78
+ this._state = VoiceClientState_1.VoiceClientState.Disconnected;
79
+ this.currentRoom = null;
80
+ this.micEnabled = false;
81
+ this.speakerEnabled = false;
82
+ this.reconnectAttempts = 0;
83
+ this.prevRoom = null;
84
+ this.prevMicEnabled = false;
85
+ this.peers = new Map();
86
+ this.speakingTimer = null;
87
+ this.reconnectTimer = null;
88
+ this.config = config;
89
+ }
90
+ // ── Public Properties ────────────────────────────────────────────
91
+ /** Current connection state */
92
+ get state() {
93
+ return this._state;
94
+ }
95
+ /** Whether connected to server */
96
+ get isConnected() {
97
+ return this._state >= VoiceClientState_1.VoiceClientState.Connected;
98
+ }
99
+ /** Whether joined a room */
100
+ get isInRoom() {
101
+ return this._state === VoiceClientState_1.VoiceClientState.InRoom;
102
+ }
103
+ /** Whether microphone is active */
104
+ get isMicEnabled() {
105
+ return this.micEnabled;
106
+ }
107
+ /** Whether speaker output is active */
108
+ get isSpeakerEnabled() {
109
+ return this.speakerEnabled;
110
+ }
111
+ /** Current room ID (null if not in room) */
112
+ get currentRoomId() {
113
+ return this.currentRoom;
114
+ }
115
+ /** List of peer IDs in the current room */
116
+ get peerIds() {
117
+ return Array.from(this.peers.keys());
118
+ }
119
+ // ── Listener ─────────────────────────────────────────────────────
120
+ /** Set the event listener */
121
+ setListener(listener) {
122
+ this.listener = listener;
123
+ }
124
+ // ── Connection ───────────────────────────────────────────────────
125
+ /** Connect to the voice server */
126
+ async connect() {
127
+ if (this._state >= VoiceClientState_1.VoiceClientState.Connected)
128
+ return;
129
+ this.setState(VoiceClientState_1.VoiceClientState.Connecting);
130
+ const scheme = this.resolveScheme();
131
+ const url = `${scheme}://${this.config.server}/ws` +
132
+ `?room=__lobby__` +
133
+ `&peer=${encodeURIComponent(this.config.peerId)}` +
134
+ `&api_key=${encodeURIComponent(this.config.apiKey)}`;
135
+ try {
136
+ this.ws = new WebSocket(url);
137
+ this.ws.binaryType = 'arraybuffer';
138
+ this.ws.onopen = () => {
139
+ this.handleWebSocketConnected();
140
+ };
141
+ this.ws.onmessage = (event) => {
142
+ if (typeof event.data === 'string') {
143
+ this.handleTextMessage(event.data);
144
+ }
145
+ else if (event.data instanceof ArrayBuffer) {
146
+ this.handleBinaryMessage(new Uint8Array(event.data));
147
+ }
148
+ };
149
+ this.ws.onclose = (event) => {
150
+ var _a, _b;
151
+ this.handleClose((_a = event.code) !== null && _a !== void 0 ? _a : 1006, (_b = event.reason) !== null && _b !== void 0 ? _b : '');
152
+ this.handleDisconnect();
153
+ };
154
+ this.ws.onerror = () => {
155
+ this.raiseError(new Error('WebSocket error'));
156
+ this.handleDisconnect();
157
+ };
158
+ }
159
+ catch (e) {
160
+ this.raiseError(e instanceof Error ? e : new Error(String(e)));
161
+ this.setState(VoiceClientState_1.VoiceClientState.Disconnected);
162
+ }
163
+ }
164
+ /** Disconnect from the server */
165
+ disconnect() {
166
+ var _a, _b;
167
+ this.config.autoReconnect = false;
168
+ this.cleanup();
169
+ this.setState(VoiceClientState_1.VoiceClientState.Disconnected);
170
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onDisconnected) === null || _b === void 0 ? void 0 : _b.call(_a);
171
+ }
172
+ // ── Room Management ──────────────────────────────────────────────
173
+ /** Join a voice room */
174
+ async joinRoom(roomId) {
175
+ var _a, _b;
176
+ if (this._state < VoiceClientState_1.VoiceClientState.Connected) {
177
+ this.raiseError(new Error('Not connected'));
178
+ return;
179
+ }
180
+ if (this.currentRoom !== null) {
181
+ await this.leaveRoom();
182
+ }
183
+ // TODO: Start native audio playback engine via NativeModules
184
+ const joinMsg = JSON.stringify({
185
+ type: 'join',
186
+ room: roomId,
187
+ peer: this.config.peerId,
188
+ sampleRate: this.config.sampleRate,
189
+ });
190
+ this.sendText(joinMsg);
191
+ this.currentRoom = roomId;
192
+ this.setState(VoiceClientState_1.VoiceClientState.InRoom);
193
+ // Start speaking detection timer
194
+ this.speakingTimer = setInterval(() => {
195
+ this.checkSpeaking();
196
+ }, SPEAKING_CHECK_INTERVAL_MS);
197
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onRoomJoined) === null || _b === void 0 ? void 0 : _b.call(_a, roomId);
198
+ }
199
+ /** Leave the current room */
200
+ async leaveRoom() {
201
+ var _a, _b, _c, _d;
202
+ if (this.currentRoom === null)
203
+ return;
204
+ this.stopMic();
205
+ if (this.speakingTimer !== null) {
206
+ clearInterval(this.speakingTimer);
207
+ this.speakingTimer = null;
208
+ }
209
+ const room = this.currentRoom;
210
+ // Notify peers leaving
211
+ const peerIds = Array.from(this.peers.keys());
212
+ this.peers.clear();
213
+ for (const peerId of peerIds) {
214
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onPeerLeft) === null || _b === void 0 ? void 0 : _b.call(_a, peerId);
215
+ }
216
+ // TODO: Clear peers and stop playback via native audio engine
217
+ this.currentRoom = null;
218
+ this.setState(VoiceClientState_1.VoiceClientState.Connected);
219
+ (_d = (_c = this.listener) === null || _c === void 0 ? void 0 : _c.onRoomLeft) === null || _d === void 0 ? void 0 : _d.call(_c, room);
220
+ }
221
+ // ── Microphone Control ───────────────────────────────────────────
222
+ /** Enable microphone (must be in a room) */
223
+ async enableMic() {
224
+ var _a, _b;
225
+ if (this.micEnabled)
226
+ return;
227
+ if (this._state !== VoiceClientState_1.VoiceClientState.InRoom) {
228
+ this.raiseError(new Error('Must be in a room to enable mic'));
229
+ return;
230
+ }
231
+ // TODO: Request microphone permission via NativeModules
232
+ // TODO: Start native audio capture via NativeModules
233
+ this.micEnabled = true;
234
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onMicEnabled) === null || _b === void 0 ? void 0 : _b.call(_a);
235
+ }
236
+ /** Disable microphone */
237
+ disableMic() {
238
+ var _a, _b;
239
+ if (!this.micEnabled)
240
+ return;
241
+ this.stopMic();
242
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onMicDisabled) === null || _b === void 0 ? void 0 : _b.call(_a);
243
+ }
244
+ /** Toggle microphone, returns new state */
245
+ async toggleMic() {
246
+ if (this.micEnabled) {
247
+ this.disableMic();
248
+ return false;
249
+ }
250
+ await this.enableMic();
251
+ return true;
252
+ }
253
+ // ── Speaker Control ──────────────────────────────────────────────
254
+ /** Enable speaker output */
255
+ enableSpeaker() {
256
+ var _a, _b;
257
+ if (this.speakerEnabled)
258
+ return;
259
+ this.speakerEnabled = true;
260
+ // TODO: Set speaker routing via NativeModules
261
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onSpeakerEnabled) === null || _b === void 0 ? void 0 : _b.call(_a);
262
+ }
263
+ /** Disable speaker output */
264
+ disableSpeaker() {
265
+ var _a, _b;
266
+ if (!this.speakerEnabled)
267
+ return;
268
+ this.speakerEnabled = false;
269
+ // TODO: Set speaker routing via NativeModules
270
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onSpeakerDisabled) === null || _b === void 0 ? void 0 : _b.call(_a);
271
+ }
272
+ /** Toggle speaker, returns new state */
273
+ toggleSpeaker() {
274
+ if (this.speakerEnabled) {
275
+ this.disableSpeaker();
276
+ return false;
277
+ }
278
+ this.enableSpeaker();
279
+ return true;
280
+ }
281
+ // ── Speaking Detection ───────────────────────────────────────────
282
+ /** Check if a specific peer is speaking */
283
+ isPeerSpeaking(peerId) {
284
+ var _a, _b;
285
+ return (_b = (_a = this.peers.get(peerId)) === null || _a === void 0 ? void 0 : _a.isSpeaking) !== null && _b !== void 0 ? _b : false;
286
+ }
287
+ /** Get peer speaking state with RMS level */
288
+ getPeerSpeakingInfo(peerId) {
289
+ const peer = this.peers.get(peerId);
290
+ if (!peer)
291
+ return { speaking: false, rms: 0 };
292
+ return { speaking: peer.isSpeaking, rms: peer.rmsLevel };
293
+ }
294
+ // ── Cleanup ──────────────────────────────────────────────────────
295
+ /** Dispose and release all resources */
296
+ dispose() {
297
+ this.config.autoReconnect = false;
298
+ this.cleanup();
299
+ }
300
+ // ── Private: WebSocket Event Handlers ────────────────────────────
301
+ handleWebSocketConnected() {
302
+ var _a, _b;
303
+ this.setState(VoiceClientState_1.VoiceClientState.Connected);
304
+ this.reconnectAttempts = 0;
305
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onConnected) === null || _b === void 0 ? void 0 : _b.call(_a);
306
+ // Re-join room if we were in one before disconnect
307
+ if (this.prevRoom !== null) {
308
+ const restoreMic = this.prevMicEnabled;
309
+ const room = this.prevRoom;
310
+ this.prevRoom = null;
311
+ this.prevMicEnabled = false;
312
+ this.joinRoom(room).then(() => {
313
+ if (restoreMic) {
314
+ this.enableMic();
315
+ }
316
+ }).catch((e) => {
317
+ this.raiseError(e instanceof Error ? e : new Error(String(e)));
318
+ });
319
+ }
320
+ }
321
+ handleTextMessage(text) {
322
+ try {
323
+ const json = JSON.parse(text);
324
+ if (json && typeof json === 'object') {
325
+ const type = json['type'];
326
+ if (type === 'udp_token') {
327
+ // Handle UDP token if needed
328
+ }
329
+ }
330
+ }
331
+ catch (e) {
332
+ this.raiseError(e instanceof Error ? e : new Error(String(e)));
333
+ }
334
+ }
335
+ // ── Private: Binary Packet Parsing ───────────────────────────────
336
+ // Format: [1B RoomLen][RoomID][1B PeerLen][PeerID][PCM Audio Data]
337
+ handleBinaryMessage(data) {
338
+ if (data.length < 4)
339
+ return;
340
+ const roomLen = data[0];
341
+ if (data.length < 2 + roomLen)
342
+ return;
343
+ const peerLen = data[1 + roomLen];
344
+ if (data.length < 2 + roomLen + peerLen)
345
+ return;
346
+ const peerIdBytes = data.slice(2 + roomLen, 2 + roomLen + peerLen);
347
+ const peerId = new TextDecoder().decode(peerIdBytes);
348
+ if (peerId === this.config.peerId)
349
+ return; // ignore own echo
350
+ const audioOffset = 2 + roomLen + peerLen;
351
+ const audioLen = data.length - audioOffset;
352
+ if (audioLen === 0)
353
+ return;
354
+ // Convert PCM bytes → Int16Array
355
+ const sampleCount = Math.floor(audioLen / 2);
356
+ const samples = new Int16Array(sampleCount);
357
+ const view = new DataView(data.buffer, data.byteOffset + audioOffset, sampleCount * 2);
358
+ for (let i = 0; i < sampleCount; i++) {
359
+ samples[i] = view.getInt16(i * 2, true); // little-endian
360
+ }
361
+ this.handlePeerAudio(peerId, samples);
362
+ }
363
+ handlePeerAudio(peerId, samples) {
364
+ var _a, _b;
365
+ let peer = this.peers.get(peerId);
366
+ if (!peer) {
367
+ peer = createPeerState(peerId);
368
+ this.peers.set(peerId, peer);
369
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onPeerJoined) === null || _b === void 0 ? void 0 : _b.call(_a, peerId);
370
+ }
371
+ // TODO: Enqueue audio to native playback engine
372
+ peerEnqueue(peer, samples);
373
+ }
374
+ checkSpeaking() {
375
+ var _a, _b, _c, _d;
376
+ for (const [peerId, peer] of this.peers) {
377
+ const rms = peerComputeRms(peer);
378
+ const wasSpeaking = peer.isSpeaking;
379
+ const isSpeaking = rms > SPEAKING_RMS_THRESHOLD;
380
+ if (isSpeaking !== wasSpeaking) {
381
+ peer.isSpeaking = isSpeaking;
382
+ if (isSpeaking) {
383
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onPeerSpeaking) === null || _b === void 0 ? void 0 : _b.call(_a, peerId);
384
+ }
385
+ else {
386
+ (_d = (_c = this.listener) === null || _c === void 0 ? void 0 : _c.onPeerStopped) === null || _d === void 0 ? void 0 : _d.call(_c, peerId);
387
+ }
388
+ }
389
+ peer.rmsLevel = rms;
390
+ }
391
+ }
392
+ // ── Private: Close / Disconnect / Reconnect ──────────────────────
393
+ handleClose(code, reason) {
394
+ var _a, _b;
395
+ // Close codes 1008 / 4001 indicate auth failure
396
+ if (code === 1008 || code === 4001) {
397
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onAuthFailed) === null || _b === void 0 ? void 0 : _b.call(_a, reason || 'Authentication failed');
398
+ this.config.autoReconnect = false;
399
+ }
400
+ }
401
+ handleDisconnect() {
402
+ var _a, _b, _c, _d;
403
+ const wasConnected = this._state >= VoiceClientState_1.VoiceClientState.Connected;
404
+ // Save state for reconnect restoration
405
+ this.prevRoom = this.currentRoom;
406
+ this.prevMicEnabled = this.micEnabled;
407
+ this.cleanup();
408
+ if (!wasConnected)
409
+ return;
410
+ this.setState(VoiceClientState_1.VoiceClientState.Disconnected);
411
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onDisconnected) === null || _b === void 0 ? void 0 : _b.call(_a);
412
+ if (this.config.autoReconnect &&
413
+ this.reconnectAttempts < this.config.maxReconnectAttempts) {
414
+ this.reconnectAttempts++;
415
+ this.setState(VoiceClientState_1.VoiceClientState.Reconnecting);
416
+ (_d = (_c = this.listener) === null || _c === void 0 ? void 0 : _c.onReconnecting) === null || _d === void 0 ? void 0 : _d.call(_c, this.reconnectAttempts);
417
+ this.reconnectTimer = setTimeout(() => {
418
+ this.connect();
419
+ }, this.config.reconnectDelayMs);
420
+ }
421
+ }
422
+ // ── Private: Send Helpers ────────────────────────────────────────
423
+ sendText(text) {
424
+ var _a;
425
+ if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
426
+ this.ws.send(text);
427
+ }
428
+ }
429
+ /** Send captured audio to server (called from native audio engine) */
430
+ sendAudio(samples) {
431
+ var _a;
432
+ if (!this.micEnabled || ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) !== WebSocket.OPEN)
433
+ return;
434
+ const bytes = new Uint8Array(samples.buffer, samples.byteOffset, samples.byteLength);
435
+ this.ws.send(bytes.slice());
436
+ }
437
+ // ── Private: Cleanup ─────────────────────────────────────────────
438
+ cleanup() {
439
+ var _a, _b;
440
+ this.stopMic();
441
+ if (this.speakingTimer !== null) {
442
+ clearInterval(this.speakingTimer);
443
+ this.speakingTimer = null;
444
+ }
445
+ if (this.reconnectTimer !== null) {
446
+ clearTimeout(this.reconnectTimer);
447
+ this.reconnectTimer = null;
448
+ }
449
+ // Notify peers leaving
450
+ const peerIds = Array.from(this.peers.keys());
451
+ this.peers.clear();
452
+ for (const peerId of peerIds) {
453
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onPeerLeft) === null || _b === void 0 ? void 0 : _b.call(_a, peerId);
454
+ }
455
+ if (this.ws !== null) {
456
+ try {
457
+ this.ws.close(1000, 'bye');
458
+ }
459
+ catch (_c) {
460
+ // ignore
461
+ }
462
+ this.ws = null;
463
+ }
464
+ this.currentRoom = null;
465
+ }
466
+ stopMic() {
467
+ if (!this.micEnabled)
468
+ return;
469
+ // TODO: Stop native audio capture
470
+ this.micEnabled = false;
471
+ }
472
+ // ── Private: Helpers ─────────────────────────────────────────────
473
+ resolveScheme() {
474
+ if (this.config.useTls === true)
475
+ return 'wss';
476
+ if (this.config.useTls === false)
477
+ return 'ws';
478
+ return 'ws';
479
+ }
480
+ setState(newState) {
481
+ var _a, _b;
482
+ if (this._state === newState)
483
+ return;
484
+ this._state = newState;
485
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onStateChanged) === null || _b === void 0 ? void 0 : _b.call(_a, newState);
486
+ }
487
+ raiseError(error) {
488
+ var _a, _b;
489
+ (_b = (_a = this.listener) === null || _a === void 0 ? void 0 : _a.onError) === null || _b === void 0 ? void 0 : _b.call(_a, error);
490
+ }
491
+ }
492
+ exports.VoiceClient = VoiceClient;
493
+ //# sourceMappingURL=VoiceClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceClient.js","sourceRoot":"","sources":["../src/VoiceClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Connection state of the VoiceClient.
3
+ */
4
+ export declare enum VoiceClientState {
5
+ /** Not connected, not attempting to connect */
6
+ Disconnected = 0,
7
+ /** Establishing WebSocket connection */
8
+ Connecting = 1,
9
+ /** Connected to server, not yet in a room */
10
+ Connected = 2,
11
+ /** Joined a room and ready for audio */
12
+ InRoom = 3,
13
+ /** Attempting to reconnect after an unexpected disconnect */
14
+ Reconnecting = 4
15
+ }
16
+ //# sourceMappingURL=VoiceClientState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceClientState.d.ts","sourceRoot":"","sources":["../src/VoiceClientState.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,oBAAY,gBAAgB;IAC1B,+CAA+C;IAC/C,YAAY,IAAI;IAEhB,wCAAwC;IACxC,UAAU,IAAI;IAEd,6CAA6C;IAC7C,SAAS,IAAI;IAEb,wCAAwC;IACxC,MAAM,IAAI;IAEV,6DAA6D;IAC7D,YAAY,IAAI;CACjB"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ // Copyright Cloudfort. All Rights Reserved.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.VoiceClientState = void 0;
5
+ /**
6
+ * Connection state of the VoiceClient.
7
+ */
8
+ var VoiceClientState;
9
+ (function (VoiceClientState) {
10
+ /** Not connected, not attempting to connect */
11
+ VoiceClientState[VoiceClientState["Disconnected"] = 0] = "Disconnected";
12
+ /** Establishing WebSocket connection */
13
+ VoiceClientState[VoiceClientState["Connecting"] = 1] = "Connecting";
14
+ /** Connected to server, not yet in a room */
15
+ VoiceClientState[VoiceClientState["Connected"] = 2] = "Connected";
16
+ /** Joined a room and ready for audio */
17
+ VoiceClientState[VoiceClientState["InRoom"] = 3] = "InRoom";
18
+ /** Attempting to reconnect after an unexpected disconnect */
19
+ VoiceClientState[VoiceClientState["Reconnecting"] = 4] = "Reconnecting";
20
+ })(VoiceClientState || (exports.VoiceClientState = VoiceClientState = {}));
21
+ //# sourceMappingURL=VoiceClientState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceClientState.js","sourceRoot":"","sources":["../src/VoiceClientState.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;AAE5C;;GAEG;AACH,IAAY,gBAeX;AAfD,WAAY,gBAAgB;IAC1B,+CAA+C;IAC/C,uEAAgB,CAAA;IAEhB,wCAAwC;IACxC,mEAAc,CAAA;IAEd,6CAA6C;IAC7C,iEAAa,CAAA;IAEb,wCAAwC;IACxC,2DAAU,CAAA;IAEV,6DAA6D;IAC7D,uEAAgB,CAAA;AAClB,CAAC,EAfW,gBAAgB,gCAAhB,gBAAgB,QAe3B"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Configuration for connecting to the voice chat service.
3
+ */
4
+ export interface VoiceConfig {
5
+ /** Server address (e.g. "callem.cloudfort.ir"). Do NOT include scheme or port. */
6
+ server: string;
7
+ /** API key obtained from account registration (vc_live_...) */
8
+ apiKey: string;
9
+ /** Unique identifier for this peer / user */
10
+ peerId: string;
11
+ /** Use WSS (TLS) instead of WS. Auto-detected when undefined. */
12
+ useTls?: boolean;
13
+ /** Audio sample rate in Hz (default 48000) */
14
+ sampleRate: number;
15
+ /** Automatically reconnect on unexpected disconnect (default true) */
16
+ autoReconnect: boolean;
17
+ /** Maximum reconnection attempts before giving up (default 5) */
18
+ maxReconnectAttempts: number;
19
+ /** Delay between reconnection attempts in milliseconds (default 2000) */
20
+ reconnectDelayMs: number;
21
+ /** Enable platform echo cancellation (default true) */
22
+ echoCancellation: boolean;
23
+ /** Enable platform noise suppression (default true) */
24
+ noiseSuppression: boolean;
25
+ /** Enable platform automatic gain control (default true) */
26
+ autoGainControl: boolean;
27
+ }
28
+ /**
29
+ * Create a VoiceConfig with sensible defaults.
30
+ */
31
+ export declare function createVoiceConfig(overrides: Partial<VoiceConfig>): VoiceConfig;
32
+ //# sourceMappingURL=VoiceConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceConfig.d.ts","sourceRoot":"","sources":["../src/VoiceConfig.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IAEf,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IAEf,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IAEf,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IAEnB,sEAAsE;IACtE,aAAa,EAAE,OAAO,CAAC;IAEvB,iEAAiE;IACjE,oBAAoB,EAAE,MAAM,CAAC;IAE7B,yEAAyE;IACzE,gBAAgB,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,gBAAgB,EAAE,OAAO,CAAC;IAE1B,uDAAuD;IACvD,gBAAgB,EAAE,OAAO,CAAC;IAE1B,4DAA4D;IAC5D,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAc9E"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ // Copyright Cloudfort. All Rights Reserved.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.createVoiceConfig = createVoiceConfig;
5
+ /**
6
+ * Create a VoiceConfig with sensible defaults.
7
+ */
8
+ function createVoiceConfig(overrides) {
9
+ return Object.assign({ server: '', apiKey: '', peerId: '', sampleRate: 48000, autoReconnect: true, maxReconnectAttempts: 5, reconnectDelayMs: 2000, echoCancellation: true, noiseSuppression: true, autoGainControl: true }, overrides);
10
+ }
11
+ //# sourceMappingURL=VoiceConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceConfig.js","sourceRoot":"","sources":["../src/VoiceConfig.ts"],"names":[],"mappings":";AAAA,4CAA4C;;AA2C5C,8CAcC;AAjBD;;GAEG;AACH,SAAgB,iBAAiB,CAAC,SAA+B;IAC/D,uBACE,MAAM,EAAE,EAAE,EACV,MAAM,EAAE,EAAE,EACV,MAAM,EAAE,EAAE,EACV,UAAU,EAAE,KAAK,EACjB,aAAa,EAAE,IAAI,EACnB,oBAAoB,EAAE,CAAC,EACvB,gBAAgB,EAAE,IAAI,EACtB,gBAAgB,EAAE,IAAI,EACtB,gBAAgB,EAAE,IAAI,EACtB,eAAe,EAAE,IAAI,IAClB,SAAS,EACZ;AACJ,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { VoiceClientState } from './VoiceClientState';
2
+ /**
3
+ * Callback interface for receiving voice client events.
4
+ *
5
+ * Implement only the methods you need — all methods have no-op defaults.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const listener: VoiceEventListener = {
10
+ * onConnected: () => console.log('Connected!'),
11
+ * onPeerSpeaking: (peerId) => console.log(`${peerId} speaking`),
12
+ * };
13
+ * ```
14
+ */
15
+ export interface VoiceEventListener {
16
+ /** Connection established */
17
+ onConnected?(): void;
18
+ /** Connection lost */
19
+ onDisconnected?(): void;
20
+ /** Reconnection attempt in progress */
21
+ onReconnecting?(attempt: number): void;
22
+ /** Authentication failed */
23
+ onAuthFailed?(reason: string): void;
24
+ /** Joined a room */
25
+ onRoomJoined?(roomId: string): void;
26
+ /** Left a room */
27
+ onRoomLeft?(roomId: string): void;
28
+ /** New peer joined the room */
29
+ onPeerJoined?(peerId: string): void;
30
+ /** Peer left the room */
31
+ onPeerLeft?(peerId: string): void;
32
+ /** Peer started speaking */
33
+ onPeerSpeaking?(peerId: string): void;
34
+ /** Peer stopped speaking */
35
+ onPeerStopped?(peerId: string): void;
36
+ /** Microphone enabled */
37
+ onMicEnabled?(): void;
38
+ /** Microphone disabled */
39
+ onMicDisabled?(): void;
40
+ /** Speaker enabled */
41
+ onSpeakerEnabled?(): void;
42
+ /** Speaker disabled */
43
+ onSpeakerDisabled?(): void;
44
+ /** Error occurred */
45
+ onError?(error: Error): void;
46
+ /** Connection state changed */
47
+ onStateChanged?(newState: VoiceClientState): void;
48
+ }
49
+ //# sourceMappingURL=VoiceEventListener.d.ts.map