@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.
- package/README.md +45 -1
- package/dist/audio/AudioNodeFactory.d.ts +130 -0
- package/dist/audio/AudioNodeFactory.js +158 -0
- package/dist/audio/AudioPipeline.d.ts +89 -0
- package/dist/audio/AudioPipeline.js +138 -0
- package/dist/{MLNoiseSuppressor.d.ts → audio/MLNoiseSuppressor.d.ts} +7 -7
- package/dist/{MLNoiseSuppressor.js → audio/MLNoiseSuppressor.js} +19 -52
- package/dist/audio/index.d.ts +6 -0
- package/dist/audio/index.js +22 -0
- package/dist/channels/huddle/HuddleChannel.d.ts +87 -0
- package/dist/channels/huddle/HuddleChannel.js +152 -0
- package/dist/channels/huddle/HuddleTypes.d.ts +85 -0
- package/dist/channels/huddle/HuddleTypes.js +25 -0
- package/dist/channels/huddle/index.d.ts +5 -0
- package/dist/channels/huddle/index.js +21 -0
- package/dist/channels/index.d.ts +5 -0
- package/dist/channels/index.js +21 -0
- package/dist/channels/spatial/SpatialAudioChannel.d.ts +144 -0
- package/dist/channels/spatial/SpatialAudioChannel.js +476 -0
- package/dist/channels/spatial/SpatialAudioTypes.d.ts +85 -0
- package/dist/channels/spatial/SpatialAudioTypes.js +42 -0
- package/dist/channels/spatial/index.d.ts +5 -0
- package/dist/channels/spatial/index.js +21 -0
- package/dist/{EventManager.d.ts → core/EventManager.d.ts} +4 -2
- package/dist/{EventManager.js → core/EventManager.js} +5 -3
- package/dist/{MediasoupManager.d.ts → core/MediasoupManager.d.ts} +10 -4
- package/dist/{MediasoupManager.js → core/MediasoupManager.js} +56 -44
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +21 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +43 -9
- package/dist/sdk/index.d.ts +36 -0
- package/dist/sdk/index.js +121 -0
- package/dist/types/events.d.ts +154 -0
- package/dist/{types.js → types/events.js} +3 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.js +23 -0
- package/dist/types/participant.d.ts +65 -0
- package/dist/types/participant.js +5 -0
- package/dist/types/position.d.ts +47 -0
- package/dist/types/position.js +9 -0
- package/dist/types/room.d.ts +82 -0
- package/dist/types/room.js +5 -0
- package/dist/utils/audio/clarity-score.d.ts +33 -0
- package/dist/utils/audio/clarity-score.js +81 -0
- package/dist/utils/audio/index.d.ts +5 -0
- package/dist/utils/audio/index.js +21 -0
- package/dist/utils/audio/voice-filter.d.ts +30 -0
- package/dist/utils/audio/voice-filter.js +70 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +23 -0
- package/dist/utils/position/coordinates.d.ts +37 -0
- package/dist/utils/position/coordinates.js +61 -0
- package/dist/utils/position/index.d.ts +6 -0
- package/dist/utils/position/index.js +22 -0
- package/dist/utils/position/normalize.d.ts +37 -0
- package/dist/utils/position/normalize.js +78 -0
- package/dist/utils/position/snap.d.ts +51 -0
- package/dist/utils/position/snap.js +81 -0
- package/dist/utils/smoothing/gain-smoothing.d.ts +45 -0
- package/dist/utils/smoothing/gain-smoothing.js +77 -0
- package/dist/utils/smoothing/index.d.ts +5 -0
- package/dist/utils/smoothing/index.js +21 -0
- package/dist/utils/smoothing/pan-smoothing.d.ts +43 -0
- package/dist/utils/smoothing/pan-smoothing.js +85 -0
- package/dist/utils/spatial/angle-calc.d.ts +24 -0
- package/dist/utils/spatial/angle-calc.js +69 -0
- package/dist/utils/spatial/distance-calc.d.ts +33 -0
- package/dist/utils/spatial/distance-calc.js +48 -0
- package/dist/utils/spatial/gain-calc.d.ts +37 -0
- package/dist/utils/spatial/gain-calc.js +52 -0
- package/dist/utils/spatial/head-position.d.ts +32 -0
- package/dist/utils/spatial/head-position.js +76 -0
- package/dist/utils/spatial/index.d.ts +9 -0
- package/dist/utils/spatial/index.js +25 -0
- package/dist/utils/spatial/listener-calc.d.ts +28 -0
- package/dist/utils/spatial/listener-calc.js +74 -0
- package/dist/utils/spatial/pan-calc.d.ts +48 -0
- package/dist/utils/spatial/pan-calc.js +80 -0
- package/package.json +1 -1
- package/dist/SpatialAudioManager.d.ts +0 -271
- package/dist/SpatialAudioManager.js +0 -1512
- package/dist/types.d.ts +0 -73
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audio utilities - Re-exports all audio utility functions
|
|
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("./clarity-score"), exports);
|
|
21
|
+
__exportStar(require("./voice-filter"), exports);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice Filter Calculations
|
|
3
|
+
*
|
|
4
|
+
* Functions for adaptive voice filtering
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Calculate adaptive highpass frequency based on voice characteristics
|
|
8
|
+
* Analyzes audio spectrum and returns optimal highpass cutoff (85-300Hz)
|
|
9
|
+
*
|
|
10
|
+
* @param frequencyData Frequency data from AnalyserNode
|
|
11
|
+
* @param sampleRate Audio sample rate
|
|
12
|
+
* @returns Optimal highpass frequency
|
|
13
|
+
*/
|
|
14
|
+
export declare function calculateAdaptiveHighpass(frequencyData: Uint8Array, sampleRate: number): number;
|
|
15
|
+
/**
|
|
16
|
+
* Voice filter chain configuration
|
|
17
|
+
*/
|
|
18
|
+
export interface VoiceFilterChain {
|
|
19
|
+
highpass: BiquadFilterNode;
|
|
20
|
+
lowpass: BiquadFilterNode;
|
|
21
|
+
voiceBand: BiquadFilterNode;
|
|
22
|
+
dynamicLowpass: BiquadFilterNode;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a voice-optimized filter chain
|
|
26
|
+
*
|
|
27
|
+
* @param audioContext AudioContext
|
|
28
|
+
* @returns Filter chain nodes
|
|
29
|
+
*/
|
|
30
|
+
export declare function createVoiceFilterChain(audioContext: AudioContext): VoiceFilterChain;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Voice Filter Calculations
|
|
4
|
+
*
|
|
5
|
+
* Functions for adaptive voice filtering
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.calculateAdaptiveHighpass = calculateAdaptiveHighpass;
|
|
9
|
+
exports.createVoiceFilterChain = createVoiceFilterChain;
|
|
10
|
+
/**
|
|
11
|
+
* Calculate adaptive highpass frequency based on voice characteristics
|
|
12
|
+
* Analyzes audio spectrum and returns optimal highpass cutoff (85-300Hz)
|
|
13
|
+
*
|
|
14
|
+
* @param frequencyData Frequency data from AnalyserNode
|
|
15
|
+
* @param sampleRate Audio sample rate
|
|
16
|
+
* @returns Optimal highpass frequency
|
|
17
|
+
*/
|
|
18
|
+
function calculateAdaptiveHighpass(frequencyData, sampleRate) {
|
|
19
|
+
const bufferLength = frequencyData.length;
|
|
20
|
+
const nyquist = sampleRate / 2;
|
|
21
|
+
const binWidth = nyquist / bufferLength;
|
|
22
|
+
let weightedSum = 0;
|
|
23
|
+
let totalEnergy = 0;
|
|
24
|
+
const maxBin = Math.floor(500 / binWidth); // Only analyze up to 500Hz
|
|
25
|
+
for (let i = 0; i < Math.min(maxBin, bufferLength); i++) {
|
|
26
|
+
const frequency = i * binWidth;
|
|
27
|
+
const magnitude = frequencyData[i] / 255.0;
|
|
28
|
+
weightedSum += frequency * magnitude;
|
|
29
|
+
totalEnergy += magnitude;
|
|
30
|
+
}
|
|
31
|
+
if (totalEnergy > 0.01) {
|
|
32
|
+
const centroid = weightedSum / totalEnergy;
|
|
33
|
+
// Map centroid to highpass frequency (85-300Hz)
|
|
34
|
+
// Lower centroid = deeper voice = use lower highpass (preserve bass)
|
|
35
|
+
// Higher centroid = higher voice = use higher highpass (remove mud)
|
|
36
|
+
return Math.max(85, Math.min(300, 85 + (centroid - 100) * 0.5));
|
|
37
|
+
}
|
|
38
|
+
// Default frequency if no significant energy
|
|
39
|
+
return 100;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a voice-optimized filter chain
|
|
43
|
+
*
|
|
44
|
+
* @param audioContext AudioContext
|
|
45
|
+
* @returns Filter chain nodes
|
|
46
|
+
*/
|
|
47
|
+
function createVoiceFilterChain(audioContext) {
|
|
48
|
+
// HIGHPASS FILTER: Remove low-frequency rumble and plosives
|
|
49
|
+
const highpass = audioContext.createBiquadFilter();
|
|
50
|
+
highpass.type = 'highpass';
|
|
51
|
+
highpass.frequency.value = 100; // Cut below 100Hz
|
|
52
|
+
highpass.Q.value = 0.5; // Gentle slope
|
|
53
|
+
// LOWPASS FILTER: Remove high-frequency hiss
|
|
54
|
+
const lowpass = audioContext.createBiquadFilter();
|
|
55
|
+
lowpass.type = 'lowpass';
|
|
56
|
+
lowpass.frequency.value = 10000; // Cut above 10kHz
|
|
57
|
+
lowpass.Q.value = 0.5;
|
|
58
|
+
// VOICE BAND EMPHASIS (disabled by default - can cause resonance)
|
|
59
|
+
const voiceBand = audioContext.createBiquadFilter();
|
|
60
|
+
voiceBand.type = 'peaking';
|
|
61
|
+
voiceBand.frequency.value = 180;
|
|
62
|
+
voiceBand.Q.value = 0.5;
|
|
63
|
+
voiceBand.gain.value = 0; // Disabled
|
|
64
|
+
// DYNAMIC LOWPASS for high-frequency control
|
|
65
|
+
const dynamicLowpass = audioContext.createBiquadFilter();
|
|
66
|
+
dynamicLowpass.type = 'lowpass';
|
|
67
|
+
dynamicLowpass.frequency.value = 12000;
|
|
68
|
+
dynamicLowpass.Q.value = 0.5;
|
|
69
|
+
return { highpass, lowpass, voiceBand, dynamicLowpass };
|
|
70
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Utils module - Re-exports all utility functions
|
|
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("./spatial"), exports);
|
|
21
|
+
__exportStar(require("./position"), exports);
|
|
22
|
+
__exportStar(require("./smoothing"), exports);
|
|
23
|
+
__exportStar(require("./audio"), exports);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinate System Conversions
|
|
3
|
+
*
|
|
4
|
+
* Converts between Unreal Engine and Standard coordinate systems
|
|
5
|
+
*
|
|
6
|
+
* Unreal Engine: X=forward, Y=right, Z=up (centimeters)
|
|
7
|
+
* Standard/WebAudio: X=right, Y=up, Z=forward (meters)
|
|
8
|
+
*/
|
|
9
|
+
import { Position } from '../../types/position';
|
|
10
|
+
/**
|
|
11
|
+
* Convert Unreal Engine coordinates to Standard coordinates
|
|
12
|
+
*
|
|
13
|
+
* Unreal: X=forward, Y=right, Z=up (centimeters)
|
|
14
|
+
* Standard: X=right, Y=up, Z=forward (meters)
|
|
15
|
+
*
|
|
16
|
+
* @param unreal Position in Unreal coordinates
|
|
17
|
+
* @returns Position in Standard coordinates (meters)
|
|
18
|
+
*/
|
|
19
|
+
export declare function unrealToStandard(unreal: Position): Position;
|
|
20
|
+
/**
|
|
21
|
+
* Convert Standard coordinates to Unreal Engine coordinates
|
|
22
|
+
*
|
|
23
|
+
* Standard: X=right, Y=up, Z=forward (meters)
|
|
24
|
+
* Unreal: X=forward, Y=right, Z=up (centimeters)
|
|
25
|
+
*
|
|
26
|
+
* @param standard Position in Standard coordinates
|
|
27
|
+
* @returns Position in Unreal coordinates (centimeters)
|
|
28
|
+
*/
|
|
29
|
+
export declare function standardToUnreal(standard: Position): Position;
|
|
30
|
+
/**
|
|
31
|
+
* Auto-detect and convert to Standard coordinates
|
|
32
|
+
* Assumes Unreal if values > 50 (likely centimeters)
|
|
33
|
+
*
|
|
34
|
+
* @param position Position to convert
|
|
35
|
+
* @returns Position in Standard coordinates (meters)
|
|
36
|
+
*/
|
|
37
|
+
export declare function autoConvertToStandard(position: Position): Position;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Coordinate System Conversions
|
|
4
|
+
*
|
|
5
|
+
* Converts between Unreal Engine and Standard coordinate systems
|
|
6
|
+
*
|
|
7
|
+
* Unreal Engine: X=forward, Y=right, Z=up (centimeters)
|
|
8
|
+
* Standard/WebAudio: X=right, Y=up, Z=forward (meters)
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.unrealToStandard = unrealToStandard;
|
|
12
|
+
exports.standardToUnreal = standardToUnreal;
|
|
13
|
+
exports.autoConvertToStandard = autoConvertToStandard;
|
|
14
|
+
/**
|
|
15
|
+
* Convert Unreal Engine coordinates to Standard coordinates
|
|
16
|
+
*
|
|
17
|
+
* Unreal: X=forward, Y=right, Z=up (centimeters)
|
|
18
|
+
* Standard: X=right, Y=up, Z=forward (meters)
|
|
19
|
+
*
|
|
20
|
+
* @param unreal Position in Unreal coordinates
|
|
21
|
+
* @returns Position in Standard coordinates (meters)
|
|
22
|
+
*/
|
|
23
|
+
function unrealToStandard(unreal) {
|
|
24
|
+
return {
|
|
25
|
+
x: unreal.y / 100, // Unreal Y (right) → Standard X (right), cm → m
|
|
26
|
+
y: unreal.z / 100, // Unreal Z (up) → Standard Y (up), cm → m
|
|
27
|
+
z: unreal.x / 100, // Unreal X (forward) → Standard Z (forward), cm → m
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Convert Standard coordinates to Unreal Engine coordinates
|
|
32
|
+
*
|
|
33
|
+
* Standard: X=right, Y=up, Z=forward (meters)
|
|
34
|
+
* Unreal: X=forward, Y=right, Z=up (centimeters)
|
|
35
|
+
*
|
|
36
|
+
* @param standard Position in Standard coordinates
|
|
37
|
+
* @returns Position in Unreal coordinates (centimeters)
|
|
38
|
+
*/
|
|
39
|
+
function standardToUnreal(standard) {
|
|
40
|
+
return {
|
|
41
|
+
x: standard.z * 100, // Standard Z (forward) → Unreal X (forward), m → cm
|
|
42
|
+
y: standard.x * 100, // Standard X (right) → Unreal Y (right), m → cm
|
|
43
|
+
z: standard.y * 100, // Standard Y (up) → Unreal Z (up), m → cm
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Auto-detect and convert to Standard coordinates
|
|
48
|
+
* Assumes Unreal if values > 50 (likely centimeters)
|
|
49
|
+
*
|
|
50
|
+
* @param position Position to convert
|
|
51
|
+
* @returns Position in Standard coordinates (meters)
|
|
52
|
+
*/
|
|
53
|
+
function autoConvertToStandard(position) {
|
|
54
|
+
const maxAxis = Math.max(Math.abs(position.x), Math.abs(position.y), Math.abs(position.z));
|
|
55
|
+
if (maxAxis > 50) {
|
|
56
|
+
// Likely Unreal coordinates (centimeters)
|
|
57
|
+
return unrealToStandard(position);
|
|
58
|
+
}
|
|
59
|
+
// Already in meters, assume Standard
|
|
60
|
+
return { ...position };
|
|
61
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Position utilities - Re-exports all position functions
|
|
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("./normalize"), exports);
|
|
21
|
+
__exportStar(require("./snap"), exports);
|
|
22
|
+
__exportStar(require("./coordinates"), exports);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Position Normalization
|
|
3
|
+
*
|
|
4
|
+
* Functions for normalizing position units (cm to meters, etc.)
|
|
5
|
+
*/
|
|
6
|
+
import { Position } from '../../types/position';
|
|
7
|
+
/**
|
|
8
|
+
* Normalize position units to meters
|
|
9
|
+
* Detects if values are likely in centimeters and converts
|
|
10
|
+
*
|
|
11
|
+
* @param position Position to normalize
|
|
12
|
+
* @param unit Force unit interpretation: 'auto' | 'meters' | 'centimeters'
|
|
13
|
+
* @returns Position in meters
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizePositionUnits(position: Position, unit?: 'auto' | 'meters' | 'centimeters'): Position;
|
|
16
|
+
/**
|
|
17
|
+
* Convert meters to centimeters
|
|
18
|
+
*
|
|
19
|
+
* @param position Position in meters
|
|
20
|
+
* @returns Position in centimeters
|
|
21
|
+
*/
|
|
22
|
+
export declare function metersToCentimeters(position: Position): Position;
|
|
23
|
+
/**
|
|
24
|
+
* Convert centimeters to meters
|
|
25
|
+
*
|
|
26
|
+
* @param position Position in centimeters
|
|
27
|
+
* @returns Position in meters
|
|
28
|
+
*/
|
|
29
|
+
export declare function centimetersToMeters(position: Position): Position;
|
|
30
|
+
/**
|
|
31
|
+
* Check if position values are likely in centimeters
|
|
32
|
+
*
|
|
33
|
+
* @param position Position to check
|
|
34
|
+
* @param threshold Threshold for detection (default: 50)
|
|
35
|
+
* @returns True if likely centimeters
|
|
36
|
+
*/
|
|
37
|
+
export declare function isLikelyCentimeters(position: Position, threshold?: number): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Position Normalization
|
|
4
|
+
*
|
|
5
|
+
* Functions for normalizing position units (cm to meters, etc.)
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.normalizePositionUnits = normalizePositionUnits;
|
|
9
|
+
exports.metersToCentimeters = metersToCentimeters;
|
|
10
|
+
exports.centimetersToMeters = centimetersToMeters;
|
|
11
|
+
exports.isLikelyCentimeters = isLikelyCentimeters;
|
|
12
|
+
/**
|
|
13
|
+
* Normalize position units to meters
|
|
14
|
+
* Detects if values are likely in centimeters and converts
|
|
15
|
+
*
|
|
16
|
+
* @param position Position to normalize
|
|
17
|
+
* @param unit Force unit interpretation: 'auto' | 'meters' | 'centimeters'
|
|
18
|
+
* @returns Position in meters
|
|
19
|
+
*/
|
|
20
|
+
function normalizePositionUnits(position, unit = 'auto') {
|
|
21
|
+
if (unit === 'meters') {
|
|
22
|
+
return { ...position };
|
|
23
|
+
}
|
|
24
|
+
if (unit === 'centimeters') {
|
|
25
|
+
return {
|
|
26
|
+
x: position.x / 100,
|
|
27
|
+
y: position.y / 100,
|
|
28
|
+
z: position.z / 100,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Auto-detect: if any axis > 50, likely centimeters
|
|
32
|
+
const maxAxis = Math.max(Math.abs(position.x), Math.abs(position.y), Math.abs(position.z));
|
|
33
|
+
if (maxAxis > 50) {
|
|
34
|
+
return {
|
|
35
|
+
x: position.x / 100,
|
|
36
|
+
y: position.y / 100,
|
|
37
|
+
z: position.z / 100,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return { ...position };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Convert meters to centimeters
|
|
44
|
+
*
|
|
45
|
+
* @param position Position in meters
|
|
46
|
+
* @returns Position in centimeters
|
|
47
|
+
*/
|
|
48
|
+
function metersToCentimeters(position) {
|
|
49
|
+
return {
|
|
50
|
+
x: position.x * 100,
|
|
51
|
+
y: position.y * 100,
|
|
52
|
+
z: position.z * 100,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Convert centimeters to meters
|
|
57
|
+
*
|
|
58
|
+
* @param position Position in centimeters
|
|
59
|
+
* @returns Position in meters
|
|
60
|
+
*/
|
|
61
|
+
function centimetersToMeters(position) {
|
|
62
|
+
return {
|
|
63
|
+
x: position.x / 100,
|
|
64
|
+
y: position.y / 100,
|
|
65
|
+
z: position.z / 100,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if position values are likely in centimeters
|
|
70
|
+
*
|
|
71
|
+
* @param position Position to check
|
|
72
|
+
* @param threshold Threshold for detection (default: 50)
|
|
73
|
+
* @returns True if likely centimeters
|
|
74
|
+
*/
|
|
75
|
+
function isLikelyCentimeters(position, threshold = 50) {
|
|
76
|
+
const maxAxis = Math.max(Math.abs(position.x), Math.abs(position.y), Math.abs(position.z));
|
|
77
|
+
return maxAxis > threshold;
|
|
78
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Position Snapping
|
|
3
|
+
*
|
|
4
|
+
* Functions for reducing position jitter by snapping to a grid
|
|
5
|
+
*/
|
|
6
|
+
import { Position } from '../../types/position';
|
|
7
|
+
/**
|
|
8
|
+
* Snap configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface SnapConfig {
|
|
11
|
+
threshold: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Default snap configuration
|
|
15
|
+
* 0.30m = 30cm - ignores pixel streaming jitter, physics wobble, breathing
|
|
16
|
+
*/
|
|
17
|
+
export declare const SNAP_CONFIG: SnapConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Position snap cache for reducing jitter
|
|
20
|
+
*/
|
|
21
|
+
export declare class PositionSnapCache {
|
|
22
|
+
private cache;
|
|
23
|
+
private threshold;
|
|
24
|
+
constructor(threshold?: number);
|
|
25
|
+
/**
|
|
26
|
+
* Snap position to reduce jitter
|
|
27
|
+
* Returns cached position if movement is below threshold
|
|
28
|
+
*
|
|
29
|
+
* @param position New position
|
|
30
|
+
* @param id Identifier for this position (participantId or 'listener')
|
|
31
|
+
* @returns Snapped position
|
|
32
|
+
*/
|
|
33
|
+
snap(position: Position, id: string): Position;
|
|
34
|
+
/**
|
|
35
|
+
* Clear cached position for an ID
|
|
36
|
+
*/
|
|
37
|
+
clear(id: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Clear all cached positions
|
|
40
|
+
*/
|
|
41
|
+
clearAll(): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Simple position snap without caching
|
|
45
|
+
* Snaps to grid based on threshold
|
|
46
|
+
*
|
|
47
|
+
* @param position Position to snap
|
|
48
|
+
* @param gridSize Grid size for snapping
|
|
49
|
+
* @returns Snapped position
|
|
50
|
+
*/
|
|
51
|
+
export declare function snapPositionSimple(position: Position, gridSize?: number): Position;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Position Snapping
|
|
4
|
+
*
|
|
5
|
+
* Functions for reducing position jitter by snapping to a grid
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.PositionSnapCache = exports.SNAP_CONFIG = void 0;
|
|
9
|
+
exports.snapPositionSimple = snapPositionSimple;
|
|
10
|
+
/**
|
|
11
|
+
* Default snap configuration
|
|
12
|
+
* 0.30m = 30cm - ignores pixel streaming jitter, physics wobble, breathing
|
|
13
|
+
*/
|
|
14
|
+
exports.SNAP_CONFIG = {
|
|
15
|
+
threshold: 0.30,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Position snap cache for reducing jitter
|
|
19
|
+
*/
|
|
20
|
+
class PositionSnapCache {
|
|
21
|
+
constructor(threshold = exports.SNAP_CONFIG.threshold) {
|
|
22
|
+
this.cache = new Map();
|
|
23
|
+
this.threshold = threshold;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Snap position to reduce jitter
|
|
27
|
+
* Returns cached position if movement is below threshold
|
|
28
|
+
*
|
|
29
|
+
* @param position New position
|
|
30
|
+
* @param id Identifier for this position (participantId or 'listener')
|
|
31
|
+
* @returns Snapped position
|
|
32
|
+
*/
|
|
33
|
+
snap(position, id) {
|
|
34
|
+
const cached = this.cache.get(id);
|
|
35
|
+
// If no cached position, use this one as baseline
|
|
36
|
+
if (!cached || (cached.x === 0 && cached.y === 0 && cached.z === 0)) {
|
|
37
|
+
this.cache.set(id, { ...position });
|
|
38
|
+
return position;
|
|
39
|
+
}
|
|
40
|
+
// Calculate movement distance
|
|
41
|
+
const dx = position.x - cached.x;
|
|
42
|
+
const dy = position.y - cached.y;
|
|
43
|
+
const dz = position.z - cached.z;
|
|
44
|
+
const movedDistance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
45
|
+
// If moved more than threshold, update cache and use new position
|
|
46
|
+
if (movedDistance > this.threshold) {
|
|
47
|
+
this.cache.set(id, { ...position });
|
|
48
|
+
return position;
|
|
49
|
+
}
|
|
50
|
+
// Position hasn't changed significantly - return cached
|
|
51
|
+
return cached;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Clear cached position for an ID
|
|
55
|
+
*/
|
|
56
|
+
clear(id) {
|
|
57
|
+
this.cache.delete(id);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Clear all cached positions
|
|
61
|
+
*/
|
|
62
|
+
clearAll() {
|
|
63
|
+
this.cache.clear();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.PositionSnapCache = PositionSnapCache;
|
|
67
|
+
/**
|
|
68
|
+
* Simple position snap without caching
|
|
69
|
+
* Snaps to grid based on threshold
|
|
70
|
+
*
|
|
71
|
+
* @param position Position to snap
|
|
72
|
+
* @param gridSize Grid size for snapping
|
|
73
|
+
* @returns Snapped position
|
|
74
|
+
*/
|
|
75
|
+
function snapPositionSimple(position, gridSize = 0.1) {
|
|
76
|
+
return {
|
|
77
|
+
x: Math.round(position.x / gridSize) * gridSize,
|
|
78
|
+
y: Math.round(position.y / gridSize) * gridSize,
|
|
79
|
+
z: Math.round(position.z / gridSize) * gridSize,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gain Smoothing
|
|
3
|
+
*
|
|
4
|
+
* Functions for smoothing audio gain changes to prevent clicks/pops
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Apply smooth gain transition using Web Audio API's setTargetAtTime
|
|
8
|
+
*
|
|
9
|
+
* @param gainNode The GainNode to modify
|
|
10
|
+
* @param targetGain Target gain value (0-1)
|
|
11
|
+
* @param audioContext AudioContext for timing
|
|
12
|
+
* @param timeConstant Time constant for transition (default: 0.1 = ~300ms to settle)
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyGainSmooth(gainNode: GainNode, targetGain: number, audioContext: AudioContext, timeConstant?: number): void;
|
|
15
|
+
/**
|
|
16
|
+
* Gain tracker for managing gain values per participant
|
|
17
|
+
*/
|
|
18
|
+
export declare class GainTracker {
|
|
19
|
+
private lastValues;
|
|
20
|
+
/**
|
|
21
|
+
* Get last gain value for a participant
|
|
22
|
+
*/
|
|
23
|
+
get(participantId: string): number | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Set last gain value for a participant
|
|
26
|
+
*/
|
|
27
|
+
set(participantId: string, value: number): void;
|
|
28
|
+
/**
|
|
29
|
+
* Clear gain value for a participant
|
|
30
|
+
*/
|
|
31
|
+
clear(participantId: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Clear all gain values
|
|
34
|
+
*/
|
|
35
|
+
clearAll(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Apply smooth stereo pan transition
|
|
39
|
+
*
|
|
40
|
+
* @param stereoPanner The StereoPannerNode to modify
|
|
41
|
+
* @param panValue Target pan value (-1 to +1)
|
|
42
|
+
* @param audioContext AudioContext for timing
|
|
43
|
+
* @param timeConstant Time constant for transition (default: 0.05 = ~150ms)
|
|
44
|
+
*/
|
|
45
|
+
export declare function applyStereoPanSmooth(stereoPanner: StereoPannerNode, panValue: number, audioContext: AudioContext, timeConstant?: number): void;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gain Smoothing
|
|
4
|
+
*
|
|
5
|
+
* Functions for smoothing audio gain changes to prevent clicks/pops
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.GainTracker = void 0;
|
|
9
|
+
exports.applyGainSmooth = applyGainSmooth;
|
|
10
|
+
exports.applyStereoPanSmooth = applyStereoPanSmooth;
|
|
11
|
+
/**
|
|
12
|
+
* Apply smooth gain transition using Web Audio API's setTargetAtTime
|
|
13
|
+
*
|
|
14
|
+
* @param gainNode The GainNode to modify
|
|
15
|
+
* @param targetGain Target gain value (0-1)
|
|
16
|
+
* @param audioContext AudioContext for timing
|
|
17
|
+
* @param timeConstant Time constant for transition (default: 0.1 = ~300ms to settle)
|
|
18
|
+
*/
|
|
19
|
+
function applyGainSmooth(gainNode, targetGain, audioContext, timeConstant = 0.1) {
|
|
20
|
+
try {
|
|
21
|
+
gainNode.gain.setTargetAtTime(targetGain, audioContext.currentTime, timeConstant);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
// Fallback: set value directly
|
|
25
|
+
gainNode.gain.value = targetGain;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Gain tracker for managing gain values per participant
|
|
30
|
+
*/
|
|
31
|
+
class GainTracker {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.lastValues = new Map();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get last gain value for a participant
|
|
37
|
+
*/
|
|
38
|
+
get(participantId) {
|
|
39
|
+
return this.lastValues.get(participantId);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Set last gain value for a participant
|
|
43
|
+
*/
|
|
44
|
+
set(participantId, value) {
|
|
45
|
+
this.lastValues.set(participantId, value);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Clear gain value for a participant
|
|
49
|
+
*/
|
|
50
|
+
clear(participantId) {
|
|
51
|
+
this.lastValues.delete(participantId);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Clear all gain values
|
|
55
|
+
*/
|
|
56
|
+
clearAll() {
|
|
57
|
+
this.lastValues.clear();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.GainTracker = GainTracker;
|
|
61
|
+
/**
|
|
62
|
+
* Apply smooth stereo pan transition
|
|
63
|
+
*
|
|
64
|
+
* @param stereoPanner The StereoPannerNode to modify
|
|
65
|
+
* @param panValue Target pan value (-1 to +1)
|
|
66
|
+
* @param audioContext AudioContext for timing
|
|
67
|
+
* @param timeConstant Time constant for transition (default: 0.05 = ~150ms)
|
|
68
|
+
*/
|
|
69
|
+
function applyStereoPanSmooth(stereoPanner, panValue, audioContext, timeConstant = 0.05) {
|
|
70
|
+
try {
|
|
71
|
+
stereoPanner.pan.setTargetAtTime(panValue, audioContext.currentTime, timeConstant);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
// Fallback: set value directly
|
|
75
|
+
stereoPanner.pan.value = panValue;
|
|
76
|
+
}
|
|
77
|
+
}
|