From d387d85dac99c79b070c27747f7b1025007339ff Mon Sep 17 00:00:00 2001 From: ServerBob Date: Thu, 5 Mar 2026 08:43:56 +0000 Subject: [PATCH] fix(voice): stabilize deepfilter input and enforce legacy AGC constraints --- .../src/components/voice-provider/index.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps/client/src/components/voice-provider/index.tsx b/apps/client/src/components/voice-provider/index.tsx index 0bed86b..11c7846 100644 --- a/apps/client/src/components/voice-provider/index.tsx +++ b/apps/client/src/components/voice-provider/index.tsx @@ -139,6 +139,15 @@ const buildMicConstraints = (devices: TDeviceSettings): MediaTrackConstraints => legacy.googEchoCancellation = true; legacy.googAutoGainControl = true; legacy.googTypingNoiseDetection = true; + } else { + // Chromium variants can still honor legacy goog* constraints. + // Mirror our intended DSP state explicitly to avoid implicit AGC. + const legacy = constraints as unknown as Record; + legacy.googHighpassFilter = false; + legacy.googNoiseSuppression = !!constraints.noiseSuppression; + legacy.googEchoCancellation = !!constraints.echoCancellation; + legacy.googAutoGainControl = !!constraints.autoGainControl; + legacy.googTypingNoiseDetection = false; } return constraints; @@ -410,6 +419,7 @@ const VoiceProvider = memo(({ children }: TVoiceProviderProps) => { const dest = ctx.createMediaStreamDestination(); let current: AudioNode = source; + let preGainNode: GainNode | undefined; let deepFilterNode: AudioWorkletNode | undefined; let deepFilterCore: DeepFilterNet3Core | undefined; let rnnoiseNode: AudioWorkletNode | undefined; @@ -420,6 +430,7 @@ const VoiceProvider = memo(({ children }: TVoiceProviderProps) => { gateNode?.disconnect(); rnnoiseNode?.disconnect(); deepFilterNode?.disconnect(); + preGainNode?.disconnect(); source.disconnect(); dest.disconnect(); deepFilterCore?.destroy?.(); @@ -438,6 +449,13 @@ const VoiceProvider = memo(({ children }: TVoiceProviderProps) => { try { if (useDeepFilterNet) { + // Mild pre-gain helps keep quiet speech above the model floor + // without aggressively boosting background noise. + preGainNode = ctx.createGain(); + preGainNode.gain.value = 1.35; + current.connect(preGainNode); + current = preGainNode; + const deepFilterSuppression = sensitivityToDeepFilterLevel( devices.voiceSensitivity ?? 70 );