@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
package/README.md
CHANGED
|
@@ -1,7 +1,51 @@
|
|
|
1
1
|
# Odyssey Audio/Video SDK (MediaSoup + Web Audio)
|
|
2
2
|
|
|
3
3
|
This package exposes `OdysseySpatialComms`, a thin TypeScript client that glues together:
|
|
4
|
-
|
|
4
|
+
## code structure:
|
|
5
|
+
src/
|
|
6
|
+
├── index.ts # Main SDK entry (OdysseySpatialComms class)
|
|
7
|
+
├── types/ # All TypeScript interfaces
|
|
8
|
+
│ ├── position.ts # Position, Direction, Rotation types
|
|
9
|
+
│ ├── participant.ts # Participant, MediaState types
|
|
10
|
+
│ ├── events.ts # All event types (OdysseyEvent, etc.)
|
|
11
|
+
│ ├── room.ts # Room-related types
|
|
12
|
+
│ └── index.ts # Re-exports all types
|
|
13
|
+
├── utils/
|
|
14
|
+
│ ├── spatial/ # Spatial audio calculations
|
|
15
|
+
│ │ ├── distance-calc.ts # Distance calculations
|
|
16
|
+
│ │ ├── gain-calc.ts # Logarithmic gain
|
|
17
|
+
│ │ ├── pan-calc.ts # Stereo panning
|
|
18
|
+
│ │ ├── head-position.ts # Head/body position
|
|
19
|
+
│ │ ├── listener-calc.ts # Listener orientation
|
|
20
|
+
│ │ └── angle-calc.ts # Azimuth/angle calculations
|
|
21
|
+
│ ├── position/ # Position utilities
|
|
22
|
+
│ │ ├── normalize.ts # Unit normalization (cm/m)
|
|
23
|
+
│ │ ├── snap.ts # Position snapping cache
|
|
24
|
+
│ │ └── coordinates.ts # Unreal↔Standard conversion
|
|
25
|
+
│ ├── smoothing/ # Audio smoothing
|
|
26
|
+
│ │ ├── pan-smoothing.ts # Pan interpolation
|
|
27
|
+
│ │ └── gain-smoothing.ts # Gain interpolation
|
|
28
|
+
│ └── audio/ # Audio quality
|
|
29
|
+
│ ├── clarity-score.ts # Voice clarity
|
|
30
|
+
│ └── voice-filter.ts # Voice filtering
|
|
31
|
+
├── channels/
|
|
32
|
+
│ ├── spatial/ # Spatial audio channel
|
|
33
|
+
│ │ ├── SpatialAudioChannel.ts # Main spatial processor
|
|
34
|
+
│ │ └── SpatialAudioTypes.ts # Channel-specific types
|
|
35
|
+
│ └── huddle/ # Huddle/private channel
|
|
36
|
+
│ ├── HuddleChannel.ts # Huddle channel manager
|
|
37
|
+
│ └── HuddleTypes.ts # Huddle types
|
|
38
|
+
├── audio/ # Audio processing
|
|
39
|
+
│ ├── AudioPipeline.ts # Master audio chain
|
|
40
|
+
│ ├── AudioNodeFactory.ts # Web Audio node factory
|
|
41
|
+
│ └── MLNoiseSuppressor.ts # TensorFlow noise suppression
|
|
42
|
+
├── core/ # Core managers
|
|
43
|
+
│ ├── EventManager.ts # Event emitter base
|
|
44
|
+
│ └── MediasoupManager.ts # WebRTC transport manager
|
|
45
|
+
└── sdk/
|
|
46
|
+
└── index.ts # Public SDK exports
|
|
47
|
+
|
|
48
|
+
|
|
5
49
|
- **MediaSoup SFU** for ultra-low-latency audio/video routing
|
|
6
50
|
- **Web Audio API** for Apple-like spatial mixing via `SpatialAudioManager`
|
|
7
51
|
- **Socket telemetry** (position + direction) so every browser hears/sees everyone exactly where they are in the 3D world
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audio Node Factory
|
|
3
|
+
*
|
|
4
|
+
* Factory functions for creating Web Audio API nodes
|
|
5
|
+
* with optimal configurations for voice communication
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* PannerNode configuration for spatial audio
|
|
9
|
+
*/
|
|
10
|
+
export interface PannerConfig {
|
|
11
|
+
refDistance?: number;
|
|
12
|
+
maxDistance?: number;
|
|
13
|
+
rolloffFactor?: number;
|
|
14
|
+
panningModel?: PanningModelType;
|
|
15
|
+
distanceModel?: DistanceModelType;
|
|
16
|
+
coneInnerAngle?: number;
|
|
17
|
+
coneOuterAngle?: number;
|
|
18
|
+
coneOuterGain?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Default panner configuration for voice
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEFAULT_PANNER_CONFIG: Required<PannerConfig>;
|
|
24
|
+
/**
|
|
25
|
+
* Create configured PannerNode for 3D spatial audio
|
|
26
|
+
*
|
|
27
|
+
* @param audioContext AudioContext
|
|
28
|
+
* @param config Optional panner configuration
|
|
29
|
+
* @returns Configured PannerNode
|
|
30
|
+
*/
|
|
31
|
+
export declare function createPanner(audioContext: AudioContext, config?: PannerConfig): PannerNode;
|
|
32
|
+
/**
|
|
33
|
+
* Create StereoPannerNode for left/right panning
|
|
34
|
+
*
|
|
35
|
+
* @param audioContext AudioContext
|
|
36
|
+
* @param initialPan Initial pan value (-1 to +1)
|
|
37
|
+
* @returns StereoPannerNode
|
|
38
|
+
*/
|
|
39
|
+
export declare function createStereoPanner(audioContext: AudioContext, initialPan?: number): StereoPannerNode;
|
|
40
|
+
/**
|
|
41
|
+
* Create GainNode with initial value
|
|
42
|
+
*
|
|
43
|
+
* @param audioContext AudioContext
|
|
44
|
+
* @param initialGain Initial gain value
|
|
45
|
+
* @returns GainNode
|
|
46
|
+
*/
|
|
47
|
+
export declare function createGain(audioContext: AudioContext, initialGain?: number): GainNode;
|
|
48
|
+
/**
|
|
49
|
+
* Create AnalyserNode for audio visualization/monitoring
|
|
50
|
+
*
|
|
51
|
+
* @param audioContext AudioContext
|
|
52
|
+
* @param fftSize FFT size (default: 2048)
|
|
53
|
+
* @returns AnalyserNode
|
|
54
|
+
*/
|
|
55
|
+
export declare function createAnalyser(audioContext: AudioContext, fftSize?: number): AnalyserNode;
|
|
56
|
+
/**
|
|
57
|
+
* Highpass filter configuration
|
|
58
|
+
*/
|
|
59
|
+
export interface HighpassConfig {
|
|
60
|
+
frequency?: number;
|
|
61
|
+
Q?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create highpass filter for removing low-frequency rumble
|
|
65
|
+
*
|
|
66
|
+
* @param audioContext AudioContext
|
|
67
|
+
* @param config Optional configuration
|
|
68
|
+
* @returns BiquadFilterNode
|
|
69
|
+
*/
|
|
70
|
+
export declare function createHighpassFilter(audioContext: AudioContext, config?: HighpassConfig): BiquadFilterNode;
|
|
71
|
+
/**
|
|
72
|
+
* Lowpass filter configuration
|
|
73
|
+
*/
|
|
74
|
+
export interface LowpassConfig {
|
|
75
|
+
frequency?: number;
|
|
76
|
+
Q?: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create lowpass filter for removing high-frequency hiss
|
|
80
|
+
*
|
|
81
|
+
* @param audioContext AudioContext
|
|
82
|
+
* @param config Optional configuration
|
|
83
|
+
* @returns BiquadFilterNode
|
|
84
|
+
*/
|
|
85
|
+
export declare function createLowpassFilter(audioContext: AudioContext, config?: LowpassConfig): BiquadFilterNode;
|
|
86
|
+
/**
|
|
87
|
+
* Peaking filter configuration
|
|
88
|
+
*/
|
|
89
|
+
export interface PeakingConfig {
|
|
90
|
+
frequency?: number;
|
|
91
|
+
Q?: number;
|
|
92
|
+
gain?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create peaking filter for frequency emphasis
|
|
96
|
+
*
|
|
97
|
+
* @param audioContext AudioContext
|
|
98
|
+
* @param config Optional configuration
|
|
99
|
+
* @returns BiquadFilterNode
|
|
100
|
+
*/
|
|
101
|
+
export declare function createPeakingFilter(audioContext: AudioContext, config?: PeakingConfig): BiquadFilterNode;
|
|
102
|
+
/**
|
|
103
|
+
* Compressor configuration
|
|
104
|
+
*/
|
|
105
|
+
export interface CompressorConfig {
|
|
106
|
+
threshold?: number;
|
|
107
|
+
knee?: number;
|
|
108
|
+
ratio?: number;
|
|
109
|
+
attack?: number;
|
|
110
|
+
release?: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create DynamicsCompressorNode with configuration
|
|
114
|
+
*
|
|
115
|
+
* @param audioContext AudioContext
|
|
116
|
+
* @param config Optional configuration
|
|
117
|
+
* @returns DynamicsCompressorNode
|
|
118
|
+
*/
|
|
119
|
+
export declare function createCompressor(audioContext: AudioContext, config?: CompressorConfig): DynamicsCompressorNode;
|
|
120
|
+
/**
|
|
121
|
+
* Create MediaStreamAudioSourceNode from track
|
|
122
|
+
*
|
|
123
|
+
* @param audioContext AudioContext
|
|
124
|
+
* @param track MediaStreamTrack (audio)
|
|
125
|
+
* @returns MediaStreamAudioSourceNode and MediaStream
|
|
126
|
+
*/
|
|
127
|
+
export declare function createMediaStreamSource(audioContext: AudioContext, track: MediaStreamTrack): {
|
|
128
|
+
source: MediaStreamAudioSourceNode;
|
|
129
|
+
stream: MediaStream;
|
|
130
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audio Node Factory
|
|
4
|
+
*
|
|
5
|
+
* Factory functions for creating Web Audio API nodes
|
|
6
|
+
* with optimal configurations for voice communication
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DEFAULT_PANNER_CONFIG = void 0;
|
|
10
|
+
exports.createPanner = createPanner;
|
|
11
|
+
exports.createStereoPanner = createStereoPanner;
|
|
12
|
+
exports.createGain = createGain;
|
|
13
|
+
exports.createAnalyser = createAnalyser;
|
|
14
|
+
exports.createHighpassFilter = createHighpassFilter;
|
|
15
|
+
exports.createLowpassFilter = createLowpassFilter;
|
|
16
|
+
exports.createPeakingFilter = createPeakingFilter;
|
|
17
|
+
exports.createCompressor = createCompressor;
|
|
18
|
+
exports.createMediaStreamSource = createMediaStreamSource;
|
|
19
|
+
/**
|
|
20
|
+
* Default panner configuration for voice
|
|
21
|
+
*/
|
|
22
|
+
exports.DEFAULT_PANNER_CONFIG = {
|
|
23
|
+
refDistance: 1.2,
|
|
24
|
+
maxDistance: 15,
|
|
25
|
+
rolloffFactor: 1.35,
|
|
26
|
+
panningModel: 'HRTF',
|
|
27
|
+
distanceModel: 'inverse',
|
|
28
|
+
coneInnerAngle: 360,
|
|
29
|
+
coneOuterAngle: 360,
|
|
30
|
+
coneOuterGain: 0.3,
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Create configured PannerNode for 3D spatial audio
|
|
34
|
+
*
|
|
35
|
+
* @param audioContext AudioContext
|
|
36
|
+
* @param config Optional panner configuration
|
|
37
|
+
* @returns Configured PannerNode
|
|
38
|
+
*/
|
|
39
|
+
function createPanner(audioContext, config = {}) {
|
|
40
|
+
const panner = audioContext.createPanner();
|
|
41
|
+
const cfg = { ...exports.DEFAULT_PANNER_CONFIG, ...config };
|
|
42
|
+
panner.panningModel = cfg.panningModel;
|
|
43
|
+
panner.distanceModel = cfg.distanceModel;
|
|
44
|
+
panner.refDistance = cfg.refDistance;
|
|
45
|
+
panner.maxDistance = cfg.maxDistance;
|
|
46
|
+
panner.rolloffFactor = cfg.rolloffFactor;
|
|
47
|
+
panner.coneInnerAngle = cfg.coneInnerAngle;
|
|
48
|
+
panner.coneOuterAngle = cfg.coneOuterAngle;
|
|
49
|
+
panner.coneOuterGain = cfg.coneOuterGain;
|
|
50
|
+
return panner;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create StereoPannerNode for left/right panning
|
|
54
|
+
*
|
|
55
|
+
* @param audioContext AudioContext
|
|
56
|
+
* @param initialPan Initial pan value (-1 to +1)
|
|
57
|
+
* @returns StereoPannerNode
|
|
58
|
+
*/
|
|
59
|
+
function createStereoPanner(audioContext, initialPan = 0) {
|
|
60
|
+
const panner = audioContext.createStereoPanner();
|
|
61
|
+
panner.pan.value = initialPan;
|
|
62
|
+
return panner;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create GainNode with initial value
|
|
66
|
+
*
|
|
67
|
+
* @param audioContext AudioContext
|
|
68
|
+
* @param initialGain Initial gain value
|
|
69
|
+
* @returns GainNode
|
|
70
|
+
*/
|
|
71
|
+
function createGain(audioContext, initialGain = 1.0) {
|
|
72
|
+
const gain = audioContext.createGain();
|
|
73
|
+
gain.gain.value = initialGain;
|
|
74
|
+
return gain;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Create AnalyserNode for audio visualization/monitoring
|
|
78
|
+
*
|
|
79
|
+
* @param audioContext AudioContext
|
|
80
|
+
* @param fftSize FFT size (default: 2048)
|
|
81
|
+
* @returns AnalyserNode
|
|
82
|
+
*/
|
|
83
|
+
function createAnalyser(audioContext, fftSize = 2048) {
|
|
84
|
+
const analyser = audioContext.createAnalyser();
|
|
85
|
+
analyser.fftSize = fftSize;
|
|
86
|
+
return analyser;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Create highpass filter for removing low-frequency rumble
|
|
90
|
+
*
|
|
91
|
+
* @param audioContext AudioContext
|
|
92
|
+
* @param config Optional configuration
|
|
93
|
+
* @returns BiquadFilterNode
|
|
94
|
+
*/
|
|
95
|
+
function createHighpassFilter(audioContext, config = {}) {
|
|
96
|
+
const filter = audioContext.createBiquadFilter();
|
|
97
|
+
filter.type = 'highpass';
|
|
98
|
+
filter.frequency.value = config.frequency ?? 100;
|
|
99
|
+
filter.Q.value = config.Q ?? 0.5;
|
|
100
|
+
return filter;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Create lowpass filter for removing high-frequency hiss
|
|
104
|
+
*
|
|
105
|
+
* @param audioContext AudioContext
|
|
106
|
+
* @param config Optional configuration
|
|
107
|
+
* @returns BiquadFilterNode
|
|
108
|
+
*/
|
|
109
|
+
function createLowpassFilter(audioContext, config = {}) {
|
|
110
|
+
const filter = audioContext.createBiquadFilter();
|
|
111
|
+
filter.type = 'lowpass';
|
|
112
|
+
filter.frequency.value = config.frequency ?? 10000;
|
|
113
|
+
filter.Q.value = config.Q ?? 0.5;
|
|
114
|
+
return filter;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create peaking filter for frequency emphasis
|
|
118
|
+
*
|
|
119
|
+
* @param audioContext AudioContext
|
|
120
|
+
* @param config Optional configuration
|
|
121
|
+
* @returns BiquadFilterNode
|
|
122
|
+
*/
|
|
123
|
+
function createPeakingFilter(audioContext, config = {}) {
|
|
124
|
+
const filter = audioContext.createBiquadFilter();
|
|
125
|
+
filter.type = 'peaking';
|
|
126
|
+
filter.frequency.value = config.frequency ?? 180;
|
|
127
|
+
filter.Q.value = config.Q ?? 0.5;
|
|
128
|
+
filter.gain.value = config.gain ?? 0;
|
|
129
|
+
return filter;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Create DynamicsCompressorNode with configuration
|
|
133
|
+
*
|
|
134
|
+
* @param audioContext AudioContext
|
|
135
|
+
* @param config Optional configuration
|
|
136
|
+
* @returns DynamicsCompressorNode
|
|
137
|
+
*/
|
|
138
|
+
function createCompressor(audioContext, config = {}) {
|
|
139
|
+
const compressor = audioContext.createDynamicsCompressor();
|
|
140
|
+
compressor.threshold.value = config.threshold ?? -24;
|
|
141
|
+
compressor.knee.value = config.knee ?? 30;
|
|
142
|
+
compressor.ratio.value = config.ratio ?? 12;
|
|
143
|
+
compressor.attack.value = config.attack ?? 0.003;
|
|
144
|
+
compressor.release.value = config.release ?? 0.25;
|
|
145
|
+
return compressor;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Create MediaStreamAudioSourceNode from track
|
|
149
|
+
*
|
|
150
|
+
* @param audioContext AudioContext
|
|
151
|
+
* @param track MediaStreamTrack (audio)
|
|
152
|
+
* @returns MediaStreamAudioSourceNode and MediaStream
|
|
153
|
+
*/
|
|
154
|
+
function createMediaStreamSource(audioContext, track) {
|
|
155
|
+
const stream = new MediaStream([track]);
|
|
156
|
+
const source = audioContext.createMediaStreamSource(stream);
|
|
157
|
+
return { source, stream };
|
|
158
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audio Pipeline - Web Audio Node Chain Setup
|
|
3
|
+
*
|
|
4
|
+
* Creates and connects audio processing nodes for participant audio
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Audio pipeline configuration
|
|
8
|
+
*/
|
|
9
|
+
export interface AudioPipelineConfig {
|
|
10
|
+
sampleRate?: number;
|
|
11
|
+
enableCompressor?: boolean;
|
|
12
|
+
enableFilters?: boolean;
|
|
13
|
+
enableDenoiser?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Default audio pipeline configuration
|
|
17
|
+
*/
|
|
18
|
+
export declare const DEFAULT_PIPELINE_CONFIG: Required<AudioPipelineConfig>;
|
|
19
|
+
/**
|
|
20
|
+
* Master audio output chain
|
|
21
|
+
*/
|
|
22
|
+
export interface MasterAudioChain {
|
|
23
|
+
masterGain: GainNode;
|
|
24
|
+
compressor: DynamicsCompressorNode;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create master audio output chain
|
|
28
|
+
*
|
|
29
|
+
* @param audioContext AudioContext
|
|
30
|
+
* @returns Master gain and compressor nodes
|
|
31
|
+
*/
|
|
32
|
+
export declare function createMasterChain(audioContext: AudioContext): MasterAudioChain;
|
|
33
|
+
/**
|
|
34
|
+
* Participant audio filter chain
|
|
35
|
+
*/
|
|
36
|
+
export interface ParticipantFilterChain {
|
|
37
|
+
highpass: BiquadFilterNode;
|
|
38
|
+
lowpass: BiquadFilterNode;
|
|
39
|
+
voiceBand: BiquadFilterNode;
|
|
40
|
+
dynamicLowpass: BiquadFilterNode;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create participant filter chain for voice optimization
|
|
44
|
+
*
|
|
45
|
+
* @param audioContext AudioContext
|
|
46
|
+
* @returns Filter nodes
|
|
47
|
+
*/
|
|
48
|
+
export declare function createFilterChain(audioContext: AudioContext): ParticipantFilterChain;
|
|
49
|
+
/**
|
|
50
|
+
* Connect filter chain in series
|
|
51
|
+
*
|
|
52
|
+
* @param filters Filter chain
|
|
53
|
+
* @returns Input and output nodes
|
|
54
|
+
*/
|
|
55
|
+
export declare function connectFilterChain(filters: ParticipantFilterChain): {
|
|
56
|
+
input: BiquadFilterNode;
|
|
57
|
+
output: BiquadFilterNode;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Create limiter (peak prevention compressor)
|
|
61
|
+
*
|
|
62
|
+
* @param audioContext AudioContext
|
|
63
|
+
* @returns DynamicsCompressorNode configured as limiter
|
|
64
|
+
*/
|
|
65
|
+
export declare function createLimiter(audioContext: AudioContext): DynamicsCompressorNode;
|
|
66
|
+
/**
|
|
67
|
+
* Mono downmix chain for stable stereo panning
|
|
68
|
+
*/
|
|
69
|
+
export interface MonoDownmixChain {
|
|
70
|
+
splitter: ChannelSplitterNode;
|
|
71
|
+
gainL: GainNode;
|
|
72
|
+
gainR: GainNode;
|
|
73
|
+
merger: ChannelMergerNode;
|
|
74
|
+
stereoUpmixer: ChannelMergerNode;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Create mono downmix chain
|
|
78
|
+
* Forces predictable mono signal before StereoPanner
|
|
79
|
+
*
|
|
80
|
+
* @param audioContext AudioContext
|
|
81
|
+
* @returns Mono downmix nodes
|
|
82
|
+
*/
|
|
83
|
+
export declare function createMonoDownmixChain(audioContext: AudioContext): MonoDownmixChain;
|
|
84
|
+
/**
|
|
85
|
+
* Connect mono downmix chain
|
|
86
|
+
*
|
|
87
|
+
* @param chain Mono downmix chain
|
|
88
|
+
*/
|
|
89
|
+
export declare function connectMonoDownmixChain(chain: MonoDownmixChain): void;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audio Pipeline - Web Audio Node Chain Setup
|
|
4
|
+
*
|
|
5
|
+
* Creates and connects audio processing nodes for participant audio
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DEFAULT_PIPELINE_CONFIG = void 0;
|
|
9
|
+
exports.createMasterChain = createMasterChain;
|
|
10
|
+
exports.createFilterChain = createFilterChain;
|
|
11
|
+
exports.connectFilterChain = connectFilterChain;
|
|
12
|
+
exports.createLimiter = createLimiter;
|
|
13
|
+
exports.createMonoDownmixChain = createMonoDownmixChain;
|
|
14
|
+
exports.connectMonoDownmixChain = connectMonoDownmixChain;
|
|
15
|
+
/**
|
|
16
|
+
* Default audio pipeline configuration
|
|
17
|
+
*/
|
|
18
|
+
exports.DEFAULT_PIPELINE_CONFIG = {
|
|
19
|
+
sampleRate: 48000,
|
|
20
|
+
enableCompressor: true,
|
|
21
|
+
enableFilters: true,
|
|
22
|
+
enableDenoiser: false,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Create master audio output chain
|
|
26
|
+
*
|
|
27
|
+
* @param audioContext AudioContext
|
|
28
|
+
* @returns Master gain and compressor nodes
|
|
29
|
+
*/
|
|
30
|
+
function createMasterChain(audioContext) {
|
|
31
|
+
// Master gain - unity gain for clean audio
|
|
32
|
+
const masterGain = audioContext.createGain();
|
|
33
|
+
masterGain.gain.value = 1.0;
|
|
34
|
+
// Master compressor - gentle dynamic range control
|
|
35
|
+
const compressor = audioContext.createDynamicsCompressor();
|
|
36
|
+
compressor.threshold.value = -15;
|
|
37
|
+
compressor.knee.value = 40;
|
|
38
|
+
compressor.ratio.value = 2.5;
|
|
39
|
+
compressor.attack.value = 0.02;
|
|
40
|
+
compressor.release.value = 0.25;
|
|
41
|
+
// Connect: masterGain → compressor → destination
|
|
42
|
+
masterGain.connect(compressor);
|
|
43
|
+
compressor.connect(audioContext.destination);
|
|
44
|
+
return { masterGain, compressor };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create participant filter chain for voice optimization
|
|
48
|
+
*
|
|
49
|
+
* @param audioContext AudioContext
|
|
50
|
+
* @returns Filter nodes
|
|
51
|
+
*/
|
|
52
|
+
function createFilterChain(audioContext) {
|
|
53
|
+
// Highpass: Remove low-frequency rumble (< 100Hz)
|
|
54
|
+
const highpass = audioContext.createBiquadFilter();
|
|
55
|
+
highpass.type = 'highpass';
|
|
56
|
+
highpass.frequency.value = 100;
|
|
57
|
+
highpass.Q.value = 0.5;
|
|
58
|
+
// Lowpass: Remove high-frequency hiss (> 10kHz)
|
|
59
|
+
const lowpass = audioContext.createBiquadFilter();
|
|
60
|
+
lowpass.type = 'lowpass';
|
|
61
|
+
lowpass.frequency.value = 10000;
|
|
62
|
+
lowpass.Q.value = 0.5;
|
|
63
|
+
// Voice band emphasis (disabled by default - can cause resonance)
|
|
64
|
+
const voiceBand = audioContext.createBiquadFilter();
|
|
65
|
+
voiceBand.type = 'peaking';
|
|
66
|
+
voiceBand.frequency.value = 180;
|
|
67
|
+
voiceBand.Q.value = 0.5;
|
|
68
|
+
voiceBand.gain.value = 0;
|
|
69
|
+
// Dynamic lowpass for high-frequency control
|
|
70
|
+
const dynamicLowpass = audioContext.createBiquadFilter();
|
|
71
|
+
dynamicLowpass.type = 'lowpass';
|
|
72
|
+
dynamicLowpass.frequency.value = 12000;
|
|
73
|
+
dynamicLowpass.Q.value = 0.5;
|
|
74
|
+
return { highpass, lowpass, voiceBand, dynamicLowpass };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Connect filter chain in series
|
|
78
|
+
*
|
|
79
|
+
* @param filters Filter chain
|
|
80
|
+
* @returns Input and output nodes
|
|
81
|
+
*/
|
|
82
|
+
function connectFilterChain(filters) {
|
|
83
|
+
filters.highpass.connect(filters.voiceBand);
|
|
84
|
+
filters.voiceBand.connect(filters.lowpass);
|
|
85
|
+
filters.lowpass.connect(filters.dynamicLowpass);
|
|
86
|
+
return {
|
|
87
|
+
input: filters.highpass,
|
|
88
|
+
output: filters.dynamicLowpass,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create limiter (peak prevention compressor)
|
|
93
|
+
*
|
|
94
|
+
* @param audioContext AudioContext
|
|
95
|
+
* @returns DynamicsCompressorNode configured as limiter
|
|
96
|
+
*/
|
|
97
|
+
function createLimiter(audioContext) {
|
|
98
|
+
const limiter = audioContext.createDynamicsCompressor();
|
|
99
|
+
limiter.threshold.value = -6; // Only activate near clipping
|
|
100
|
+
limiter.knee.value = 3; // Hard knee = limiter behavior
|
|
101
|
+
limiter.ratio.value = 20; // High ratio = limiter
|
|
102
|
+
limiter.attack.value = 0.001; // 1ms - catch peaks fast
|
|
103
|
+
limiter.release.value = 0.05; // 50ms - fast release
|
|
104
|
+
return limiter;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create mono downmix chain
|
|
108
|
+
* Forces predictable mono signal before StereoPanner
|
|
109
|
+
*
|
|
110
|
+
* @param audioContext AudioContext
|
|
111
|
+
* @returns Mono downmix nodes
|
|
112
|
+
*/
|
|
113
|
+
function createMonoDownmixChain(audioContext) {
|
|
114
|
+
const splitter = audioContext.createChannelSplitter(2);
|
|
115
|
+
const gainL = audioContext.createGain();
|
|
116
|
+
const gainR = audioContext.createGain();
|
|
117
|
+
const merger = audioContext.createChannelMerger(1);
|
|
118
|
+
const stereoUpmixer = audioContext.createChannelMerger(2);
|
|
119
|
+
gainL.gain.value = 0.5;
|
|
120
|
+
gainR.gain.value = 0.5;
|
|
121
|
+
return { splitter, gainL, gainR, merger, stereoUpmixer };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Connect mono downmix chain
|
|
125
|
+
*
|
|
126
|
+
* @param chain Mono downmix chain
|
|
127
|
+
*/
|
|
128
|
+
function connectMonoDownmixChain(chain) {
|
|
129
|
+
// Split stereo input
|
|
130
|
+
chain.splitter.connect(chain.gainL, 0);
|
|
131
|
+
chain.splitter.connect(chain.gainR, 1);
|
|
132
|
+
// Mix to mono
|
|
133
|
+
chain.gainL.connect(chain.merger, 0, 0);
|
|
134
|
+
chain.gainR.connect(chain.merger, 0, 0);
|
|
135
|
+
// Upmix mono to stereo (same signal both channels)
|
|
136
|
+
chain.merger.connect(chain.stereoUpmixer, 0, 0);
|
|
137
|
+
chain.merger.connect(chain.stereoUpmixer, 0, 1);
|
|
138
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ML Noise Suppressor - TensorFlow.js-based Real-Time Audio Enhancement
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Integrates trained ML model for noise suppression
|
|
5
|
+
* Falls back to traditional DSP if ML is unavailable
|
|
4
6
|
*/
|
|
5
7
|
export declare class MLNoiseSuppressor {
|
|
6
8
|
private model;
|
|
@@ -18,12 +20,10 @@ export declare class MLNoiseSuppressor {
|
|
|
18
20
|
initialize(modelUrl: string): Promise<void>;
|
|
19
21
|
/**
|
|
20
22
|
* Process audio buffer through ML model
|
|
21
|
-
* @param inputBuffer Audio samples to process
|
|
22
|
-
* @returns Denoised audio samples
|
|
23
23
|
*/
|
|
24
24
|
processAudio(inputBuffer: Float32Array): Promise<Float32Array>;
|
|
25
25
|
/**
|
|
26
|
-
* Extract audio features
|
|
26
|
+
* Extract audio features
|
|
27
27
|
*/
|
|
28
28
|
private extractFeatures;
|
|
29
29
|
/**
|
|
@@ -31,15 +31,15 @@ export declare class MLNoiseSuppressor {
|
|
|
31
31
|
*/
|
|
32
32
|
private createSequences;
|
|
33
33
|
/**
|
|
34
|
-
* Apply temporal smoothing to mask
|
|
34
|
+
* Apply temporal smoothing to mask
|
|
35
35
|
*/
|
|
36
36
|
private applyTemporalSmoothing;
|
|
37
37
|
/**
|
|
38
|
-
* Apply noise suppression mask to audio
|
|
38
|
+
* Apply noise suppression mask to audio
|
|
39
39
|
*/
|
|
40
40
|
private applyMaskToAudio;
|
|
41
41
|
/**
|
|
42
|
-
* Reset processing state
|
|
42
|
+
* Reset processing state
|
|
43
43
|
*/
|
|
44
44
|
reset(): void;
|
|
45
45
|
/**
|