@newgameplusinc/odyssey-audio-video-sdk-dev 1.0.258 → 1.0.260

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 (83) hide show
  1. package/README.md +45 -1
  2. package/dist/audio/AudioNodeFactory.d.ts +130 -0
  3. package/dist/audio/AudioNodeFactory.js +158 -0
  4. package/dist/audio/AudioPipeline.d.ts +89 -0
  5. package/dist/audio/AudioPipeline.js +138 -0
  6. package/dist/{MLNoiseSuppressor.d.ts → audio/MLNoiseSuppressor.d.ts} +7 -7
  7. package/dist/{MLNoiseSuppressor.js → audio/MLNoiseSuppressor.js} +19 -52
  8. package/dist/audio/index.d.ts +6 -0
  9. package/dist/audio/index.js +22 -0
  10. package/dist/channels/huddle/HuddleChannel.d.ts +87 -0
  11. package/dist/channels/huddle/HuddleChannel.js +152 -0
  12. package/dist/channels/huddle/HuddleTypes.d.ts +85 -0
  13. package/dist/channels/huddle/HuddleTypes.js +25 -0
  14. package/dist/channels/huddle/index.d.ts +5 -0
  15. package/dist/channels/huddle/index.js +21 -0
  16. package/dist/channels/index.d.ts +5 -0
  17. package/dist/channels/index.js +21 -0
  18. package/dist/channels/spatial/SpatialAudioChannel.d.ts +144 -0
  19. package/dist/channels/spatial/SpatialAudioChannel.js +476 -0
  20. package/dist/channels/spatial/SpatialAudioTypes.d.ts +85 -0
  21. package/dist/channels/spatial/SpatialAudioTypes.js +42 -0
  22. package/dist/channels/spatial/index.d.ts +5 -0
  23. package/dist/channels/spatial/index.js +21 -0
  24. package/dist/{EventManager.d.ts → core/EventManager.d.ts} +4 -2
  25. package/dist/{EventManager.js → core/EventManager.js} +5 -3
  26. package/dist/{MediasoupManager.d.ts → core/MediasoupManager.d.ts} +10 -4
  27. package/dist/{MediasoupManager.js → core/MediasoupManager.js} +56 -44
  28. package/dist/core/index.d.ts +5 -0
  29. package/dist/core/index.js +21 -0
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.js +43 -9
  32. package/dist/sdk/index.d.ts +36 -0
  33. package/dist/sdk/index.js +121 -0
  34. package/dist/types/events.d.ts +154 -0
  35. package/dist/{types.js → types/events.js} +3 -0
  36. package/dist/types/index.d.ts +7 -0
  37. package/dist/types/index.js +23 -0
  38. package/dist/types/participant.d.ts +65 -0
  39. package/dist/types/participant.js +5 -0
  40. package/dist/types/position.d.ts +47 -0
  41. package/dist/types/position.js +9 -0
  42. package/dist/types/room.d.ts +82 -0
  43. package/dist/types/room.js +5 -0
  44. package/dist/utils/audio/clarity-score.d.ts +33 -0
  45. package/dist/utils/audio/clarity-score.js +81 -0
  46. package/dist/utils/audio/index.d.ts +5 -0
  47. package/dist/utils/audio/index.js +21 -0
  48. package/dist/utils/audio/voice-filter.d.ts +30 -0
  49. package/dist/utils/audio/voice-filter.js +70 -0
  50. package/dist/utils/index.d.ts +7 -0
  51. package/dist/utils/index.js +23 -0
  52. package/dist/utils/position/coordinates.d.ts +37 -0
  53. package/dist/utils/position/coordinates.js +61 -0
  54. package/dist/utils/position/index.d.ts +6 -0
  55. package/dist/utils/position/index.js +22 -0
  56. package/dist/utils/position/normalize.d.ts +37 -0
  57. package/dist/utils/position/normalize.js +78 -0
  58. package/dist/utils/position/snap.d.ts +51 -0
  59. package/dist/utils/position/snap.js +81 -0
  60. package/dist/utils/smoothing/gain-smoothing.d.ts +45 -0
  61. package/dist/utils/smoothing/gain-smoothing.js +77 -0
  62. package/dist/utils/smoothing/index.d.ts +5 -0
  63. package/dist/utils/smoothing/index.js +21 -0
  64. package/dist/utils/smoothing/pan-smoothing.d.ts +43 -0
  65. package/dist/utils/smoothing/pan-smoothing.js +85 -0
  66. package/dist/utils/spatial/angle-calc.d.ts +24 -0
  67. package/dist/utils/spatial/angle-calc.js +69 -0
  68. package/dist/utils/spatial/distance-calc.d.ts +33 -0
  69. package/dist/utils/spatial/distance-calc.js +48 -0
  70. package/dist/utils/spatial/gain-calc.d.ts +37 -0
  71. package/dist/utils/spatial/gain-calc.js +52 -0
  72. package/dist/utils/spatial/head-position.d.ts +32 -0
  73. package/dist/utils/spatial/head-position.js +76 -0
  74. package/dist/utils/spatial/index.d.ts +9 -0
  75. package/dist/utils/spatial/index.js +25 -0
  76. package/dist/utils/spatial/listener-calc.d.ts +28 -0
  77. package/dist/utils/spatial/listener-calc.js +74 -0
  78. package/dist/utils/spatial/pan-calc.d.ts +48 -0
  79. package/dist/utils/spatial/pan-calc.js +80 -0
  80. package/package.json +1 -1
  81. package/dist/SpatialAudioManager.d.ts +0 -271
  82. package/dist/SpatialAudioManager.js +0 -1512
  83. package/dist/types.d.ts +0 -73
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * Spatial Audio Types
4
+ *
5
+ * Type definitions for spatial audio processing
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.DEFAULT_DENOISER_OPTIONS = exports.DEFAULT_SPATIAL_CONFIG = void 0;
9
+ /**
10
+ * Default spatial distance configuration
11
+ */
12
+ exports.DEFAULT_SPATIAL_CONFIG = {
13
+ refDistance: 1.2,
14
+ maxDistance: 15,
15
+ rolloffFactor: 1.35,
16
+ unit: 'auto',
17
+ };
18
+ /**
19
+ * Default denoiser configuration
20
+ */
21
+ exports.DEFAULT_DENOISER_OPTIONS = {
22
+ enabled: false,
23
+ threshold: 0.002,
24
+ noiseFloor: 0.0005,
25
+ release: 0.4,
26
+ attack: 0.1,
27
+ holdMs: 200,
28
+ maxReduction: 0.15,
29
+ hissCut: 0.15,
30
+ expansionRatio: 1.05,
31
+ learnRate: 0.03,
32
+ voiceBoost: 0.35,
33
+ voiceSensitivity: 0.1,
34
+ voiceEnhancement: false,
35
+ silenceFloor: 0.0002,
36
+ silenceHoldMs: 400,
37
+ silenceReleaseMs: 200,
38
+ speechBoost: 0.25,
39
+ highBandGate: 0.15,
40
+ highBandAttack: 0.08,
41
+ highBandRelease: 0.03,
42
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Spatial module - Re-exports spatial audio channel functionality
3
+ */
4
+ export * from './SpatialAudioTypes';
5
+ export * from './SpatialAudioChannel';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Spatial module - Re-exports spatial audio channel functionality
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ __exportStar(require("./SpatialAudioTypes"), exports);
21
+ __exportStar(require("./SpatialAudioChannel"), exports);
@@ -1,10 +1,12 @@
1
- import { EventEmitter } from "events";
2
- import { OdysseyEvent } from "./types";
3
1
  /**
2
+ * Event Manager
3
+ *
4
4
  * A clean, standalone event bus for the SDK, completely decoupled from the socket.
5
5
  * This ensures that only processed, structured SDK events are emitted to the application.
6
6
  * It extends the Node.js EventEmitter to provide a standard and reliable event API.
7
7
  */
8
+ import { EventEmitter } from 'events';
9
+ import { OdysseyEvent } from '../types/events';
8
10
  export declare class EventManager extends EventEmitter {
9
11
  constructor();
10
12
  on(event: OdysseyEvent, listener: (...args: any[]) => void): this;
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EventManager = void 0;
4
- const events_1 = require("events");
5
2
  /**
3
+ * Event Manager
4
+ *
6
5
  * A clean, standalone event bus for the SDK, completely decoupled from the socket.
7
6
  * This ensures that only processed, structured SDK events are emitted to the application.
8
7
  * It extends the Node.js EventEmitter to provide a standard and reliable event API.
9
8
  */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EventManager = void 0;
11
+ const events_1 = require("events");
10
12
  class EventManager extends events_1.EventEmitter {
11
13
  constructor() {
12
14
  super();
@@ -1,6 +1,12 @@
1
- import * as mediasoupClient from "mediasoup-client";
2
- import { types } from "mediasoup-client";
3
- import { Socket } from "socket.io-client";
1
+ /**
2
+ * Mediasoup Manager
3
+ *
4
+ * Handles WebRTC transport, producer, and consumer management
5
+ * using the mediasoup-client library
6
+ */
7
+ import * as mediasoupClient from 'mediasoup-client';
8
+ import { types } from 'mediasoup-client';
9
+ import { Socket } from 'socket.io-client';
4
10
  export declare class MediasoupManager {
5
11
  private device;
6
12
  private socket;
@@ -20,7 +26,7 @@ export declare class MediasoupManager {
20
26
  consume(data: {
21
27
  consumerId: string;
22
28
  producerId: string;
23
- kind: "audio" | "video";
29
+ kind: 'audio' | 'video';
24
30
  rtpParameters: any;
25
31
  participantId: string;
26
32
  }): Promise<{
@@ -1,4 +1,10 @@
1
1
  "use strict";
2
+ /**
3
+ * Mediasoup Manager
4
+ *
5
+ * Handles WebRTC transport, producer, and consumer management
6
+ * using the mediasoup-client library
7
+ */
2
8
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
9
  if (k2 === undefined) k2 = k;
4
10
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -53,32 +59,32 @@ class MediasoupManager {
53
59
  }
54
60
  sendDeviceRtpCapabilities(participantId) {
55
61
  this.participantId = participantId;
56
- this.socket.emit("device-rtp-capabilities", {
62
+ this.socket.emit('device-rtp-capabilities', {
57
63
  participantId,
58
64
  rtpCapabilities: this.device.rtpCapabilities,
59
65
  });
60
66
  }
61
67
  async createSendTransport(participantId) {
62
- const params = await this.createWebRtcTransport("send", participantId);
68
+ const params = await this.createWebRtcTransport('send', participantId);
63
69
  this.sendTransport = this.device.createSendTransport(params);
64
70
  this.connectSendTransport();
65
71
  }
66
72
  async createRecvTransport(participantId) {
67
- const params = await this.createWebRtcTransport("recv", participantId);
73
+ const params = await this.createWebRtcTransport('recv', participantId);
68
74
  this.recvTransport = this.device.createRecvTransport(params);
69
75
  this.connectRecvTransport();
70
76
  }
71
77
  connectSendTransport() {
72
- this.sendTransport?.on("connect", async ({ dtlsParameters }, callback, errback) => {
73
- this.socket.emit("connect-transport", { transportId: this.sendTransport.id, dtlsParameters }, (response) => {
78
+ this.sendTransport?.on('connect', async ({ dtlsParameters }, callback, errback) => {
79
+ this.socket.emit('connect-transport', { transportId: this.sendTransport.id, dtlsParameters }, (response) => {
74
80
  if (response.error)
75
81
  errback(new Error(response.error));
76
82
  else
77
83
  callback();
78
84
  });
79
85
  });
80
- this.sendTransport?.on("produce", async ({ kind, rtpParameters, appData, }, callback, errback) => {
81
- this.socket.emit("produce", {
86
+ this.sendTransport?.on('produce', async ({ kind, rtpParameters, appData, }, callback, errback) => {
87
+ this.socket.emit('produce', {
82
88
  transportId: this.sendTransport.id,
83
89
  kind,
84
90
  rtpParameters,
@@ -90,59 +96,56 @@ class MediasoupManager {
90
96
  callback({ id: response.producerId });
91
97
  });
92
98
  });
93
- // Handle transport connection state changes
94
- this.sendTransport?.on("connectionstatechange", (state) => {
95
- if (state === "failed" || state === "closed") {
96
- // Clear all producers since transport is dead
99
+ this.sendTransport?.on('connectionstatechange', (state) => {
100
+ if (state === 'failed' || state === 'closed') {
97
101
  this.producers.clear();
98
- // Emit event so parent SDK can recreate producers
99
- this.socket.emit("transport-failed", {
102
+ this.socket.emit('transport-failed', {
100
103
  participantId: this.participantId,
101
- direction: "send"
104
+ direction: 'send',
102
105
  });
103
106
  }
104
107
  });
105
108
  }
106
109
  connectRecvTransport() {
107
- this.recvTransport?.on("connect", async ({ dtlsParameters }, callback, errback) => {
108
- this.socket.emit("connect-transport", { transportId: this.recvTransport.id, dtlsParameters }, (response) => {
109
- if (response.error)
110
+ this.recvTransport?.on('connect', async ({ dtlsParameters }, callback, errback) => {
111
+ console.log(`🎧 [MediasoupManager] Recv transport connecting, DTLS params:`, {
112
+ transportId: this.recvTransport.id.substring(0, 8),
113
+ });
114
+ this.socket.emit('connect-transport', { transportId: this.recvTransport.id, dtlsParameters }, (response) => {
115
+ if (response.error) {
116
+ console.error(`🎧 [MediasoupManager] ❌ Recv transport connect failed:`, response.error);
110
117
  errback(new Error(response.error));
111
- else
118
+ }
119
+ else {
120
+ console.log(`🎧 [MediasoupManager] ✅ Recv transport connected`);
112
121
  callback();
122
+ }
113
123
  });
114
124
  });
115
- // Handle transport connection state changes
116
- this.recvTransport?.on("connectionstatechange", (state) => {
117
- if (state === "failed" || state === "closed") {
118
- // Consumers will be closed by server, SDK will handle via consumer.on('transportclose')
125
+ this.recvTransport?.on('connectionstatechange', (state) => {
126
+ console.log(`🎧 [MediasoupManager] Recv transport connection state changed: ${state}`);
127
+ if (state === 'failed' || state === 'closed') {
128
+ console.error(`🎧 [MediasoupManager] Recv transport ${state}`);
119
129
  }
120
130
  });
121
131
  }
122
132
  async produce(track, appData) {
123
133
  if (!this.sendTransport)
124
- throw new Error("Send transport not initialized");
125
- // Configure simulcast for video tracks for adaptive bitrate
134
+ throw new Error('Send transport not initialized');
126
135
  const produceOptions = { track, appData };
127
136
  if (track.kind === 'video') {
128
137
  produceOptions.encodings = [
129
- // Low quality layer - 100 kbps, good for poor connections
130
138
  { rid: 'r0', active: true, maxBitrate: 100000, scaleResolutionDownBy: 4 },
131
- // Medium quality layer - 300 kbps, balanced
132
139
  { rid: 'r1', active: true, maxBitrate: 300000, scaleResolutionDownBy: 2 },
133
- // High quality layer - 900 kbps, full resolution
134
- { rid: 'r2', active: true, maxBitrate: 900000, scaleResolutionDownBy: 1 }
140
+ { rid: 'r2', active: true, maxBitrate: 900000, scaleResolutionDownBy: 1 },
135
141
  ];
136
- // VP8 codec for simulcast support
137
142
  produceOptions.codecOptions = {
138
- videoGoogleStartBitrate: 1000
143
+ videoGoogleStartBitrate: 1000,
139
144
  };
140
145
  }
141
146
  const producer = await this.sendTransport.produce(produceOptions);
142
- // Handle producer events
143
147
  producer.on('transportclose', () => {
144
148
  this.producers.delete(producer.id);
145
- // The main SDK (index.ts) should handle recreation
146
149
  });
147
150
  producer.on('trackended', () => {
148
151
  producer.close();
@@ -153,17 +156,30 @@ class MediasoupManager {
153
156
  }
154
157
  async consume(data) {
155
158
  if (!this.recvTransport)
156
- throw new Error("Receive transport not set up");
159
+ throw new Error('Receive transport not set up');
160
+ console.log(`🎧 [MediasoupManager] Creating consumer for ${data.participantId.substring(0, 8)}`, {
161
+ consumerId: data.consumerId.substring(0, 8),
162
+ producerId: data.producerId.substring(0, 8),
163
+ kind: data.kind,
164
+ recvTransportId: this.recvTransport.id.substring(0, 8),
165
+ recvTransportConnectionState: this.recvTransport.connectionState,
166
+ });
157
167
  const consumer = await this.recvTransport.consume({
158
168
  id: data.consumerId,
159
169
  producerId: data.producerId,
160
170
  kind: data.kind,
161
171
  rtpParameters: data.rtpParameters,
162
172
  });
163
- // Handle consumer events
173
+ console.log(`🎧 [MediasoupManager] Consumer created for ${data.participantId.substring(0, 8)}`, {
174
+ consumerId: consumer.id.substring(0, 8),
175
+ trackKind: consumer.track.kind,
176
+ trackEnabled: consumer.track.enabled,
177
+ trackMuted: consumer.track.muted,
178
+ trackReadyState: consumer.track.readyState,
179
+ consumerPaused: consumer.paused,
180
+ });
164
181
  consumer.on('transportclose', () => {
165
182
  this.consumers.delete(consumer.id);
166
- // The main SDK (index.ts) should handle recreation
167
183
  });
168
184
  consumer.on('trackended', () => {
169
185
  consumer.close();
@@ -174,7 +190,7 @@ class MediasoupManager {
174
190
  }
175
191
  async resumeConsumer(consumerId) {
176
192
  return new Promise((resolve, reject) => {
177
- this.socket.emit("resume-consumer", { consumerId, participantId: this.participantId }, (response) => {
193
+ this.socket.emit('resume-consumer', { consumerId, participantId: this.participantId }, (response) => {
178
194
  if (response.error) {
179
195
  reject(new Error(response.error));
180
196
  }
@@ -186,23 +202,19 @@ class MediasoupManager {
186
202
  }
187
203
  async createWebRtcTransport(direction, participantId) {
188
204
  return new Promise((resolve, reject) => {
189
- // Set up listener for transport-created event
190
205
  const handleTransportCreated = (data) => {
191
206
  if (data.type === direction) {
192
- // Remove listener to prevent memory leaks
193
- this.socket.off("transport-created", handleTransportCreated);
207
+ this.socket.off('transport-created', handleTransportCreated);
194
208
  if (data.error) {
195
209
  return reject(new Error(data.error));
196
210
  }
197
211
  resolve(data.params);
198
212
  }
199
213
  };
200
- this.socket.on("transport-created", handleTransportCreated);
201
- // Emit the request
202
- this.socket.emit("create-transport", { direction, participantId });
203
- // Add timeout to prevent hanging forever
214
+ this.socket.on('transport-created', handleTransportCreated);
215
+ this.socket.emit('create-transport', { direction, participantId });
204
216
  setTimeout(() => {
205
- this.socket.off("transport-created", handleTransportCreated);
217
+ this.socket.off('transport-created', handleTransportCreated);
206
218
  reject(new Error(`Timeout waiting for ${direction} transport`));
207
219
  }, 10000);
208
220
  });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core module - Re-exports core SDK components
3
+ */
4
+ export * from './EventManager';
5
+ export * from './MediasoupManager';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Core module - Re-exports core SDK components
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ __exportStar(require("./EventManager"), exports);
21
+ __exportStar(require("./MediasoupManager"), exports);
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { EventManager } from "./EventManager";
2
- import { SpatialAudioOptions } from "./SpatialAudioManager";
1
+ import { EventManager } from "./core/EventManager";
2
+ import { SpatialAudioOptions } from "./channels/spatial/SpatialAudioChannel";
3
3
  import { Direction, MediaState, OdysseyEvent, Participant, Position, RoomJoinedData } from "./types";
4
4
  export declare class OdysseySpatialComms extends EventManager {
5
5
  private socket;
package/dist/index.js CHANGED
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OdysseySpatialComms = void 0;
4
4
  const socket_io_client_1 = require("socket.io-client");
5
- const EventManager_1 = require("./EventManager");
6
- const MediasoupManager_1 = require("./MediasoupManager");
7
- const SpatialAudioManager_1 = require("./SpatialAudioManager");
5
+ const EventManager_1 = require("./core/EventManager");
6
+ const MediasoupManager_1 = require("./core/MediasoupManager");
7
+ const SpatialAudioChannel_1 = require("./channels/spatial/SpatialAudioChannel");
8
8
  class OdysseySpatialComms extends EventManager_1.EventManager {
9
9
  constructor(serverUrl, spatialOptions) {
10
10
  super(); // Initialize the EventEmitter base class
@@ -14,7 +14,7 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
14
14
  transports: ["websocket"],
15
15
  });
16
16
  this.mediasoupManager = new MediasoupManager_1.MediasoupManager(this.socket);
17
- this.spatialAudioManager = new SpatialAudioManager_1.SpatialAudioManager(spatialOptions);
17
+ this.spatialAudioManager = new SpatialAudioChannel_1.SpatialAudioManager(spatialOptions);
18
18
  // Set max listeners to prevent warning
19
19
  this.setMaxListeners(50);
20
20
  this.listenForEvents();
@@ -211,6 +211,15 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
211
211
  pan: spatialData?.pan,
212
212
  dxLocal: spatialData?.dxLocal,
213
213
  };
214
+ // ========== DEBUG: SDK SENDING TO SERVER ==========
215
+ console.log("📤 [SDK->Server] updatePosition:", {
216
+ participantId: updateData.participantId,
217
+ position: updateData.position,
218
+ direction: updateData.direction,
219
+ rot: updateData.rot,
220
+ pan: updateData.pan,
221
+ dxLocal: updateData.dxLocal,
222
+ });
214
223
  this.socket.emit("update-position", updateData);
215
224
  }
216
225
  }
@@ -229,6 +238,13 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
229
238
  this.spatialAudioManager.setListenerPosition(position, orientation);
230
239
  }
231
240
  setListenerFromLSD(listenerPos, cameraPos, lookAtPos, rot) {
241
+ // ========== DEBUG: LISTENER POSITION UPDATE ==========
242
+ console.log("🎧 [SDK] setListenerFromLSD:", {
243
+ listenerPos,
244
+ cameraPos,
245
+ lookAtPos,
246
+ rot,
247
+ });
232
248
  this.spatialAudioManager.setListenerFromLSD(listenerPos, cameraPos, lookAtPos, rot);
233
249
  }
234
250
  listenForEvents() {
@@ -383,11 +399,19 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
383
399
  participant.consumers.set(consumer.id, consumer);
384
400
  if (track.kind === "audio") {
385
401
  participant.audioTrack = track;
402
+ console.log(`🎧 [SDK] Received audio consumer for ${participant.participantId.substring(0, 8)}`, {
403
+ consumerId: consumer.id.substring(0, 8),
404
+ trackEnabled: track.enabled,
405
+ trackMuted: track.muted,
406
+ trackReadyState: track.readyState,
407
+ consumerPaused: consumer.paused,
408
+ });
386
409
  // CRITICAL: Do NOT setup spatial audio for local participant (yourself)
387
410
  // This prevents hearing your own microphone (loopback)
388
411
  const isLocalParticipant = participant.participantId ===
389
412
  this.localParticipant?.participantId;
390
413
  if (isLocalParticipant) {
414
+ console.log(`🎧 [SDK] Skipping audio setup for local participant (prevent loopback)`);
391
415
  // Do NOT connect this audio to Web Audio API
392
416
  return; // Exit early to prevent any audio processing
393
417
  }
@@ -395,18 +419,20 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
395
419
  // Check if participant is in a huddle (non-spatial channel)
396
420
  const participantChannel = participant.currentChannel || "spatial";
397
421
  const isInHuddle = participantChannel !== "spatial";
422
+ console.log(`🎧 [SDK] Setting up spatial audio for ${participant.participantId.substring(0, 8)}, huddle: ${isInHuddle}`);
398
423
  // Setup spatial audio - bypass 3D positioning for huddle members
399
424
  await this.spatialAudioManager.setupSpatialAudioForParticipant(participant.participantId, track, isInHuddle // Bypass spatialization if in huddle
400
425
  );
401
426
  }
402
427
  // NOW resume the consumer after audio pipeline is ready
428
+ console.log(`🎧 [SDK] Resuming consumer ${consumer.id.substring(0, 8)}...`);
403
429
  this.mediasoupManager
404
430
  .resumeConsumer(consumer.id)
405
431
  .then(() => {
406
- // Consumer resumed successfully
432
+ console.log(`🎧 [SDK] ✅ Consumer ${consumer.id.substring(0, 8)} resumed successfully`);
407
433
  })
408
- .catch(() => {
409
- // Failed to resume consumer - will be handled by transport recovery
434
+ .catch((err) => {
435
+ console.error(`🎧 [SDK] ❌ Failed to resume consumer ${consumer.id.substring(0, 8)}:`, err);
410
436
  });
411
437
  }
412
438
  else if (track.kind === "video") {
@@ -436,8 +462,16 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
436
462
  }
437
463
  });
438
464
  this.socket.on("participant-position-updated", (data) => {
439
- // DEBUG: Log position update received from socket
440
- console.log(`[SDK-SOCKET] id=${data.participantId.substring(0, 8)} pos=(${data.position.x.toFixed(1)},${data.position.y.toFixed(1)},${data.position.z.toFixed(1)}) rot=(${data.rot?.x?.toFixed(1)},${data.rot?.y?.toFixed(1)},${data.rot?.z?.toFixed(1)})`);
465
+ // ========== DEBUG: SDK RECEIVED FROM SERVER ==========
466
+ console.log("📥 [SDK<-Server] participant-position-updated:", {
467
+ participantId: data.participantId,
468
+ position: data.position,
469
+ direction: data.direction,
470
+ rot: data.rot,
471
+ pan: data.pan,
472
+ dxLocal: data.dxLocal,
473
+ currentChannel: data.currentChannel,
474
+ });
441
475
  const participant = this.room?.participants.get(data.participantId);
442
476
  if (participant) {
443
477
  participant.position = data.position;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Odyssey Mediasoup SDK - Main Entry Point
3
+ *
4
+ * A comprehensive WebRTC SDK for real-time audio/video communication
5
+ * with spatial audio and ML-powered noise suppression.
6
+ *
7
+ * @module @odyssey/mediasoup-sdk
8
+ */
9
+ export type { Position, Direction, Rotation, ListenerRight, UnrealPosition, StandardPosition, } from '../types/position';
10
+ export type { Participant, MediaState, ParticipantSnapshot, } from '../types/participant';
11
+ export type { RoomJoinedEvent, ConsumerCreatedEvent, ConsumerClosedEvent, ConsumerPausedEvent, ConsumerResumedEvent, ParticipantJoinedEvent, ParticipantLeftEvent, ParticipantPositionEvent, MuteStateChangedEvent, HuddleInviteReceivedEvent, HuddleResponseEvent, OdysseyEvent, OdysseyEventMap, } from '../types/events';
12
+ export type { Room, RoomJoinedData, JoinRoomData, ConsumerCreatedData, TransportOptions, ProducerOptions, } from '../types/room';
13
+ export { getDistanceBetween, getHorizontalDistance, isWithinRange, } from '../utils/spatial/distance-calc';
14
+ export { calculateLogarithmicGain, DEFAULT_GAIN_CONFIG, type GainConfig, } from '../utils/spatial/gain-calc';
15
+ export { calculateListenerRight, calculatePanFromPositions, panValueToPanning, type Panning, } from '../utils/spatial/pan-calc';
16
+ export { computeHeadPosition, parseBodyHeight, getVectorFromListener, } from '../utils/spatial/head-position';
17
+ export { getListenerRightFromRotation, calculateListenerOrientation, type ListenerOrientation, } from '../utils/spatial/listener-calc';
18
+ export { computeAzimuthFromPositions, calculateAngleToSource, } from '../utils/spatial/angle-calc';
19
+ export { normalizePositionUnits, metersToCentimeters, centimetersToMeters, isLikelyCentimeters, } from '../utils/position/normalize';
20
+ export { PositionSnapCache, snapPositionSimple, SNAP_CONFIG, type SnapConfig, } from '../utils/position/snap';
21
+ export { unrealToStandard, standardToUnreal, autoConvertToStandard, } from '../utils/position/coordinates';
22
+ export { PanSmoother, DEFAULT_PAN_SMOOTHER_OPTIONS, type PanSmootherOptions, } from '../utils/smoothing/pan-smoothing';
23
+ export { applyGainSmooth, applyStereoPanSmooth, GainTracker, } from '../utils/smoothing/gain-smoothing';
24
+ export { calculateClarityScore, calculateProximityWeight, normalizeVector, } from '../utils/audio/clarity-score';
25
+ export { calculateAdaptiveHighpass, createVoiceFilterChain, } from '../utils/audio/voice-filter';
26
+ export { HuddleChannel, type HuddleChannelConfig, } from '../channels/huddle/HuddleChannel';
27
+ export { SPATIAL_CHANNEL_ID, isHuddleChannel, type HuddleInvite, type HuddleResponse, type HuddleAcceptResponse, type HuddleRejectResponse, } from '../channels/huddle/HuddleTypes';
28
+ export { SpatialAudioChannel, type SpatialAudioConfig, } from '../channels/spatial/SpatialAudioChannel';
29
+ export { DEFAULT_SPATIAL_CONFIG, DEFAULT_DENOISER_OPTIONS, type SpatialDistanceConfig, type DenoiserOptions, type ParticipantAudioNodes, type ListenerState, } from '../channels/spatial/SpatialAudioTypes';
30
+ export { createMasterChain, createFilterChain, connectFilterChain, createLimiter, createMonoDownmixChain, connectMonoDownmixChain, DEFAULT_PIPELINE_CONFIG, type AudioPipelineConfig, type MasterAudioChain, type ParticipantFilterChain, type MonoDownmixChain, } from '../audio/AudioPipeline';
31
+ export { createPanner, createStereoPanner, createGain, createAnalyser, createHighpassFilter, createLowpassFilter, createPeakingFilter, createCompressor, createMediaStreamSource, DEFAULT_PANNER_CONFIG, type PannerConfig, type HighpassConfig, type LowpassConfig, type PeakingConfig, type CompressorConfig, } from '../audio/AudioNodeFactory';
32
+ export { MLNoiseSuppressor } from '../audio/MLNoiseSuppressor';
33
+ export { EventManager } from '../core/EventManager';
34
+ export { MediasoupManager } from '../core/MediasoupManager';
35
+ export declare const SDK_VERSION = "2.0.0";
36
+ export declare const SDK_NAME = "Odyssey Mediasoup SDK";