diff --git a/apps/desktop/src/components/CallControls.tsx b/apps/desktop/src/components/CallControls.tsx
index fd932c0..0250fa9 100644
--- a/apps/desktop/src/components/CallControls.tsx
+++ b/apps/desktop/src/components/CallControls.tsx
@@ -9,7 +9,6 @@ import {
MonitorStopIcon,
MusicIcon,
PhoneOffIcon,
- SparklesIcon,
UsersIcon,
VideoIcon,
} from './icons';
@@ -19,7 +18,6 @@ interface Props {
sharing: boolean;
video: boolean;
deafened: boolean;
- noiseSuppression?: boolean;
onToggleMute: () => void;
onToggleShare: () => void;
/** Right-click on the share button opens the quality picker dialog while
@@ -28,7 +26,6 @@ interface Props {
onShareContextMenu?: (e: React.MouseEvent) => void;
onToggleVideo?: () => void;
onToggleDeafen: () => void;
- onToggleNoiseSuppression?: () => void;
onHangup: () => void;
onOpenParticipants?: () => void;
/** Toggle the in-call soundboard popover. Active = panel currently open. */
@@ -48,13 +45,11 @@ export function CallControls({
sharing,
video,
deafened,
- noiseSuppression,
onToggleMute,
onToggleShare,
onShareContextMenu,
onToggleVideo,
onToggleDeafen,
- onToggleNoiseSuppression,
onHangup,
onOpenParticipants,
onToggleSoundboard,
@@ -134,26 +129,6 @@ export function CallControls({
)}
- {onToggleNoiseSuppression && (
-
-
-
- )}
{onToggleSoundboard && (
(null);
- const [noiseSuppression, setNoiseSuppression] = useState(
- () => getAudioSettings().noiseSuppression,
- );
- useEffect(() => subscribeAudioSettings((s) => setNoiseSuppression(s.noiseSuppression)), []);
// Active-speaker auto-focus uses "who most recently started speaking"
// rather than "exactly one speaker" — matches Discord more closely and
// handles the case where two people talk briefly without the focus
@@ -180,7 +170,6 @@ export function InCallPanel({ conversation }: Props) {
sharing={isScreenSharing}
video={isCameraEnabled}
deafened={isDeafened}
- noiseSuppression={noiseSuppression}
onToggleMute={toggleMute}
// 1-click share uses last-saved preset + displaySurface. Right-click
// opens the quality picker for users who want to change settings
@@ -198,14 +187,6 @@ export function InCallPanel({ conversation }: Props) {
}}
onToggleVideo={() => void toggleCamera()}
onToggleDeafen={toggleDeafen}
- // Hot-swap the mic track with new constraints by replaying the
- // input-device switch with the same id. setAudioInputDevice re-reads
- // audioSettings, so flipping noiseSuppression first is enough.
- onToggleNoiseSuppression={() => {
- const prev = getAudioSettings().noiseSuppression;
- updateAudioSettings({ noiseSuppression: !prev });
- void setAudioInputDevice(getAudioSettings().inputDeviceId);
- }}
onOpenParticipants={() => setParticipantsOpen((v) => !v)}
participantsOpen={participantsOpen}
onToggleSoundboard={() => setSoundboardOpen((v) => !v)}
diff --git a/apps/desktop/src/context/CallContext.tsx b/apps/desktop/src/context/CallContext.tsx
index 7a79f2f..e2c7012 100644
--- a/apps/desktop/src/context/CallContext.tsx
+++ b/apps/desktop/src/context/CallContext.tsx
@@ -1235,6 +1235,23 @@ export function CallProvider({ children }: { children: ReactNode }) {
});
}, []);
+ // Hot-swap the mic track when the user flips noiseSuppression in Settings
+ // so the change takes effect without needing to rejoin the call. Tracks
+ // the previous value in a ref so we only re-acquire getUserMedia on
+ // actual transitions (avoid a rebuild on every unrelated settings save).
+ useEffect(() => {
+ let lastNs = getAudioSettings().noiseSuppression;
+ return subscribeAudioSettings((s) => {
+ if (s.noiseSuppression === lastNs) return;
+ lastNs = s.noiseSuppression;
+ const r = roomRef.current;
+ if (!r) return;
+ // setupMicPipeline re-reads audioSettings so the new NS constraint
+ // gets picked up. Same helper as the initial join + retry paths.
+ void setupMicPipeline(r);
+ });
+ }, [setupMicPipeline]);
+
// --- Push-to-talk ------------------------------------------------------
// While PTT is active + we're in a connected call, the mic is held off
// except while the configured key is pressed. Under Tauri we also register
diff --git a/apps/desktop/src/lib/audioSettings.ts b/apps/desktop/src/lib/audioSettings.ts
index 618ca00..a71b452 100644
--- a/apps/desktop/src/lib/audioSettings.ts
+++ b/apps/desktop/src/lib/audioSettings.ts
@@ -41,7 +41,10 @@ const DEFAULTS: AudioSettings = {
inputDeviceId: null,
outputDeviceId: null,
voiceThreshold: 0.03,
- noiseSuppression: true,
+ // Off by default — browser-native NS colours voice audibly on some
+ // mics and is a frequent "why does my voice sound weird" report.
+ // Users who want it enable it explicitly in Settings → Sprache.
+ noiseSuppression: false,
videoBackgroundBlur: false,
ringtoneVolume: 0.9,
};