@tensamin/audio 0.1.9 → 0.1.11
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 +4 -4
- package/dist/{chunk-FOGC2MFA.mjs → chunk-3I4OQD2L.mjs} +1 -1
- package/dist/{chunk-3A2CTC4K.mjs → chunk-B36JBXOK.mjs} +7 -4
- package/dist/{chunk-KGCEV2VT.mjs → chunk-GFLVGUTU.mjs} +2 -2
- package/dist/{chunk-E7NH2QKZ.mjs → chunk-I5AR7XQD.mjs} +2 -2
- package/dist/{chunk-ZISGHJDU.mjs → chunk-RLZVZ6D6.mjs} +1 -1
- package/dist/extensibility/plugins.js +7 -4
- package/dist/extensibility/plugins.mjs +2 -2
- package/dist/index.js +9 -6
- package/dist/index.mjs +5 -5
- package/dist/livekit/integration.js +9 -6
- package/dist/livekit/integration.mjs +5 -5
- package/dist/pipeline/audio-pipeline.js +9 -6
- package/dist/pipeline/audio-pipeline.mjs +4 -4
- package/dist/types.d.mts +3 -3
- package/dist/types.d.ts +3 -3
- package/dist/vad/vad-node.js +7 -4
- package/dist/vad/vad-node.mjs +1 -1
- package/dist/vad/vad-state.js +2 -2
- package/dist/vad/vad-state.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,11 +101,11 @@ vad: {
|
|
|
101
101
|
energyVad?: {
|
|
102
102
|
smoothing: number; // Default: 0.95
|
|
103
103
|
initialNoiseFloor: number; // Default: 0.001
|
|
104
|
-
noiseFloorAdaptRateQuiet: number; // Default: 0.
|
|
104
|
+
noiseFloorAdaptRateQuiet: number; // Default: 0.005
|
|
105
105
|
noiseFloorAdaptRateLoud: number; // Default: 0.01
|
|
106
106
|
minSNR: number; // Default: 10.0 (dB)
|
|
107
107
|
snrRange: number; // Default: 10.0 (dB)
|
|
108
|
-
minEnergy: number; // Default: 0.
|
|
108
|
+
minEnergy: number; // Default: 0.001
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
```
|
|
@@ -116,7 +116,7 @@ vad: {
|
|
|
116
116
|
- `stopThreshold`: Probability threshold to mute audio (Default: 0.3, ~13dB SNR)
|
|
117
117
|
- `hangoverMs`: Delay before muting after speech stops (Default: 300ms)
|
|
118
118
|
- `preRollMs`: Audio buffer duration before speech onset
|
|
119
|
-
- `minSpeechDurationMs`: Minimum duration to consider as valid speech
|
|
119
|
+
- `minSpeechDurationMs`: Minimum duration to consider as valid speech (Default: 150ms)
|
|
120
120
|
- `minSilenceDurationMs`: Minimum silence duration between speech segments
|
|
121
121
|
|
|
122
122
|
**Energy VAD Parameters:**
|
|
@@ -124,7 +124,7 @@ vad: {
|
|
|
124
124
|
- `smoothing`: Energy calculation smoothing factor (0-1)
|
|
125
125
|
- `minSNR`: Minimum signal-to-noise ratio in dB for speech detection
|
|
126
126
|
- `snrRange`: Range in dB for probability scaling from minSNR
|
|
127
|
-
- `minEnergy`: Minimum absolute RMS energy to consider as speech
|
|
127
|
+
- `minEnergy`: Minimum absolute RMS energy to consider as speech (Default: 0.001, ~-60dB)
|
|
128
128
|
|
|
129
129
|
### Output Control
|
|
130
130
|
|
|
@@ -3,11 +3,11 @@ var createEnergyVadWorkletCode = (vadConfig) => {
|
|
|
3
3
|
const energyParams = vadConfig?.energyVad || {};
|
|
4
4
|
const smoothing = energyParams.smoothing ?? 0.95;
|
|
5
5
|
const initialNoiseFloor = energyParams.initialNoiseFloor ?? 1e-3;
|
|
6
|
-
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ??
|
|
6
|
+
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ?? 5e-3;
|
|
7
7
|
const noiseFloorAdaptRateLoud = energyParams.noiseFloorAdaptRateLoud ?? 0.01;
|
|
8
8
|
const minSNR = energyParams.minSNR ?? 10;
|
|
9
9
|
const snrRange = energyParams.snrRange ?? 10;
|
|
10
|
-
const minEnergy = energyParams.minEnergy ??
|
|
10
|
+
const minEnergy = energyParams.minEnergy ?? 1e-3;
|
|
11
11
|
return `
|
|
12
12
|
class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
13
13
|
constructor() {
|
|
@@ -71,7 +71,8 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// Ensure noise floor doesn't drop to absolute zero
|
|
74
|
-
|
|
74
|
+
// 0.00005 is approx -86dB, very quiet but prevents SNR explosion
|
|
75
|
+
this.noiseFloor = Math.max(this.noiseFloor, 0.00005);
|
|
75
76
|
|
|
76
77
|
// Calculate Signal-to-Noise Ratio (SNR) in dB using smoothed energy
|
|
77
78
|
const snr = this.energy / (this.noiseFloor + 1e-6);
|
|
@@ -83,8 +84,10 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
83
84
|
let probability = Math.min(1, Math.max(0, (snrDb - this.minSNR) / this.snrRange));
|
|
84
85
|
|
|
85
86
|
// Apply absolute energy threshold
|
|
87
|
+
// We use a soft threshold to avoid abrupt cutting
|
|
86
88
|
if (this.energy < this.minEnergy) {
|
|
87
|
-
|
|
89
|
+
const energyRatio = this.energy / (this.minEnergy + 1e-6);
|
|
90
|
+
probability *= Math.pow(energyRatio, 2); // Quadratic falloff
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
this.port.postMessage({ probability, snr: snrDb, noiseFloor: this.noiseFloor, rms: this.energy });
|
|
@@ -26,11 +26,11 @@ var VADStateMachine = class {
|
|
|
26
26
|
energyVad: {
|
|
27
27
|
smoothing: config?.energyVad?.smoothing ?? 0.95,
|
|
28
28
|
initialNoiseFloor: config?.energyVad?.initialNoiseFloor ?? 1e-3,
|
|
29
|
-
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ??
|
|
29
|
+
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ?? 5e-3,
|
|
30
30
|
noiseFloorAdaptRateLoud: config?.energyVad?.noiseFloorAdaptRateLoud ?? 0.01,
|
|
31
31
|
minSNR: config?.energyVad?.minSNR ?? 10,
|
|
32
32
|
snrRange: config?.energyVad?.snrRange ?? 10,
|
|
33
|
-
minEnergy: config?.energyVad?.minEnergy ??
|
|
33
|
+
minEnergy: config?.energyVad?.minEnergy ?? 1e-3
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
this.lastSilenceTime = Date.now();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VADStateMachine
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GFLVGUTU.mjs";
|
|
4
4
|
import {
|
|
5
5
|
getAudioContext,
|
|
6
6
|
registerPipeline,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
getNoiseSuppressionPlugin,
|
|
11
11
|
getVADPlugin
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3I4OQD2L.mjs";
|
|
13
13
|
|
|
14
14
|
// src/pipeline/audio-pipeline.ts
|
|
15
15
|
import mitt from "mitt";
|
|
@@ -106,11 +106,11 @@ var createEnergyVadWorkletCode = (vadConfig) => {
|
|
|
106
106
|
const energyParams = vadConfig?.energyVad || {};
|
|
107
107
|
const smoothing = energyParams.smoothing ?? 0.95;
|
|
108
108
|
const initialNoiseFloor = energyParams.initialNoiseFloor ?? 1e-3;
|
|
109
|
-
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ??
|
|
109
|
+
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ?? 5e-3;
|
|
110
110
|
const noiseFloorAdaptRateLoud = energyParams.noiseFloorAdaptRateLoud ?? 0.01;
|
|
111
111
|
const minSNR = energyParams.minSNR ?? 10;
|
|
112
112
|
const snrRange = energyParams.snrRange ?? 10;
|
|
113
|
-
const minEnergy = energyParams.minEnergy ??
|
|
113
|
+
const minEnergy = energyParams.minEnergy ?? 1e-3;
|
|
114
114
|
return `
|
|
115
115
|
class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
116
116
|
constructor() {
|
|
@@ -174,7 +174,8 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
// Ensure noise floor doesn't drop to absolute zero
|
|
177
|
-
|
|
177
|
+
// 0.00005 is approx -86dB, very quiet but prevents SNR explosion
|
|
178
|
+
this.noiseFloor = Math.max(this.noiseFloor, 0.00005);
|
|
178
179
|
|
|
179
180
|
// Calculate Signal-to-Noise Ratio (SNR) in dB using smoothed energy
|
|
180
181
|
const snr = this.energy / (this.noiseFloor + 1e-6);
|
|
@@ -186,8 +187,10 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
186
187
|
let probability = Math.min(1, Math.max(0, (snrDb - this.minSNR) / this.snrRange));
|
|
187
188
|
|
|
188
189
|
// Apply absolute energy threshold
|
|
190
|
+
// We use a soft threshold to avoid abrupt cutting
|
|
189
191
|
if (this.energy < this.minEnergy) {
|
|
190
|
-
|
|
192
|
+
const energyRatio = this.energy / (this.minEnergy + 1e-6);
|
|
193
|
+
probability *= Math.pow(energyRatio, 2); // Quadratic falloff
|
|
191
194
|
}
|
|
192
195
|
|
|
193
196
|
this.port.postMessage({ probability, snr: snrDb, noiseFloor: this.noiseFloor, rms: this.energy });
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
getVADPlugin,
|
|
4
4
|
registerNoiseSuppressionPlugin,
|
|
5
5
|
registerVADPlugin
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-3I4OQD2L.mjs";
|
|
7
7
|
import "../chunk-XO6B3D4A.mjs";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-B36JBXOK.mjs";
|
|
9
9
|
export {
|
|
10
10
|
getNoiseSuppressionPlugin,
|
|
11
11
|
getVADPlugin,
|
package/dist/index.js
CHANGED
|
@@ -158,11 +158,11 @@ var createEnergyVadWorkletCode = (vadConfig) => {
|
|
|
158
158
|
const energyParams = vadConfig?.energyVad || {};
|
|
159
159
|
const smoothing = energyParams.smoothing ?? 0.95;
|
|
160
160
|
const initialNoiseFloor = energyParams.initialNoiseFloor ?? 1e-3;
|
|
161
|
-
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ??
|
|
161
|
+
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ?? 5e-3;
|
|
162
162
|
const noiseFloorAdaptRateLoud = energyParams.noiseFloorAdaptRateLoud ?? 0.01;
|
|
163
163
|
const minSNR = energyParams.minSNR ?? 10;
|
|
164
164
|
const snrRange = energyParams.snrRange ?? 10;
|
|
165
|
-
const minEnergy = energyParams.minEnergy ??
|
|
165
|
+
const minEnergy = energyParams.minEnergy ?? 1e-3;
|
|
166
166
|
return `
|
|
167
167
|
class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
168
168
|
constructor() {
|
|
@@ -226,7 +226,8 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// Ensure noise floor doesn't drop to absolute zero
|
|
229
|
-
|
|
229
|
+
// 0.00005 is approx -86dB, very quiet but prevents SNR explosion
|
|
230
|
+
this.noiseFloor = Math.max(this.noiseFloor, 0.00005);
|
|
230
231
|
|
|
231
232
|
// Calculate Signal-to-Noise Ratio (SNR) in dB using smoothed energy
|
|
232
233
|
const snr = this.energy / (this.noiseFloor + 1e-6);
|
|
@@ -238,8 +239,10 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
238
239
|
let probability = Math.min(1, Math.max(0, (snrDb - this.minSNR) / this.snrRange));
|
|
239
240
|
|
|
240
241
|
// Apply absolute energy threshold
|
|
242
|
+
// We use a soft threshold to avoid abrupt cutting
|
|
241
243
|
if (this.energy < this.minEnergy) {
|
|
242
|
-
|
|
244
|
+
const energyRatio = this.energy / (this.minEnergy + 1e-6);
|
|
245
|
+
probability *= Math.pow(energyRatio, 2); // Quadratic falloff
|
|
243
246
|
}
|
|
244
247
|
|
|
245
248
|
this.port.postMessage({ probability, snr: snrDb, noiseFloor: this.noiseFloor, rms: this.energy });
|
|
@@ -374,11 +377,11 @@ var VADStateMachine = class {
|
|
|
374
377
|
energyVad: {
|
|
375
378
|
smoothing: config?.energyVad?.smoothing ?? 0.95,
|
|
376
379
|
initialNoiseFloor: config?.energyVad?.initialNoiseFloor ?? 1e-3,
|
|
377
|
-
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ??
|
|
380
|
+
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ?? 5e-3,
|
|
378
381
|
noiseFloorAdaptRateLoud: config?.energyVad?.noiseFloorAdaptRateLoud ?? 0.01,
|
|
379
382
|
minSNR: config?.energyVad?.minSNR ?? 10,
|
|
380
383
|
snrRange: config?.energyVad?.snrRange ?? 10,
|
|
381
|
-
minEnergy: config?.energyVad?.minEnergy ??
|
|
384
|
+
minEnergy: config?.energyVad?.minEnergy ?? 1e-3
|
|
382
385
|
}
|
|
383
386
|
};
|
|
384
387
|
this.lastSilenceTime = Date.now();
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "./chunk-WBQAMGXK.mjs";
|
|
2
2
|
import {
|
|
3
3
|
attachProcessingToTrack
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RLZVZ6D6.mjs";
|
|
5
5
|
import {
|
|
6
6
|
createAudioPipeline
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-I5AR7XQD.mjs";
|
|
8
8
|
import {
|
|
9
9
|
VADStateMachine
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GFLVGUTU.mjs";
|
|
11
11
|
import {
|
|
12
12
|
closeAudioContext,
|
|
13
13
|
getAudioContext,
|
|
@@ -21,13 +21,13 @@ import {
|
|
|
21
21
|
getVADPlugin,
|
|
22
22
|
registerNoiseSuppressionPlugin,
|
|
23
23
|
registerVADPlugin
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-3I4OQD2L.mjs";
|
|
25
25
|
import {
|
|
26
26
|
RNNoisePlugin
|
|
27
27
|
} from "./chunk-XO6B3D4A.mjs";
|
|
28
28
|
import {
|
|
29
29
|
EnergyVADPlugin
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-B36JBXOK.mjs";
|
|
31
31
|
export {
|
|
32
32
|
EnergyVADPlugin,
|
|
33
33
|
RNNoisePlugin,
|
|
@@ -127,11 +127,11 @@ var createEnergyVadWorkletCode = (vadConfig) => {
|
|
|
127
127
|
const energyParams = vadConfig?.energyVad || {};
|
|
128
128
|
const smoothing = energyParams.smoothing ?? 0.95;
|
|
129
129
|
const initialNoiseFloor = energyParams.initialNoiseFloor ?? 1e-3;
|
|
130
|
-
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ??
|
|
130
|
+
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ?? 5e-3;
|
|
131
131
|
const noiseFloorAdaptRateLoud = energyParams.noiseFloorAdaptRateLoud ?? 0.01;
|
|
132
132
|
const minSNR = energyParams.minSNR ?? 10;
|
|
133
133
|
const snrRange = energyParams.snrRange ?? 10;
|
|
134
|
-
const minEnergy = energyParams.minEnergy ??
|
|
134
|
+
const minEnergy = energyParams.minEnergy ?? 1e-3;
|
|
135
135
|
return `
|
|
136
136
|
class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
137
137
|
constructor() {
|
|
@@ -195,7 +195,8 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
// Ensure noise floor doesn't drop to absolute zero
|
|
198
|
-
|
|
198
|
+
// 0.00005 is approx -86dB, very quiet but prevents SNR explosion
|
|
199
|
+
this.noiseFloor = Math.max(this.noiseFloor, 0.00005);
|
|
199
200
|
|
|
200
201
|
// Calculate Signal-to-Noise Ratio (SNR) in dB using smoothed energy
|
|
201
202
|
const snr = this.energy / (this.noiseFloor + 1e-6);
|
|
@@ -207,8 +208,10 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
207
208
|
let probability = Math.min(1, Math.max(0, (snrDb - this.minSNR) / this.snrRange));
|
|
208
209
|
|
|
209
210
|
// Apply absolute energy threshold
|
|
211
|
+
// We use a soft threshold to avoid abrupt cutting
|
|
210
212
|
if (this.energy < this.minEnergy) {
|
|
211
|
-
|
|
213
|
+
const energyRatio = this.energy / (this.minEnergy + 1e-6);
|
|
214
|
+
probability *= Math.pow(energyRatio, 2); // Quadratic falloff
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
this.port.postMessage({ probability, snr: snrDb, noiseFloor: this.noiseFloor, rms: this.energy });
|
|
@@ -337,11 +340,11 @@ var VADStateMachine = class {
|
|
|
337
340
|
energyVad: {
|
|
338
341
|
smoothing: config?.energyVad?.smoothing ?? 0.95,
|
|
339
342
|
initialNoiseFloor: config?.energyVad?.initialNoiseFloor ?? 1e-3,
|
|
340
|
-
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ??
|
|
343
|
+
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ?? 5e-3,
|
|
341
344
|
noiseFloorAdaptRateLoud: config?.energyVad?.noiseFloorAdaptRateLoud ?? 0.01,
|
|
342
345
|
minSNR: config?.energyVad?.minSNR ?? 10,
|
|
343
346
|
snrRange: config?.energyVad?.snrRange ?? 10,
|
|
344
|
-
minEnergy: config?.energyVad?.minEnergy ??
|
|
347
|
+
minEnergy: config?.energyVad?.minEnergy ?? 1e-3
|
|
345
348
|
}
|
|
346
349
|
};
|
|
347
350
|
this.lastSilenceTime = Date.now();
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
attachProcessingToTrack
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-RLZVZ6D6.mjs";
|
|
4
|
+
import "../chunk-I5AR7XQD.mjs";
|
|
5
|
+
import "../chunk-GFLVGUTU.mjs";
|
|
6
6
|
import "../chunk-OZ7KMC4S.mjs";
|
|
7
|
-
import "../chunk-
|
|
7
|
+
import "../chunk-3I4OQD2L.mjs";
|
|
8
8
|
import "../chunk-XO6B3D4A.mjs";
|
|
9
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-B36JBXOK.mjs";
|
|
10
10
|
export {
|
|
11
11
|
attachProcessingToTrack
|
|
12
12
|
};
|
|
@@ -125,11 +125,11 @@ var createEnergyVadWorkletCode = (vadConfig) => {
|
|
|
125
125
|
const energyParams = vadConfig?.energyVad || {};
|
|
126
126
|
const smoothing = energyParams.smoothing ?? 0.95;
|
|
127
127
|
const initialNoiseFloor = energyParams.initialNoiseFloor ?? 1e-3;
|
|
128
|
-
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ??
|
|
128
|
+
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ?? 5e-3;
|
|
129
129
|
const noiseFloorAdaptRateLoud = energyParams.noiseFloorAdaptRateLoud ?? 0.01;
|
|
130
130
|
const minSNR = energyParams.minSNR ?? 10;
|
|
131
131
|
const snrRange = energyParams.snrRange ?? 10;
|
|
132
|
-
const minEnergy = energyParams.minEnergy ??
|
|
132
|
+
const minEnergy = energyParams.minEnergy ?? 1e-3;
|
|
133
133
|
return `
|
|
134
134
|
class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
135
135
|
constructor() {
|
|
@@ -193,7 +193,8 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// Ensure noise floor doesn't drop to absolute zero
|
|
196
|
-
|
|
196
|
+
// 0.00005 is approx -86dB, very quiet but prevents SNR explosion
|
|
197
|
+
this.noiseFloor = Math.max(this.noiseFloor, 0.00005);
|
|
197
198
|
|
|
198
199
|
// Calculate Signal-to-Noise Ratio (SNR) in dB using smoothed energy
|
|
199
200
|
const snr = this.energy / (this.noiseFloor + 1e-6);
|
|
@@ -205,8 +206,10 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
205
206
|
let probability = Math.min(1, Math.max(0, (snrDb - this.minSNR) / this.snrRange));
|
|
206
207
|
|
|
207
208
|
// Apply absolute energy threshold
|
|
209
|
+
// We use a soft threshold to avoid abrupt cutting
|
|
208
210
|
if (this.energy < this.minEnergy) {
|
|
209
|
-
|
|
211
|
+
const energyRatio = this.energy / (this.minEnergy + 1e-6);
|
|
212
|
+
probability *= Math.pow(energyRatio, 2); // Quadratic falloff
|
|
210
213
|
}
|
|
211
214
|
|
|
212
215
|
this.port.postMessage({ probability, snr: snrDb, noiseFloor: this.noiseFloor, rms: this.energy });
|
|
@@ -335,11 +338,11 @@ var VADStateMachine = class {
|
|
|
335
338
|
energyVad: {
|
|
336
339
|
smoothing: config?.energyVad?.smoothing ?? 0.95,
|
|
337
340
|
initialNoiseFloor: config?.energyVad?.initialNoiseFloor ?? 1e-3,
|
|
338
|
-
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ??
|
|
341
|
+
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ?? 5e-3,
|
|
339
342
|
noiseFloorAdaptRateLoud: config?.energyVad?.noiseFloorAdaptRateLoud ?? 0.01,
|
|
340
343
|
minSNR: config?.energyVad?.minSNR ?? 10,
|
|
341
344
|
snrRange: config?.energyVad?.snrRange ?? 10,
|
|
342
|
-
minEnergy: config?.energyVad?.minEnergy ??
|
|
345
|
+
minEnergy: config?.energyVad?.minEnergy ?? 1e-3
|
|
343
346
|
}
|
|
344
347
|
};
|
|
345
348
|
this.lastSilenceTime = Date.now();
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createAudioPipeline
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-I5AR7XQD.mjs";
|
|
4
|
+
import "../chunk-GFLVGUTU.mjs";
|
|
5
5
|
import "../chunk-OZ7KMC4S.mjs";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-3I4OQD2L.mjs";
|
|
7
7
|
import "../chunk-XO6B3D4A.mjs";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-B36JBXOK.mjs";
|
|
9
9
|
export {
|
|
10
10
|
createAudioPipeline
|
|
11
11
|
};
|
package/dist/types.d.mts
CHANGED
|
@@ -97,12 +97,12 @@ interface AudioProcessingConfig {
|
|
|
97
97
|
initialNoiseFloor?: number;
|
|
98
98
|
/**
|
|
99
99
|
* Rate at which noise floor adapts to quiet signals (0-1).
|
|
100
|
-
* Default: 0.
|
|
100
|
+
* Default: 0.005 (slower downward drift)
|
|
101
101
|
*/
|
|
102
102
|
noiseFloorAdaptRateQuiet?: number;
|
|
103
103
|
/**
|
|
104
104
|
* Rate at which noise floor adapts to loud signals (0-1).
|
|
105
|
-
* Default: 0.01
|
|
105
|
+
* Default: 0.01
|
|
106
106
|
*/
|
|
107
107
|
noiseFloorAdaptRateLoud?: number;
|
|
108
108
|
/**
|
|
@@ -118,7 +118,7 @@ interface AudioProcessingConfig {
|
|
|
118
118
|
/**
|
|
119
119
|
* Minimum absolute RMS energy to consider as speech.
|
|
120
120
|
* Prevents triggering on very quiet background noise in silent rooms.
|
|
121
|
-
* Default: 0.
|
|
121
|
+
* Default: 0.001 (approx -60dB)
|
|
122
122
|
*/
|
|
123
123
|
minEnergy?: number;
|
|
124
124
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -97,12 +97,12 @@ interface AudioProcessingConfig {
|
|
|
97
97
|
initialNoiseFloor?: number;
|
|
98
98
|
/**
|
|
99
99
|
* Rate at which noise floor adapts to quiet signals (0-1).
|
|
100
|
-
* Default: 0.
|
|
100
|
+
* Default: 0.005 (slower downward drift)
|
|
101
101
|
*/
|
|
102
102
|
noiseFloorAdaptRateQuiet?: number;
|
|
103
103
|
/**
|
|
104
104
|
* Rate at which noise floor adapts to loud signals (0-1).
|
|
105
|
-
* Default: 0.01
|
|
105
|
+
* Default: 0.01
|
|
106
106
|
*/
|
|
107
107
|
noiseFloorAdaptRateLoud?: number;
|
|
108
108
|
/**
|
|
@@ -118,7 +118,7 @@ interface AudioProcessingConfig {
|
|
|
118
118
|
/**
|
|
119
119
|
* Minimum absolute RMS energy to consider as speech.
|
|
120
120
|
* Prevents triggering on very quiet background noise in silent rooms.
|
|
121
|
-
* Default: 0.
|
|
121
|
+
* Default: 0.001 (approx -60dB)
|
|
122
122
|
*/
|
|
123
123
|
minEnergy?: number;
|
|
124
124
|
};
|
package/dist/vad/vad-node.js
CHANGED
|
@@ -27,11 +27,11 @@ var createEnergyVadWorkletCode = (vadConfig) => {
|
|
|
27
27
|
const energyParams = vadConfig?.energyVad || {};
|
|
28
28
|
const smoothing = energyParams.smoothing ?? 0.95;
|
|
29
29
|
const initialNoiseFloor = energyParams.initialNoiseFloor ?? 1e-3;
|
|
30
|
-
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ??
|
|
30
|
+
const noiseFloorAdaptRateQuiet = energyParams.noiseFloorAdaptRateQuiet ?? 5e-3;
|
|
31
31
|
const noiseFloorAdaptRateLoud = energyParams.noiseFloorAdaptRateLoud ?? 0.01;
|
|
32
32
|
const minSNR = energyParams.minSNR ?? 10;
|
|
33
33
|
const snrRange = energyParams.snrRange ?? 10;
|
|
34
|
-
const minEnergy = energyParams.minEnergy ??
|
|
34
|
+
const minEnergy = energyParams.minEnergy ?? 1e-3;
|
|
35
35
|
return `
|
|
36
36
|
class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
37
37
|
constructor() {
|
|
@@ -95,7 +95,8 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// Ensure noise floor doesn't drop to absolute zero
|
|
98
|
-
|
|
98
|
+
// 0.00005 is approx -86dB, very quiet but prevents SNR explosion
|
|
99
|
+
this.noiseFloor = Math.max(this.noiseFloor, 0.00005);
|
|
99
100
|
|
|
100
101
|
// Calculate Signal-to-Noise Ratio (SNR) in dB using smoothed energy
|
|
101
102
|
const snr = this.energy / (this.noiseFloor + 1e-6);
|
|
@@ -107,8 +108,10 @@ class EnergyVadProcessor extends AudioWorkletProcessor {
|
|
|
107
108
|
let probability = Math.min(1, Math.max(0, (snrDb - this.minSNR) / this.snrRange));
|
|
108
109
|
|
|
109
110
|
// Apply absolute energy threshold
|
|
111
|
+
// We use a soft threshold to avoid abrupt cutting
|
|
110
112
|
if (this.energy < this.minEnergy) {
|
|
111
|
-
|
|
113
|
+
const energyRatio = this.energy / (this.minEnergy + 1e-6);
|
|
114
|
+
probability *= Math.pow(energyRatio, 2); // Quadratic falloff
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
this.port.postMessage({ probability, snr: snrDb, noiseFloor: this.noiseFloor, rms: this.energy });
|
package/dist/vad/vad-node.mjs
CHANGED
package/dist/vad/vad-state.js
CHANGED
|
@@ -50,11 +50,11 @@ var VADStateMachine = class {
|
|
|
50
50
|
energyVad: {
|
|
51
51
|
smoothing: config?.energyVad?.smoothing ?? 0.95,
|
|
52
52
|
initialNoiseFloor: config?.energyVad?.initialNoiseFloor ?? 1e-3,
|
|
53
|
-
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ??
|
|
53
|
+
noiseFloorAdaptRateQuiet: config?.energyVad?.noiseFloorAdaptRateQuiet ?? 5e-3,
|
|
54
54
|
noiseFloorAdaptRateLoud: config?.energyVad?.noiseFloorAdaptRateLoud ?? 0.01,
|
|
55
55
|
minSNR: config?.energyVad?.minSNR ?? 10,
|
|
56
56
|
snrRange: config?.energyVad?.snrRange ?? 10,
|
|
57
|
-
minEnergy: config?.energyVad?.minEnergy ??
|
|
57
|
+
minEnergy: config?.energyVad?.minEnergy ?? 1e-3
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
this.lastSilenceTime = Date.now();
|
package/dist/vad/vad-state.mjs
CHANGED