@newgameplusinc/odyssey-audio-video-sdk-dev 1.0.264 → 1.0.266
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.
|
@@ -27,6 +27,10 @@ export declare class SpatialAudioChannel {
|
|
|
27
27
|
private positionCache;
|
|
28
28
|
private panSmoother;
|
|
29
29
|
private isMasterMuted;
|
|
30
|
+
private lastGainValues;
|
|
31
|
+
private lastPanValues;
|
|
32
|
+
private readonly GAIN_CHANGE_THRESHOLD;
|
|
33
|
+
private readonly PAN_CHANGE_THRESHOLD;
|
|
30
34
|
private mlNoiseSuppressor;
|
|
31
35
|
private noiseSuppressionMode;
|
|
32
36
|
constructor(config?: SpatialAudioConfig);
|
|
@@ -40,6 +44,7 @@ export declare class SpatialAudioChannel {
|
|
|
40
44
|
setupParticipant(participantId: string, track: MediaStreamTrack, bypassSpatialization?: boolean): Promise<void>;
|
|
41
45
|
/**
|
|
42
46
|
* Update spatial audio for a participant
|
|
47
|
+
* OPTIMIZED: Only updates gain/pan when values change significantly
|
|
43
48
|
*/
|
|
44
49
|
updateSpatialAudio(participantId: string, position: Position, direction?: {
|
|
45
50
|
x: number;
|
|
@@ -29,6 +29,11 @@ class SpatialAudioChannel {
|
|
|
29
29
|
initialized: false,
|
|
30
30
|
};
|
|
31
31
|
this.isMasterMuted = false;
|
|
32
|
+
// Gain/Pan caching to prevent unnecessary audio parameter updates
|
|
33
|
+
this.lastGainValues = new Map();
|
|
34
|
+
this.lastPanValues = new Map();
|
|
35
|
+
this.GAIN_CHANGE_THRESHOLD = 0.02; // 2% change required to update
|
|
36
|
+
this.PAN_CHANGE_THRESHOLD = 0.03; // 3% change required to update
|
|
32
37
|
// ML Noise Suppression
|
|
33
38
|
this.mlNoiseSuppressor = null;
|
|
34
39
|
this.noiseSuppressionMode = 'none';
|
|
@@ -124,9 +129,13 @@ class SpatialAudioChannel {
|
|
|
124
129
|
dynamicLowpass,
|
|
125
130
|
stream,
|
|
126
131
|
});
|
|
132
|
+
// Initialize gain cache for this participant at full volume
|
|
133
|
+
this.lastGainValues.set(participantId, 1.0);
|
|
134
|
+
this.lastPanValues.set(participantId, 0);
|
|
127
135
|
}
|
|
128
136
|
/**
|
|
129
137
|
* Update spatial audio for a participant
|
|
138
|
+
* OPTIMIZED: Only updates gain/pan when values change significantly
|
|
130
139
|
*/
|
|
131
140
|
updateSpatialAudio(participantId, position, direction) {
|
|
132
141
|
const nodes = this.participantNodes.get(participantId);
|
|
@@ -140,7 +149,11 @@ class SpatialAudioChannel {
|
|
|
140
149
|
const distance = (0, distance_calc_1.getDistanceBetween)(listenerPos, speakerHead);
|
|
141
150
|
// Hard cutoff at max distance
|
|
142
151
|
if (distance >= this.distanceConfig.maxDistance) {
|
|
143
|
-
|
|
152
|
+
const lastGain = this.lastGainValues.get(participantId) ?? 1.0;
|
|
153
|
+
if (lastGain > 0.01) {
|
|
154
|
+
(0, gain_smoothing_1.applyGainSmooth)(nodes.gain, 0, this.audioContext, 0.1);
|
|
155
|
+
this.lastGainValues.set(participantId, 0);
|
|
156
|
+
}
|
|
144
157
|
return;
|
|
145
158
|
}
|
|
146
159
|
// Calculate pan
|
|
@@ -153,11 +166,21 @@ class SpatialAudioChannel {
|
|
|
153
166
|
maxDistance: this.distanceConfig.maxDistance,
|
|
154
167
|
});
|
|
155
168
|
const gainValue = gainPercent / 100;
|
|
156
|
-
//
|
|
169
|
+
// Calculate pan value
|
|
157
170
|
const panValue = (panning.right - panning.left) / 100;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
(
|
|
171
|
+
// OPTIMIZATION: Only apply pan if it changed significantly
|
|
172
|
+
const lastPan = this.lastPanValues.get(participantId) ?? 0;
|
|
173
|
+
if (Math.abs(panValue - lastPan) > this.PAN_CHANGE_THRESHOLD) {
|
|
174
|
+
(0, gain_smoothing_1.applyStereoPanSmooth)(nodes.stereoPanner, panValue, this.audioContext, 0.08);
|
|
175
|
+
this.lastPanValues.set(participantId, panValue);
|
|
176
|
+
}
|
|
177
|
+
// OPTIMIZATION: Only apply gain if it changed significantly
|
|
178
|
+
// This prevents continuous setTargetAtTime calls which cause audio instability
|
|
179
|
+
const lastGain = this.lastGainValues.get(participantId) ?? 1.0;
|
|
180
|
+
if (Math.abs(gainValue - lastGain) > this.GAIN_CHANGE_THRESHOLD) {
|
|
181
|
+
(0, gain_smoothing_1.applyGainSmooth)(nodes.gain, gainValue, this.audioContext, 0.15);
|
|
182
|
+
this.lastGainValues.set(participantId, gainValue);
|
|
183
|
+
}
|
|
161
184
|
}
|
|
162
185
|
/**
|
|
163
186
|
* Set listener position from LSD data
|
|
@@ -316,6 +339,8 @@ class SpatialAudioChannel {
|
|
|
316
339
|
this.participantNodes.delete(participantId);
|
|
317
340
|
this.panSmoother.clear(participantId);
|
|
318
341
|
this.positionCache.clear(participantId);
|
|
342
|
+
this.lastGainValues.delete(participantId);
|
|
343
|
+
this.lastPanValues.delete(participantId);
|
|
319
344
|
}
|
|
320
345
|
}
|
|
321
346
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,10 @@ export declare class OdysseySpatialComms extends EventManager {
|
|
|
68
68
|
dxLocal?: number;
|
|
69
69
|
}): void;
|
|
70
70
|
updateMediaState(mediaState: MediaState): void;
|
|
71
|
+
/**
|
|
72
|
+
* Stop screenshare - closes producer and notifies all consumers
|
|
73
|
+
*/
|
|
74
|
+
stopScreenShare(): Promise<void>;
|
|
71
75
|
setListenerPosition(position: Position, orientation: {
|
|
72
76
|
forwardX: number;
|
|
73
77
|
forwardY: number;
|
package/dist/index.js
CHANGED
|
@@ -225,6 +225,34 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Stop screenshare - closes producer and notifies all consumers
|
|
230
|
+
*/
|
|
231
|
+
async stopScreenShare() {
|
|
232
|
+
if (!this.localParticipant || !this.room)
|
|
233
|
+
return;
|
|
234
|
+
// Close local screenshare track
|
|
235
|
+
const screenshareTrack = this.localParticipant.screenshareTrack;
|
|
236
|
+
if (screenshareTrack) {
|
|
237
|
+
screenshareTrack.stop();
|
|
238
|
+
this.localParticipant.screenshareTrack = null;
|
|
239
|
+
}
|
|
240
|
+
// Close local screenshare producer
|
|
241
|
+
for (const [producerId, producer] of this.localParticipant.producers) {
|
|
242
|
+
if (producer.appData?.isScreenshare) {
|
|
243
|
+
producer.close();
|
|
244
|
+
this.localParticipant.producers.delete(producerId);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Notify server to close screenshare and notify consumers
|
|
249
|
+
return new Promise((resolve) => {
|
|
250
|
+
this.socket.emit("stop-screenshare", { participantId: this.localParticipant.participantId }, () => {
|
|
251
|
+
this.localParticipant.mediaState.sharescreen = false;
|
|
252
|
+
resolve();
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
228
256
|
setListenerPosition(position, orientation) {
|
|
229
257
|
this.spatialAudioManager.setListenerPosition(position, orientation);
|
|
230
258
|
}
|
package/package.json
CHANGED