diff --git a/react/features/base/icons/svg/index.ts b/react/features/base/icons/svg/index.ts index c57991553..67c666f61 100644 --- a/react/features/base/icons/svg/index.ts +++ b/react/features/base/icons/svg/index.ts @@ -88,6 +88,8 @@ export { default as IconMuteEveryone } from './mute-everyone.svg'; export { default as IconMuteEveryoneElse } from './mute-everyone-else.svg'; export { default as IconMuteVideoEveryone } from './mute-video-everyone.svg'; export { default as IconMuteVideoEveryoneElse } from './mute-video-everyone-else.svg'; +export { default as IconNoiseSuppressionOff } from './noise-suppression-off.svg'; +export { default as IconNoiseSuppressionOn } from './noise-suppression-on.svg'; export { default as IconNotificationJoin } from './navigate_next.svg'; export { default as IconOpenInNew } from './open_in_new.svg'; export { default as IconOutlook } from './office365.svg'; diff --git a/react/features/base/icons/svg/noise-suppression-off.svg b/react/features/base/icons/svg/noise-suppression-off.svg new file mode 100644 index 000000000..554f1e918 --- /dev/null +++ b/react/features/base/icons/svg/noise-suppression-off.svg @@ -0,0 +1,4 @@ + + + + diff --git a/react/features/base/icons/svg/noise-suppression-on.svg b/react/features/base/icons/svg/noise-suppression-on.svg new file mode 100644 index 000000000..18b9fea1a --- /dev/null +++ b/react/features/base/icons/svg/noise-suppression-on.svg @@ -0,0 +1,3 @@ + + + diff --git a/react/features/noise-suppression/components/NoiseSuppressionButton.tsx b/react/features/noise-suppression/components/NoiseSuppressionButton.tsx index 3be6f38e6..ccd4d42d8 100644 --- a/react/features/noise-suppression/components/NoiseSuppressionButton.tsx +++ b/react/features/noise-suppression/components/NoiseSuppressionButton.tsx @@ -3,8 +3,8 @@ import { IState } from '../../app/types'; // @ts-ignore import { translate } from '../../base/i18n'; import { - IconShareAudio, - IconStopAudioShare + IconNoiseSuppressionOn, + IconNoiseSuppressionOff } from '../../base/icons/svg/index'; import { connect } from '../../base/redux/functions'; import { @@ -31,10 +31,10 @@ type Props = AbstractButtonProps & { */ class NoiseSuppressionButton extends AbstractButton { accessibilityLabel = 'toolbar.accessibilityLabel.noiseSuppression'; - icon = IconShareAudio; + icon = IconNoiseSuppressionOn; label = 'toolbar.noiseSuppression'; tooltip = 'toolbar.noiseSuppression'; - toggledIcon = IconStopAudioShare; + toggledIcon = IconNoiseSuppressionOff; toggledLabel = 'toolbar.disableNoiseSuppression'; private props: Props; diff --git a/react/features/stream-effects/noise-suppression/NoiseSuppressionEffect.ts b/react/features/stream-effects/noise-suppression/NoiseSuppressionEffect.ts index 0995530db..3b4526a3f 100644 --- a/react/features/stream-effects/noise-suppression/NoiseSuppressionEffect.ts +++ b/react/features/stream-effects/noise-suppression/NoiseSuppressionEffect.ts @@ -29,6 +29,16 @@ export class NoiseSuppressionEffect { */ private _noiseSuppressorNode: AudioWorkletNode; + /** + * Audio track extracted from the original MediaStream to which the effect is applied. + */ + private _originalMediaTrack: MediaStreamTrack; + + /** + * Noise suppressed audio track extracted from the media destination node. + */ + private _outputMediaTrack: MediaStreamTrack; + /** * Effect interface called by source JitsiLocalTrack. * Applies effect that uses a {@code NoiseSuppressor} service initialized with {@code RnnoiseProcessor} @@ -38,10 +48,11 @@ export class NoiseSuppressionEffect { * @returns {MediaStream} - MediaStream containing both audio tracks mixed together. */ startEffect(audioStream: MediaStream) : MediaStream { + this._originalMediaTrack = audioStream.getAudioTracks()[0]; this._audioContext = new AudioContext(); - this._audioSource = this._audioContext.createMediaStreamSource(audioStream); this._audioDestination = this._audioContext.createMediaStreamDestination(); + this._outputMediaTrack = this._audioDestination.stream.getAudioTracks()[0]; const baseUrl = `${getBaseUrl()}libs/`; const workletUrl = `${baseUrl}noise-suppressor-worklet.min.js`; @@ -57,6 +68,13 @@ export class NoiseSuppressionEffect { logger.error('Error while adding audio worklet module: ', error); }); + // Sync the effect track muted state with the original track state. + this._outputMediaTrack.enabled = this._originalMediaTrack.enabled; + + // We enable the audio on the original track because mute/unmute action will only affect the audio destination + // output track from this point on. + this._originalMediaTrack.enabled = true; + return this._audioDestination.stream; } @@ -77,6 +95,9 @@ export class NoiseSuppressionEffect { * @returns {void} */ stopEffect(): void { + // Sync original track muted state with effect state before removing the effect. + this._originalMediaTrack.enabled = this._outputMediaTrack.enabled; + // Technically after this process the Audio Worklet along with it's resources should be garbage collected, // however on chrome there seems to be a problem as described here: // https://bugs.chromium.org/p/chromium/issues/detail?id=1298955