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