@@ -2,7 +2,8 @@ import React from 'react';
22import { Features , LocalAudioStream } from '@azure/communication-calling' ;
33import {
44 EchoCancellationEffect ,
5- DeepNoiseSuppressionEffect
5+ DeepNoiseSuppressionEffect ,
6+ VoiceIsolationEffect
67} from '@azure/communication-calling-effects' ;
78import { Dropdown , PrimaryButton } from '@fluentui/react' ;
89
@@ -41,10 +42,17 @@ export default class AudioEffectsContainer extends React.Component {
4142 noiseSuppressionList : [ ] ,
4243 currentSelected : undefined
4344 } ,
45+ voiceIsolation : {
46+ startLoading : false ,
47+ stopLoading : false ,
48+ voiceIsolationList : [ ] ,
49+ currentSelected : undefined
50+ } ,
4451 activeEffects : {
4552 autoGainControl : [ ] ,
4653 echoCancellation : [ ] ,
47- noiseSuppression : [ ]
54+ noiseSuppression : [ ] ,
55+ voiceIsolation : [ ]
4856 }
4957 } ;
5058
@@ -123,6 +131,7 @@ export default class AudioEffectsContainer extends React.Component {
123131 const autoGainControlList = [ ] ;
124132 const echoCancellationList = [ ] ;
125133 const noiseSuppressionList = [ ] ;
134+ const voiceIsolationList = [ ] ;
126135
127136 if ( this . localAudioStreamFeatureApi ) {
128137 if ( await this . localAudioStreamFeatureApi . isSupported ( 'BrowserAutoGainControl' ) ) {
@@ -167,6 +176,15 @@ export default class AudioEffectsContainer extends React.Component {
167176 } ) ;
168177 }
169178
179+ const voiceIsolation = new VoiceIsolationEffect ( ) ;
180+ if ( await this . localAudioStreamFeatureApi . isSupported ( voiceIsolation ) ) {
181+ supported . push ( voiceIsolation ) ;
182+ voiceIsolationList . push ( {
183+ key : voiceIsolation . name ,
184+ text : 'Voice Isolation'
185+ } ) ;
186+ }
187+
170188 this . setState ( {
171189 supportedAudioEffects : [ ...supported ] ,
172190 supportedAudioEffectsPopulated : true ,
@@ -182,10 +200,15 @@ export default class AudioEffectsContainer extends React.Component {
182200 ...this . state . noiseSuppression ,
183201 noiseSuppressionList
184202 } ,
203+ voiceIsolation : {
204+ ...this . state . voiceIsolation ,
205+ voiceIsolationList
206+ } ,
185207 activeEffects : {
186208 autoGainControl : this . localAudioStreamFeatureApi ?. activeEffects ?. autoGainControl ,
187209 echoCancellation : this . localAudioStreamFeatureApi ?. activeEffects ?. echoCancellation ,
188- noiseSuppression : this . localAudioStreamFeatureApi ?. activeEffects ?. noiseSuppression
210+ noiseSuppression : this . localAudioStreamFeatureApi ?. activeEffects ?. noiseSuppression ,
211+ voiceIsolation : this . localAudioStreamFeatureApi ?. activeEffects ?. voiceIsolation
189212 }
190213 } ) ;
191214 }
@@ -377,6 +400,64 @@ export default class AudioEffectsContainer extends React.Component {
377400 }
378401 /* ------------ NS control functions - end ---------------- */
379402
403+ /* ------------ VI control functions - start ---------------- */
404+ viSelectionChanged ( e , item ) {
405+ const effect = this . findEffectFromSupportedList ( item . key ) ;
406+ if ( effect ) {
407+ this . setState ( {
408+ voiceIsolation : {
409+ ...this . state . voiceIsolation ,
410+ currentSelected : effect
411+ }
412+ } ) ;
413+ }
414+ }
415+
416+ async startVi ( ) {
417+ this . setState ( {
418+ voiceIsolation : {
419+ ...this . state . voiceIsolation ,
420+ startLoading : true
421+ }
422+ } ) ;
423+
424+ if ( this . localAudioStreamFeatureApi ) {
425+ await this . localAudioStreamFeatureApi . startEffects ( {
426+ voiceIsolation : this . state . voiceIsolation . currentSelected
427+ } ) ;
428+ }
429+
430+ this . setState ( {
431+ voiceIsolation : {
432+ ...this . state . voiceIsolation ,
433+ startLoading : false
434+ }
435+ } ) ;
436+ }
437+
438+ async stopVi ( ) {
439+ this . setState ( {
440+ voiceIsolation : {
441+ ...this . state . voiceIsolation ,
442+ stopLoading : true
443+ }
444+ } ) ;
445+
446+ if ( this . localAudioStreamFeatureApi ) {
447+ await this . localAudioStreamFeatureApi . stopEffects ( {
448+ voiceIsolation : true
449+ } ) ;
450+ }
451+
452+ this . setState ( {
453+ voiceIsolation : {
454+ ...this . state . voiceIsolation ,
455+ stopLoading : false
456+ }
457+ } ) ;
458+ }
459+ /* ------------ VI control functions - end ---------------- */
460+
380461 render ( ) {
381462 return (
382463 < >
@@ -403,6 +484,11 @@ export default class AudioEffectsContainer extends React.Component {
403484 { this . state . activeEffects . noiseSuppression [ 0 ] }
404485 </ div >
405486 }
487+ { this . state . activeEffects . voiceIsolation ?. length > 0 &&
488+ < div className = 'ms-Grid-col ms-sm4 ms-md4 ms-lg4' >
489+ { this . state . activeEffects . voiceIsolation [ 0 ] }
490+ </ div >
491+ }
406492 </ div >
407493 < div className = 'ms-Grid-row' >
408494 < div className = 'ms-Grid-col ms-sm12 ms-md12 ms-lg12' >
@@ -484,6 +570,33 @@ export default class AudioEffectsContainer extends React.Component {
484570 </ PrimaryButton >
485571 </ div >
486572 </ div >
573+
574+ < div className = 'ms-Grid-row' >
575+ < div className = 'ms-Grid-col ms-sm12 ms-md12 ms-lg12' >
576+ < Dropdown
577+ label = 'Voice Isolation'
578+ onChange = { ( e , item ) => this . viSelectionChanged ( e , item ) }
579+ options = { this . state . voiceIsolation . voiceIsolationList }
580+ placeholder = { 'Select an option' }
581+ styles = { { dropdown : { width : 300 , color : 'black' } , label : { color : 'white' } } }
582+ />
583+ </ div >
584+ < div className = 'ms-Grid-col ms-sm12 ms-md12 ms-lg12' >
585+ < PrimaryButton
586+ className = 'secondary-button mt-2'
587+ onClick = { ( ) => this . startNs ( ) }
588+ >
589+ { this . state . noiseSuppression . startLoading ? < LoadingSpinner /> : 'Start NS' }
590+ </ PrimaryButton >
591+
592+ < PrimaryButton
593+ className = 'secondary-button mt-2'
594+ onClick = { ( ) => this . stopNs ( ) }
595+ >
596+ { this . state . noiseSuppression . stopLoading ? < LoadingSpinner /> : 'Stop NS' }
597+ </ PrimaryButton >
598+ </ div >
599+ </ div >
487600 </ div >
488601 :
489602 < div >
0 commit comments