@@ -2,41 +2,68 @@ import EventEmitter from '../util/EventEmitter';
22import { calculateAverage , filterPositiveValues } from '../util/MathUtil' ;
33
44import { DetectionEvents } from './DetectionEvents' ;
5+ import { IVADScore } from './VADAudioAnalyser' ;
56
67/**
78 * The average value VAD needs to be under over a period of time to be considered noise.
89 * @type {number }
910 */
10- const VAD_NOISE_AVG_THRESHOLD = 0.2 ;
11+ const VAD_NOISE_AVG_THRESHOLD : number = 0.2 ;
1112
1213/**
1314 * The average values that audio input need to be over to be considered loud.
1415 * @type {number }
1516 */
16- const NOISY_AUDIO_LEVEL_THRESHOLD = 0.040 ;
17+ const NOISY_AUDIO_LEVEL_THRESHOLD : number = 0.040 ;
1718
1819/**
1920 * The value that a VAD score needs to be under in order for processing to begin.
2021 * @type {number }
2122 */
22- const VAD_SCORE_TRIGGER = 0.2 ;
23+ const VAD_SCORE_TRIGGER : number = 0.2 ;
2324
2425/**
2526 * The value that a VAD score needs to be under in order for processing to begin.
2627 * @type {number }
2728 */
28- const AUDIO_LEVEL_SCORE_TRIGGER = 0.020 ;
29+ const AUDIO_LEVEL_SCORE_TRIGGER : number = 0.020 ;
2930
3031/**
3132 * Time span over which we calculate an average score used to determine if we trigger the event.
3233 * @type {number }
3334 */
34- const PROCESS_TIME_FRAME_SPAN_MS = 1500 ;
35+ const PROCESS_TIME_FRAME_SPAN_MS : number = 1500 ;
3536
3637/**
3738 * Detect if provided VAD score and PCM data is considered noise.
3839 */
3940export default class VADNoiseDetection extends EventEmitter {
41+ /**
42+ * Flag which denotes the current state of the detection service i.e.if there is already a processing operation
43+ * ongoing.
44+ */
45+ private _processing : boolean ;
46+
47+ /**
48+ * Buffer that keeps the VAD scores for a period of time.
49+ */
50+ private _scoreArray : number [ ] ;
51+
52+ /**
53+ * Buffer that keeps audio level samples for a period of time.
54+ */
55+ private _audioLvlArray : number [ ] ;
56+
57+ /**
58+ * Current state of the service, if it's not active no processing will occur.
59+ */
60+ private _active : boolean ;
61+
62+ /**
63+ * Timeout reference for processing VAD scores.
64+ */
65+ private _processTimeout ?: NodeJS . Timeout ;
66+
4067 /**
4168 * Creates <tt>VADNoiseDetection</tt>
4269 *
@@ -66,6 +93,11 @@ export default class VADNoiseDetection extends EventEmitter {
6693 */
6794 this . _active = false ;
6895
96+ /**
97+ * Timeout reference for processing VAD scores.
98+ */
99+ this . _processTimeout = null ;
100+
69101 this . _calculateNoisyScore = this . _calculateNoisyScore . bind ( this ) ;
70102 }
71103
@@ -75,9 +107,9 @@ export default class VADNoiseDetection extends EventEmitter {
75107 * @returns {void }
76108 * @fires VAD_NOISY_DEVICE
77109 */
78- _calculateNoisyScore ( ) {
79- const scoreAvg = calculateAverage ( this . _scoreArray ) ;
80- const audioLevelAvg = calculateAverage ( this . _audioLvlArray ) ;
110+ private _calculateNoisyScore ( ) : void {
111+ const scoreAvg = calculateAverage ( new Float32Array ( this . _scoreArray ) ) ;
112+ const audioLevelAvg = calculateAverage ( new Float32Array ( this . _audioLvlArray ) ) ;
81113
82114 if ( scoreAvg < VAD_NOISE_AVG_THRESHOLD && audioLevelAvg > NOISY_AUDIO_LEVEL_THRESHOLD ) {
83115 this . emit ( DetectionEvents . VAD_NOISY_DEVICE ) ;
@@ -89,34 +121,34 @@ export default class VADNoiseDetection extends EventEmitter {
89121 this . reset ( ) ;
90122 }
91123
92- /**
93- * Record the vad score and average volume in the appropriate buffers.
94- *
95- * @param {number } vadScore
96- * @param {number } avgAudioLvl - average audio level of the PCM sample associated with the VAD score.s
97- */
98- _recordValues ( vadScore , avgAudioLvl ) {
99- this . _scoreArray . push ( vadScore ) ;
100- this . _audioLvlArray . push ( avgAudioLvl ) ;
101- }
102-
103124 /**
104125 * Set the active state of the detection service and notify any listeners.
105126 *
106127 * @param {boolean } active
107128 * @fires DETECTOR_STATE_CHANGE
108129 */
109- _setActiveState ( active ) {
130+ private _setActiveState ( active : boolean ) : void {
110131 this . _active = active ;
111132 this . emit ( DetectionEvents . DETECTOR_STATE_CHANGE , this . _active ) ;
112133 }
113134
135+ /**
136+ * Record the vad score and average volume in the appropriate buffers.
137+ *
138+ * @param {number } vadScore
139+ * @param {number } avgAudioLvl - average audio level of the PCM sample associated with the VAD score.s
140+ */
141+ private _recordValues ( vadScore : number , avgAudioLvl : number ) : void {
142+ this . _scoreArray . push ( vadScore ) ;
143+ this . _audioLvlArray . push ( avgAudioLvl ) ;
144+ }
145+
114146 /**
115147 * Change the state according to the muted status of the tracked device.
116148 *
117149 * @param {boolean } isMuted - Is the device muted or not.
118150 */
119- changeMuteState ( isMuted ) {
151+ public changeMuteState ( isMuted : boolean ) : void {
120152 // This service only needs to run when the microphone is not muted.
121153 this . _setActiveState ( ! isMuted ) ;
122154 this . reset ( ) ;
@@ -127,22 +159,10 @@ export default class VADNoiseDetection extends EventEmitter {
127159 *
128160 * @returns {boolean }
129161 */
130- isActive ( ) {
162+ public isActive ( ) : boolean {
131163 return this . _active ;
132164 }
133165
134- /**
135- * Reset the processing context, clear buffers, cancel the timeout trigger.
136- *
137- * @returns {void }
138- */
139- reset ( ) {
140- this . _processing = false ;
141- this . _scoreArray = [ ] ;
142- this . _audioLvlArray = [ ] ;
143- clearTimeout ( this . _processTimeout ) ;
144- }
145-
146166 /**
147167 * Listens for {@link TrackVADEmitter} events and processes them.
148168 *
@@ -153,26 +173,28 @@ export default class VADNoiseDetection extends EventEmitter {
153173 * @param {string } vadScore.deviceId - Device id of the associated track.
154174 * @listens VAD_SCORE_PUBLISHED
155175 */
156- processVADScore ( vadScore ) {
176+ public processVADScore ( vadScore : IVADScore ) : void {
157177 if ( ! this . _active ) {
158178 return ;
159179 }
160180
161181 // There is a processing phase on going, add score to buffer array.
162182 if ( this . _processing ) {
163- // Filter and calculate sample average so we don't have to process one large array at a time.
164- const posAudioLevels = filterPositiveValues ( vadScore . pcmData ) ;
183+ // Filter and calculate sample average so we don't have to process one large array at a time.
184+ const pcmDataArray = Array . isArray ( vadScore . pcmData ) ? new Float32Array ( vadScore . pcmData ) : vadScore . pcmData ;
185+ const posAudioLevels = filterPositiveValues ( pcmDataArray ) ;
165186
166- this . _recordValues ( vadScore . score , calculateAverage ( posAudioLevels ) ) ;
187+ this . _recordValues ( vadScore . score , calculateAverage ( new Float32Array ( posAudioLevels ) ) ) ;
167188
168189 return ;
169190 }
170191
171192 // If the VAD score for the sample is low and audio level has a high enough level we can start listening for
172193 // noise
173194 if ( vadScore . score < VAD_SCORE_TRIGGER ) {
174- const posAudioLevels = filterPositiveValues ( vadScore . pcmData ) ;
175- const avgAudioLvl = calculateAverage ( posAudioLevels ) ;
195+ const pcmDataArray = Array . isArray ( vadScore . pcmData ) ? new Float32Array ( vadScore . pcmData ) : vadScore . pcmData ;
196+ const posAudioLevels = filterPositiveValues ( pcmDataArray ) ;
197+ const avgAudioLvl = calculateAverage ( new Float32Array ( posAudioLevels ) ) ;
176198
177199 if ( avgAudioLvl > AUDIO_LEVEL_SCORE_TRIGGER ) {
178200 this . _processing = true ;
@@ -183,4 +205,19 @@ export default class VADNoiseDetection extends EventEmitter {
183205 }
184206 }
185207 }
208+
209+ /**
210+ * Reset the processing context, clear buffers, cancel the timeout trigger.
211+ *
212+ * @returns {void }
213+ */
214+ public reset ( ) : void {
215+ this . _processing = false ;
216+ this . _scoreArray = [ ] ;
217+ this . _audioLvlArray = [ ] ;
218+ if ( this . _processTimeout ) {
219+ clearTimeout ( this . _processTimeout ) ;
220+ this . _processTimeout = null ;
221+ }
222+ }
186223}
0 commit comments