fix: improve voice quality and add distortion troubleshooting
- Fix RNNoise configuration: use mono instead of stereo, increase VAD threshold to 95% - Adjust quantum settings: increase min-quantum to 64 for stability - Add comprehensive voice distortion troubleshoot script - Create optional disable-auto-rnnoise.nix for problematic setups - The automatic RNNoise filter can cause artifacts, script helps diagnose and fix
This commit is contained in:
parent
52a9d544fc
commit
406acb3daf
3 changed files with 318 additions and 5 deletions
25
modules/sound/disable-auto-rnnoise.nix
Normal file
25
modules/sound/disable-auto-rnnoise.nix
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
# Optional configuration to disable automatic RNNoise filter
|
||||||
|
# This can be imported if the automatic filter causes distortion
|
||||||
|
|
||||||
|
services.pipewire = {
|
||||||
|
extraConfig.pipewire."15-disable-auto-rnnoise" = {
|
||||||
|
"context.modules" = [
|
||||||
|
# Commenting out the automatic RNNoise filter
|
||||||
|
# Users should use EasyEffects for manual noise suppression instead
|
||||||
|
# {
|
||||||
|
# name = "libpipewire-module-filter-chain";
|
||||||
|
# args = {
|
||||||
|
# "node.description" = "Noise Canceling Source";
|
||||||
|
# # ... rest of RNNoise config
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -24,8 +24,8 @@
|
||||||
"context.properties" = {
|
"context.properties" = {
|
||||||
"default.clock.rate" = 48000;
|
"default.clock.rate" = 48000;
|
||||||
"default.clock.quantum" = 1024;
|
"default.clock.quantum" = 1024;
|
||||||
"default.clock.min-quantum" = 32;
|
"default.clock.min-quantum" = 64;
|
||||||
"default.clock.max-quantum" = 2048;
|
"default.clock.max-quantum" = 8192;
|
||||||
};
|
};
|
||||||
|
|
||||||
"context.modules" = [
|
"context.modules" = [
|
||||||
|
@ -40,10 +40,10 @@
|
||||||
type = "ladspa";
|
type = "ladspa";
|
||||||
name = "rnnoise";
|
name = "rnnoise";
|
||||||
plugin = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so";
|
plugin = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so";
|
||||||
label = "noise_suppressor_stereo";
|
label = "noise_suppressor_mono";
|
||||||
control = {
|
control = {
|
||||||
"VAD Threshold (%)" = 50.0;
|
"VAD Threshold (%)" = 95.0;
|
||||||
"VAD Grace Period (ms)" = 200;
|
"VAD Grace Period (ms)" = 100;
|
||||||
"Retroactive VAD Grace (ms)" = 0;
|
"Retroactive VAD Grace (ms)" = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,9 @@
|
||||||
|
|
||||||
# Validation script
|
# Validation script
|
||||||
(writeShellScriptBin "validate-audio" (builtins.readFile ./validate-audio.sh))
|
(writeShellScriptBin "validate-audio" (builtins.readFile ./validate-audio.sh))
|
||||||
|
|
||||||
|
# Troubleshoot script for voice distortion
|
||||||
|
(writeShellScriptBin "troubleshoot-voice-distortion" (builtins.readFile ./troubleshoot-voice-distortion.sh))
|
||||||
|
|
||||||
# Optional: Professional audio tools
|
# Optional: Professional audio tools
|
||||||
# qjackctl # JACK control GUI (for JACK applications)
|
# qjackctl # JACK control GUI (for JACK applications)
|
||||||
|
|
285
modules/sound/troubleshoot-voice-distortion.sh
Executable file
285
modules/sound/troubleshoot-voice-distortion.sh
Executable file
|
@ -0,0 +1,285 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Voice Distortion Troubleshoot Script
|
||||||
|
# This script helps diagnose and fix voice distortion issues in PipeWire
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "🎤 Voice Distortion Troubleshoot Tool"
|
||||||
|
echo "===================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
success() {
|
||||||
|
echo -e "${GREEN}✅ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}❌ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
highlight() {
|
||||||
|
echo -e "${CYAN}🔧 $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Let's diagnose your voice distortion issue step by step..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Check current audio settings
|
||||||
|
echo "1. Current Audio Configuration"
|
||||||
|
echo "=============================="
|
||||||
|
|
||||||
|
if command -v wpctl >/dev/null 2>&1; then
|
||||||
|
echo "Default devices:"
|
||||||
|
wpctl status | head -20
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get default source
|
||||||
|
DEFAULT_SOURCE=$(wpctl inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | grep "node.name" | head -1 | sed 's/.*"\(.*\)".*/\1/' || echo "unknown")
|
||||||
|
info "Current default source: $DEFAULT_SOURCE"
|
||||||
|
|
||||||
|
# Check sample rate
|
||||||
|
CURRENT_RATE=$(pw-metadata -n settings | grep "clock.rate" | awk '{print $3}' || echo "unknown")
|
||||||
|
info "Current sample rate: $CURRENT_RATE Hz"
|
||||||
|
|
||||||
|
# Check buffer size
|
||||||
|
CURRENT_QUANTUM=$(pw-metadata -n settings | grep "clock.quantum" | awk '{print $3}' || echo "unknown")
|
||||||
|
info "Current buffer size: $CURRENT_QUANTUM samples"
|
||||||
|
|
||||||
|
else
|
||||||
|
error "wpctl not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. Check for common distortion causes
|
||||||
|
echo "2. Distortion Diagnosis"
|
||||||
|
echo "======================"
|
||||||
|
|
||||||
|
# Check if using RNNoise filter
|
||||||
|
if pw-dump 2>/dev/null | jq -r '.[] | select(.info.props."node.name" == "rnnoise_source")' | grep -q "rnnoise"; then
|
||||||
|
warning "You're using the RNNoise filter chain - this might be causing distortion"
|
||||||
|
echo " The automatic filter chain can sometimes cause artifacts"
|
||||||
|
else
|
||||||
|
info "Not using automatic RNNoise filter"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for high CPU usage
|
||||||
|
if command -v pw-top >/dev/null 2>&1; then
|
||||||
|
highlight "Checking PipeWire performance (5 seconds)..."
|
||||||
|
timeout 5 pw-top --batch-mode 2>/dev/null | tail -10 || warning "Could not check performance"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check input levels
|
||||||
|
if command -v wpctl >/dev/null 2>&1; then
|
||||||
|
echo ""
|
||||||
|
echo "Current microphone volume levels:"
|
||||||
|
wpctl get-volume @DEFAULT_AUDIO_SOURCE@ || warning "Could not get volume info"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Quick fixes
|
||||||
|
echo "3. Quick Fixes to Try"
|
||||||
|
echo "===================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Choose a solution to try:"
|
||||||
|
echo ""
|
||||||
|
echo "A) Disable automatic RNNoise filter (recommended first step)"
|
||||||
|
echo "B) Lower microphone input gain"
|
||||||
|
echo "C) Reduce buffer size for lower latency"
|
||||||
|
echo "D) Use EasyEffects instead of filter chain"
|
||||||
|
echo "E) Reset to safe audio settings"
|
||||||
|
echo "F) Test different sample rates"
|
||||||
|
echo "G) Monitor audio in real-time"
|
||||||
|
echo "H) All of the above (comprehensive fix)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Enter your choice (A-H): " choice
|
||||||
|
|
||||||
|
case $choice in
|
||||||
|
A|a)
|
||||||
|
echo ""
|
||||||
|
highlight "Disabling automatic RNNoise filter..."
|
||||||
|
if pw-dump 2>/dev/null | jq -r '.[] | select(.info.props."node.name" == "rnnoise_source") | .id' | while read id; do
|
||||||
|
echo "Removing filter node $id"
|
||||||
|
pw-cli destroy "$id" 2>/dev/null || warning "Could not remove filter $id"
|
||||||
|
done; then
|
||||||
|
success "RNNoise filter disabled"
|
||||||
|
echo "Try speaking now. If distortion is gone, use EasyEffects for noise suppression instead."
|
||||||
|
else
|
||||||
|
warning "Could not disable RNNoise filter automatically"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
B|b)
|
||||||
|
echo ""
|
||||||
|
highlight "Lowering microphone input gain to 50%..."
|
||||||
|
wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 50%
|
||||||
|
success "Microphone gain reduced to 50%"
|
||||||
|
echo "Test your voice now. Adjust further if needed with: wpctl set-volume @DEFAULT_AUDIO_SOURCE@ X%"
|
||||||
|
;;
|
||||||
|
|
||||||
|
C|c)
|
||||||
|
echo ""
|
||||||
|
highlight "Setting lower buffer size for reduced latency..."
|
||||||
|
pw-metadata -n settings 0 clock.force-quantum 512
|
||||||
|
success "Buffer size set to 512 samples"
|
||||||
|
echo "This should reduce latency but may increase CPU usage"
|
||||||
|
;;
|
||||||
|
|
||||||
|
D|d)
|
||||||
|
echo ""
|
||||||
|
highlight "Launching EasyEffects for manual noise suppression..."
|
||||||
|
if command -v easyeffects >/dev/null 2>&1; then
|
||||||
|
easyeffects &
|
||||||
|
success "EasyEffects launched"
|
||||||
|
echo ""
|
||||||
|
echo "In EasyEffects:"
|
||||||
|
echo "1. Go to 'Input' tab"
|
||||||
|
echo "2. Add 'RNNoise' effect"
|
||||||
|
echo "3. Set 'VAD Threshold' to 95% (very conservative)"
|
||||||
|
echo "4. Set 'Wet' signal to 50-70% (not 100%)"
|
||||||
|
echo "5. Disable any other aggressive processing"
|
||||||
|
else
|
||||||
|
error "EasyEffects not available"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
E|e)
|
||||||
|
echo ""
|
||||||
|
highlight "Resetting to safe audio settings..."
|
||||||
|
# Reset quantum
|
||||||
|
pw-metadata -n settings 0 clock.force-quantum 0
|
||||||
|
# Reset rate
|
||||||
|
pw-metadata -n settings 0 clock.force-rate 0
|
||||||
|
# Set reasonable volume
|
||||||
|
wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 70%
|
||||||
|
# Restart audio services
|
||||||
|
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||||
|
success "Audio settings reset to defaults"
|
||||||
|
echo "Wait 5 seconds for services to restart, then test your voice"
|
||||||
|
;;
|
||||||
|
|
||||||
|
F|f)
|
||||||
|
echo ""
|
||||||
|
highlight "Testing different sample rates..."
|
||||||
|
echo "Current rate: $(pw-metadata -n settings | grep clock.rate | awk '{print $3}' || echo 'default')"
|
||||||
|
echo ""
|
||||||
|
echo "Trying 44100 Hz..."
|
||||||
|
pw-metadata -n settings 0 clock.force-rate 44100
|
||||||
|
sleep 2
|
||||||
|
echo "Test your voice now. Press Enter to continue..."
|
||||||
|
read
|
||||||
|
echo "Trying 48000 Hz..."
|
||||||
|
pw-metadata -n settings 0 clock.force-rate 48000
|
||||||
|
sleep 2
|
||||||
|
echo "Test your voice now. Press Enter to continue..."
|
||||||
|
read
|
||||||
|
echo "Back to automatic rate..."
|
||||||
|
pw-metadata -n settings 0 clock.force-rate 0
|
||||||
|
success "Rate testing complete"
|
||||||
|
;;
|
||||||
|
|
||||||
|
G|g)
|
||||||
|
echo ""
|
||||||
|
highlight "Starting real-time audio monitoring..."
|
||||||
|
echo "Press Ctrl+C to stop monitoring"
|
||||||
|
echo ""
|
||||||
|
if command -v pw-top >/dev/null 2>&1; then
|
||||||
|
pw-top
|
||||||
|
else
|
||||||
|
echo "Monitoring with wpctl status (updating every 2 seconds):"
|
||||||
|
while true; do
|
||||||
|
clear
|
||||||
|
echo "=== PipeWire Status ==="
|
||||||
|
wpctl status
|
||||||
|
echo ""
|
||||||
|
echo "=== Microphone Volume ==="
|
||||||
|
wpctl get-volume @DEFAULT_AUDIO_SOURCE@
|
||||||
|
echo ""
|
||||||
|
echo "Press Ctrl+C to stop"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
H|h)
|
||||||
|
echo ""
|
||||||
|
highlight "Running comprehensive fix..."
|
||||||
|
|
||||||
|
# Step 1: Disable RNNoise filter
|
||||||
|
echo "1/6: Disabling automatic RNNoise filter..."
|
||||||
|
pw-dump 2>/dev/null | jq -r '.[] | select(.info.props."node.name" == "rnnoise_source") | .id' | while read id; do
|
||||||
|
pw-cli destroy "$id" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
# Step 2: Reset audio settings
|
||||||
|
echo "2/6: Resetting audio settings..."
|
||||||
|
pw-metadata -n settings 0 clock.force-quantum 0
|
||||||
|
pw-metadata -n settings 0 clock.force-rate 0
|
||||||
|
|
||||||
|
# Step 3: Set conservative volume
|
||||||
|
echo "3/6: Setting conservative microphone gain..."
|
||||||
|
wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 60%
|
||||||
|
|
||||||
|
# Step 4: Restart services
|
||||||
|
echo "4/6: Restarting audio services..."
|
||||||
|
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||||
|
|
||||||
|
# Step 5: Wait for restart
|
||||||
|
echo "5/6: Waiting for services to stabilize..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Step 6: Launch EasyEffects
|
||||||
|
echo "6/6: Launching EasyEffects for manual control..."
|
||||||
|
if command -v easyeffects >/dev/null 2>&1; then
|
||||||
|
easyeffects &
|
||||||
|
success "Comprehensive fix applied!"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo "1. Test your voice without any effects first"
|
||||||
|
echo "2. In EasyEffects, gradually add noise suppression:"
|
||||||
|
echo " - Start with RNNoise at 50% wet signal"
|
||||||
|
echo " - Use VAD threshold of 95% or higher"
|
||||||
|
echo " - Avoid aggressive compression or EQ"
|
||||||
|
echo "3. If still distorted, try lowering input gain further"
|
||||||
|
else
|
||||||
|
warning "EasyEffects not available for manual control"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
error "Invalid choice"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🎯 Additional Tips to Prevent Distortion:"
|
||||||
|
echo "========================================="
|
||||||
|
echo ""
|
||||||
|
echo "• Keep microphone gain below 80% to avoid clipping"
|
||||||
|
echo "• Use RNNoise conservatively (50-70% wet signal, not 100%)"
|
||||||
|
echo "• Check for background applications using audio"
|
||||||
|
echo "• Ensure your microphone hardware supports 48kHz"
|
||||||
|
echo "• Consider using a better quality microphone"
|
||||||
|
echo "• Avoid stacking multiple noise reduction effects"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Run this script again anytime with: troubleshoot-voice-distortion"
|
Loading…
Add table
Add a link
Reference in a new issue