Add comprehensive PipeWire audio configuration with noise suppression
- Add modules/sound/pipewire.nix with full PipeWire stack - Include RNNoise AI-powered noise suppression - Add EasyEffects with pre-configured presets for mic and speakers - Include multiple GUI applications (pavucontrol, helvum, qpwgraph, pwvucontrol) - Add helper scripts: audio-setup, microphone-test, validate-audio - Optimize for low-latency real-time audio processing - Enable auto-start and desktop integration - Remove duplicate PipeWire configs from hardware-co.nix and users/common.nix - Import sound module through desktop/common.nix for all desktop machines
This commit is contained in:
parent
54e80f5c13
commit
9c9dcdc196
8 changed files with 1416 additions and 13 deletions
|
@ -19,10 +19,4 @@
|
|||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
# Audio system (PipeWire)
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
../sound/pipewire.nix
|
||||
];
|
||||
|
||||
# Common desktop configuration shared across all environments
|
||||
|
||||
# XDG Portal configuration for Wayland/X11 compatibility
|
||||
|
|
273
modules/sound/README.md
Normal file
273
modules/sound/README.md
Normal file
|
@ -0,0 +1,273 @@
|
|||
# PipeWire with WirePlumber Configuration
|
||||
|
||||
This module provides a comprehensive PipeWire setup with WirePlumber session management, noise suppression, and GUI tools for audio management.
|
||||
|
||||
## Features
|
||||
|
||||
### Core Audio Stack
|
||||
|
||||
- **PipeWire**: Modern audio server with low latency
|
||||
- **WirePlumber**: Session manager for device management and routing
|
||||
- **ALSA/PulseAudio/JACK Compatibility**: Works with all major audio APIs
|
||||
- **Real-time Processing**: RTKit integration for optimal performance
|
||||
|
||||
### Noise Suppression
|
||||
|
||||
- **RNNoise Plugin**: AI-powered noise suppression for microphones
|
||||
- **EasyEffects Integration**: GUI for managing audio effects
|
||||
- **Automatic Filter Chain**: Pre-configured noise suppression pipeline
|
||||
|
||||
### GUI Applications Included
|
||||
|
||||
- **EasyEffects**: Modern audio effects processor with noise suppression
|
||||
- **PulseAudio Volume Control (pavucontrol)**: Volume and device management
|
||||
- **Helvum**: Graphical PipeWire patchbay for routing
|
||||
- **qpwgraph**: Qt-based PipeWire graph manager
|
||||
- **pwvucontrol**: Native PipeWire volume control
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Import the Module
|
||||
|
||||
Add to your NixOS configuration:
|
||||
|
||||
```nix
|
||||
imports = [
|
||||
./modules/sound/pipewire.nix
|
||||
];
|
||||
```
|
||||
|
||||
### 2. Rebuild System
|
||||
|
||||
```bash
|
||||
sudo nixos-rebuild switch
|
||||
```
|
||||
|
||||
### 3. Verify Installation
|
||||
|
||||
```bash
|
||||
# Check if PipeWire is running
|
||||
systemctl --user status pipewire
|
||||
|
||||
# Launch the audio setup helper
|
||||
audio-setup
|
||||
|
||||
# Test microphone with noise suppression
|
||||
microphone-test
|
||||
```
|
||||
|
||||
## Using Noise Suppression
|
||||
|
||||
### Method 1: EasyEffects (Recommended)
|
||||
|
||||
1. Launch EasyEffects: `easyeffects` or use the application menu
|
||||
2. Go to the "Input" tab
|
||||
3. Load the pre-configured "Microphone_Noise_Suppression" preset
|
||||
4. Enable the RNNoise effect
|
||||
5. Adjust the "VAD Threshold" (Voice Activity Detection) as needed
|
||||
|
||||
### Method 2: PipeWire Filter Chain (Automatic)
|
||||
|
||||
The configuration includes an automatic RNNoise filter chain that creates a "Noise Canceling Source" device. This appears as a separate microphone input in audio applications.
|
||||
|
||||
## GUI Applications Usage
|
||||
|
||||
### EasyEffects
|
||||
|
||||
- **Purpose**: Real-time audio effects and noise suppression
|
||||
- **Launch**: `easyeffects` or from application menu
|
||||
- **Features**: RNNoise, equalizer, compressor, limiter, gate
|
||||
- **Auto-start**: Configured to start with desktop session
|
||||
|
||||
### Volume Controls
|
||||
|
||||
- **pavucontrol**: Traditional PulseAudio-style interface
|
||||
- **pwvucontrol**: Native PipeWire interface
|
||||
- **Usage**: Control volumes, switch devices, manage streams
|
||||
|
||||
### Audio Routing
|
||||
|
||||
- **Helvum**: Visual patchbay for connecting audio streams
|
||||
- **qpwgraph**: Advanced graph-based routing interface
|
||||
- **Usage**: Route audio between applications and devices
|
||||
|
||||
## Command-Line Tools
|
||||
|
||||
### System Status
|
||||
|
||||
```bash
|
||||
# PipeWire status overview
|
||||
wpctl status
|
||||
|
||||
# Real-time monitoring
|
||||
pw-top
|
||||
|
||||
# Inspect audio objects
|
||||
pw-dump | jq '.'
|
||||
|
||||
# Show metadata
|
||||
pw-metadata
|
||||
```
|
||||
|
||||
### Device Management
|
||||
|
||||
```bash
|
||||
# List devices
|
||||
wpctl status
|
||||
|
||||
# Set default sink
|
||||
wpctl set-default SINK_ID
|
||||
|
||||
# Set volume
|
||||
wpctl set-volume SOURCE_ID 80%
|
||||
|
||||
# Mute/unmute
|
||||
wpctl set-mute SOURCE_ID toggle
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Test microphone
|
||||
microphone-test
|
||||
|
||||
# Record and playback test
|
||||
arecord -d 5 -f cd test.wav && aplay test.wav
|
||||
```
|
||||
|
||||
## Configuration Details
|
||||
|
||||
### Audio Quality Settings
|
||||
|
||||
- **Sample Rate**: 48kHz (professional audio standard)
|
||||
- **Buffer Size**: 1024 samples (balanced latency/stability)
|
||||
- **Resampling Quality**: High (level 4)
|
||||
- **Channels**: Stereo support with spatial audio capabilities
|
||||
|
||||
### Noise Suppression Settings
|
||||
|
||||
- **RNNoise VAD Threshold**: 50% (adjustable)
|
||||
- **VAD Grace Period**: 200ms
|
||||
- **Noise Reduction**: 80% wet signal
|
||||
- **Processing**: Real-time with minimal latency
|
||||
|
||||
### Performance Optimizations
|
||||
|
||||
- **Real-time Scheduling**: RTKit enabled
|
||||
- **Memory Locking**: Enabled for critical processes
|
||||
- **CPU Affinity**: Configurable per audio thread
|
||||
- **Quantum Settings**: Optimized for low latency
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### No Audio Output
|
||||
|
||||
```bash
|
||||
# Check PipeWire is running
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
|
||||
# Check default devices
|
||||
wpctl status
|
||||
```
|
||||
|
||||
#### Microphone Not Working
|
||||
|
||||
```bash
|
||||
# Test microphone detection
|
||||
arecord -l
|
||||
|
||||
# Check permissions
|
||||
groups $USER | grep audio
|
||||
```
|
||||
|
||||
#### High CPU Usage
|
||||
|
||||
```bash
|
||||
# Monitor PipeWire performance
|
||||
pw-top
|
||||
|
||||
# Check buffer settings
|
||||
pw-metadata | grep quantum
|
||||
```
|
||||
|
||||
#### Noise Suppression Not Working
|
||||
|
||||
1. Verify RNNoise plugin is loaded: `ladspa-ls | grep -i noise`
|
||||
2. Check EasyEffects preset is loaded
|
||||
3. Ensure correct input device is selected
|
||||
4. Adjust VAD threshold in EasyEffects
|
||||
|
||||
### Reset Configuration
|
||||
|
||||
```bash
|
||||
# Reset user PipeWire configuration
|
||||
rm -rf ~/.config/pipewire ~/.config/easyeffects
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Filter Chains
|
||||
|
||||
Edit `/etc/pipewire/pipewire.conf.d/10-noise-suppression.conf` to modify the RNNoise filter chain parameters.
|
||||
|
||||
### Device-Specific Settings
|
||||
|
||||
Add rules to `/etc/wireplumber/wireplumber.conf.d/51-noise-suppression.conf` for specific audio devices.
|
||||
|
||||
### EasyEffects Presets
|
||||
|
||||
Custom presets are stored in `/etc/easyeffects/` and can be modified or extended.
|
||||
|
||||
## Integration with Applications
|
||||
|
||||
### Discord/Zoom/Teams
|
||||
|
||||
1. Set default microphone to "Noise Canceling Source" in application settings
|
||||
2. Or use EasyEffects on the regular microphone input
|
||||
3. Adjust noise gate and compressor settings as needed
|
||||
|
||||
### OBS Studio
|
||||
|
||||
1. Add "Application Audio Capture" source
|
||||
2. Select the noise-suppressed microphone device
|
||||
3. Or use OBS's built-in noise suppression with the processed audio
|
||||
|
||||
### Music Production (JACK)
|
||||
|
||||
```bash
|
||||
# Start JACK mode if needed
|
||||
pw-jack your-daw-application
|
||||
```
|
||||
|
||||
## Updates and Maintenance
|
||||
|
||||
### Updating Configuration
|
||||
|
||||
After modifying the Nix configuration:
|
||||
|
||||
```bash
|
||||
sudo nixos-rebuild switch
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
```
|
||||
|
||||
### Monitoring Performance
|
||||
|
||||
Regular checks recommended:
|
||||
|
||||
```bash
|
||||
# Weekly performance check
|
||||
pw-top
|
||||
|
||||
# Monthly configuration review
|
||||
audio-setup
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [PipeWire Documentation](https://docs.pipewire.org/)
|
||||
- [WirePlumber Documentation](https://pipewire.pages.freedesktop.org/wireplumber/)
|
||||
- [EasyEffects Documentation](https://github.com/wwmm/easyeffects)
|
||||
- [RNNoise Project](https://jmvalin.ca/demo/rnnoise/)
|
212
modules/sound/audio-desktop-integration.nix
Normal file
212
modules/sound/audio-desktop-integration.nix
Normal file
|
@ -0,0 +1,212 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
# Desktop entries for quick audio management access
|
||||
environment.etc = {
|
||||
# Desktop entry for EasyEffects
|
||||
"xdg/autostart/easyeffects.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Name=EasyEffects
|
||||
Comment=Audio effects for PipeWire applications
|
||||
Icon=easyeffects
|
||||
Exec=easyeffects --gapplication-service
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=AudioVideo;Audio;
|
||||
StartupNotify=true
|
||||
X-GNOME-Autostart-enabled=true
|
||||
'';
|
||||
|
||||
# Custom desktop entry for audio control center
|
||||
"applications/audio-control-center.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=Audio Control Center
|
||||
Comment=Centralized audio management
|
||||
Icon=audio-volume-high
|
||||
Categories=AudioVideo;Audio;Settings;
|
||||
Keywords=audio;sound;volume;pipewire;pulseaudio;
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
Exec=sh -c 'if command -v easyeffects >/dev/null 2>&1; then easyeffects; elif command -v pavucontrol >/dev/null 2>&1; then pavucontrol; elif command -v pwvucontrol >/dev/null 2>&1; then pwvucontrol; else helvum; fi'
|
||||
'';
|
||||
};
|
||||
|
||||
# Create a script for easy audio management
|
||||
environment.systemPackages = with pkgs; [
|
||||
(writeShellScriptBin "audio-setup" ''
|
||||
#!/bin/bash
|
||||
|
||||
echo "🎵 Audio Control Center"
|
||||
echo "======================"
|
||||
echo ""
|
||||
echo "Available audio applications:"
|
||||
echo ""
|
||||
|
||||
if command -v easyeffects >/dev/null 2>&1; then
|
||||
echo " 1. EasyEffects - Audio effects and noise suppression"
|
||||
fi
|
||||
|
||||
if command -v pavucontrol >/dev/null 2>&1; then
|
||||
echo " 2. PulseAudio Volume Control - Volume and device management"
|
||||
fi
|
||||
|
||||
if command -v pwvucontrol >/dev/null 2>&1; then
|
||||
echo " 3. PipeWire Volume Control - Native PipeWire control"
|
||||
fi
|
||||
|
||||
if command -v helvum >/dev/null 2>&1; then
|
||||
echo " 4. Helvum - PipeWire patchbay"
|
||||
fi
|
||||
|
||||
if command -v qpwgraph >/dev/null 2>&1; then
|
||||
echo " 5. qpwgraph - Qt PipeWire graph manager"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " 🔧 Audio Tools:"
|
||||
echo " • pw-top - Monitor PipeWire performance"
|
||||
echo " • pw-dump - Inspect PipeWire objects"
|
||||
echo " • pw-metadata - View/set PipeWire metadata"
|
||||
echo " • wpctl - WirePlumber control utility"
|
||||
echo ""
|
||||
|
||||
echo "Choose an option (1-5) or press Enter for EasyEffects:"
|
||||
read -r choice
|
||||
|
||||
case $choice in
|
||||
1|"")
|
||||
if command -v easyeffects >/dev/null 2>&1; then
|
||||
echo "Starting EasyEffects..."
|
||||
easyeffects
|
||||
else
|
||||
echo "EasyEffects not found!"
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
if command -v pavucontrol >/dev/null 2>&1; then
|
||||
echo "Starting PulseAudio Volume Control..."
|
||||
pavucontrol
|
||||
else
|
||||
echo "pavucontrol not found!"
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
if command -v pwvucontrol >/dev/null 2>&1; then
|
||||
echo "Starting PipeWire Volume Control..."
|
||||
pwvucontrol
|
||||
else
|
||||
echo "pwvucontrol not found!"
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
if command -v helvum >/dev/null 2>&1; then
|
||||
echo "Starting Helvum..."
|
||||
helvum
|
||||
else
|
||||
echo "Helvum not found!"
|
||||
fi
|
||||
;;
|
||||
5)
|
||||
if command -v qpwgraph >/dev/null 2>&1; then
|
||||
echo "Starting qpwgraph..."
|
||||
qpwgraph
|
||||
else
|
||||
echo "qpwgraph not found!"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice"
|
||||
;;
|
||||
esac
|
||||
'')
|
||||
|
||||
(writeShellScriptBin "microphone-test" ''
|
||||
#!/bin/bash
|
||||
|
||||
echo "🎤 Microphone Test & Setup"
|
||||
echo "=========================="
|
||||
echo ""
|
||||
|
||||
# Check if PipeWire is running
|
||||
if ! pgrep -x pipewire >/dev/null; then
|
||||
echo "❌ PipeWire is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ PipeWire is running"
|
||||
|
||||
# Check for RNNoise
|
||||
if ls /nix/store/*/lib/ladspa/librnnoise_ladspa.so >/dev/null 2>&1; then
|
||||
echo "✅ RNNoise plugin is available"
|
||||
else
|
||||
echo "⚠️ RNNoise plugin not found"
|
||||
fi
|
||||
|
||||
# List audio sources
|
||||
echo ""
|
||||
echo "📺 Available audio sources:"
|
||||
wpctl status | grep -A 20 "Audio Sources"
|
||||
|
||||
echo ""
|
||||
echo "🔊 Available audio sinks:"
|
||||
wpctl status | grep -A 20 "Audio Sinks"
|
||||
|
||||
echo ""
|
||||
echo "Would you like to:"
|
||||
echo " 1. Test microphone input"
|
||||
echo " 2. Open EasyEffects for noise suppression setup"
|
||||
echo " 3. Show detailed audio device information"
|
||||
echo " 4. Monitor audio levels"
|
||||
echo ""
|
||||
read -p "Choose an option (1-4): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
echo "Recording 5 seconds of audio for playback test..."
|
||||
echo "Speak into your microphone now!"
|
||||
if command -v arecord >/dev/null 2>&1 && command -v aplay >/dev/null 2>&1; then
|
||||
arecord -d 5 -f cd /tmp/mic_test.wav && echo "Playing back recording..." && aplay /tmp/mic_test.wav
|
||||
rm -f /tmp/mic_test.wav
|
||||
else
|
||||
echo "❌ ALSA utilities not available"
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
if command -v easyeffects >/dev/null 2>&1; then
|
||||
echo "Opening EasyEffects..."
|
||||
easyeffects &
|
||||
else
|
||||
echo "❌ EasyEffects not found"
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
echo ""
|
||||
echo "🔍 Detailed audio information:"
|
||||
echo ""
|
||||
pw-dump | jq '.[] | select(.info.props."media.class" == "Audio/Source" or .info.props."media.class" == "Audio/Sink") | {id: .id, name: .info.props."node.name", description: .info.props."node.description", class: .info.props."media.class"}'
|
||||
;;
|
||||
4)
|
||||
echo "Monitoring audio levels (Ctrl+C to stop)..."
|
||||
if command -v pw-top >/dev/null 2>&1; then
|
||||
pw-top
|
||||
else
|
||||
echo "Monitoring with wpctl..."
|
||||
while true; do
|
||||
clear
|
||||
wpctl status
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice"
|
||||
;;
|
||||
esac
|
||||
'')
|
||||
];
|
||||
}
|
546
modules/sound/easyeffects-presets.nix
Normal file
546
modules/sound/easyeffects-presets.nix
Normal file
|
@ -0,0 +1,546 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
# Create EasyEffects configuration directory and presets
|
||||
environment.etc = {
|
||||
# Input preset for microphone noise suppression
|
||||
"easyeffects/input/Microphone_Noise_Suppression.json".text = builtins.toJSON {
|
||||
input = {
|
||||
blocklist = [];
|
||||
equalizer = {
|
||||
balance = 0.0;
|
||||
bypass = false;
|
||||
input-gain = 0.0;
|
||||
left = {
|
||||
band0 = {
|
||||
frequency = 29.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band1 = {
|
||||
frequency = 59.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band2 = {
|
||||
frequency = 119.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band3 = {
|
||||
frequency = 237.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band4 = {
|
||||
frequency = 474.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band5 = {
|
||||
frequency = 947.0;
|
||||
gain = 2.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band6 = {
|
||||
frequency = 1889.0;
|
||||
gain = 1.5;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band7 = {
|
||||
frequency = 3770.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band8 = {
|
||||
frequency = 7523.0;
|
||||
gain = 0.5;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band9 = {
|
||||
frequency = 15011.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
};
|
||||
mode = "IIR";
|
||||
num-bands = 10;
|
||||
output-gain = 0.0;
|
||||
pitch-left = 0.0;
|
||||
pitch-right = 0.0;
|
||||
right = {
|
||||
band0 = {
|
||||
frequency = 29.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band1 = {
|
||||
frequency = 59.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band2 = {
|
||||
frequency = 119.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band3 = {
|
||||
frequency = 237.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band4 = {
|
||||
frequency = 474.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band5 = {
|
||||
frequency = 947.0;
|
||||
gain = 2.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band6 = {
|
||||
frequency = 1889.0;
|
||||
gain = 1.5;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band7 = {
|
||||
frequency = 3770.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band8 = {
|
||||
frequency = 7523.0;
|
||||
gain = 0.5;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band9 = {
|
||||
frequency = 15011.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
};
|
||||
split-channels = false;
|
||||
};
|
||||
filter = {
|
||||
balance = 0.0;
|
||||
bypass = false;
|
||||
frequency = 2000.0;
|
||||
gain = 0.0;
|
||||
mode = "12dB/oct Highpass";
|
||||
quality = 0.7071;
|
||||
slope = "x1";
|
||||
};
|
||||
gate = {
|
||||
attack = 20.0;
|
||||
bypass = false;
|
||||
curve-threshold = -24.0;
|
||||
curve-zone = 2.0;
|
||||
hpf-frequency = 10.0;
|
||||
hpf-mode = "12dB/oct Highpass";
|
||||
input-gain = 0.0;
|
||||
knee = 2.5;
|
||||
lpf-frequency = 20000.0;
|
||||
lpf-mode = "12dB/oct Lowpass";
|
||||
makeup = 0.0;
|
||||
ratio = 2.0;
|
||||
release = 250.0;
|
||||
sidechain = {
|
||||
lookahead = 0.0;
|
||||
mode = "RMS";
|
||||
preamp = 0.0;
|
||||
reactivity = 10.0;
|
||||
source = "Middle";
|
||||
};
|
||||
threshold = -18.0;
|
||||
};
|
||||
limiter = {
|
||||
alr = false;
|
||||
alr-attack = 5.0;
|
||||
alr-knee = 0.0;
|
||||
alr-release = 50.0;
|
||||
attack = 5.0;
|
||||
bypass = false;
|
||||
dithering = "None";
|
||||
external-sidechain = false;
|
||||
gain-boost = true;
|
||||
input-gain = 0.0;
|
||||
lookahead = 5.0;
|
||||
mode = "Herm Thin";
|
||||
output-gain = 0.0;
|
||||
oversampling = "None";
|
||||
release = 5.0;
|
||||
sidechain-preamp = 0.0;
|
||||
stereo-link = 100.0;
|
||||
threshold = 0.0;
|
||||
};
|
||||
plugins_order = [
|
||||
"filter"
|
||||
"gate"
|
||||
"equalizer"
|
||||
"rnnoise"
|
||||
"limiter"
|
||||
];
|
||||
rnnoise = {
|
||||
bypass = false;
|
||||
enable-vad = true;
|
||||
input-gain = 0.0;
|
||||
model-path = "";
|
||||
output-gain = 0.0;
|
||||
release = 20.0;
|
||||
vad-thres = 50.0;
|
||||
wet = 80.0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Output preset for speakers/headphones
|
||||
"easyeffects/output/Speakers_Enhanced.json".text = builtins.toJSON {
|
||||
output = {
|
||||
blocklist = [];
|
||||
equalizer = {
|
||||
balance = 0.0;
|
||||
bypass = false;
|
||||
input-gain = 0.0;
|
||||
left = {
|
||||
band0 = {
|
||||
frequency = 29.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band1 = {
|
||||
frequency = 59.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band2 = {
|
||||
frequency = 119.0;
|
||||
gain = 0.5;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band3 = {
|
||||
frequency = 237.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band4 = {
|
||||
frequency = 474.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band5 = {
|
||||
frequency = 947.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band6 = {
|
||||
frequency = 1889.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band7 = {
|
||||
frequency = 3770.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band8 = {
|
||||
frequency = 7523.0;
|
||||
gain = 2.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band9 = {
|
||||
frequency = 15011.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
};
|
||||
mode = "IIR";
|
||||
num-bands = 10;
|
||||
output-gain = 0.0;
|
||||
pitch-left = 0.0;
|
||||
pitch-right = 0.0;
|
||||
right = {
|
||||
band0 = {
|
||||
frequency = 29.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band1 = {
|
||||
frequency = 59.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band2 = {
|
||||
frequency = 119.0;
|
||||
gain = 0.5;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band3 = {
|
||||
frequency = 237.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band4 = {
|
||||
frequency = 474.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band5 = {
|
||||
frequency = 947.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band6 = {
|
||||
frequency = 1889.0;
|
||||
gain = 0.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band7 = {
|
||||
frequency = 3770.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band8 = {
|
||||
frequency = 7523.0;
|
||||
gain = 2.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
band9 = {
|
||||
frequency = 15011.0;
|
||||
gain = 1.0;
|
||||
mode = "RLC (BT)";
|
||||
mute = false;
|
||||
q = 4.36;
|
||||
slope = "x1";
|
||||
solo = false;
|
||||
type = "Bell";
|
||||
};
|
||||
};
|
||||
split-channels = false;
|
||||
};
|
||||
limiter = {
|
||||
alr = false;
|
||||
alr-attack = 5.0;
|
||||
alr-knee = 0.0;
|
||||
alr-release = 50.0;
|
||||
attack = 5.0;
|
||||
bypass = false;
|
||||
dithering = "None";
|
||||
external-sidechain = false;
|
||||
gain-boost = true;
|
||||
input-gain = 0.0;
|
||||
lookahead = 5.0;
|
||||
mode = "Herm Thin";
|
||||
output-gain = 0.0;
|
||||
oversampling = "None";
|
||||
release = 5.0;
|
||||
sidechain-preamp = 0.0;
|
||||
stereo-link = 100.0;
|
||||
threshold = -1.0;
|
||||
};
|
||||
plugins_order = [
|
||||
"equalizer"
|
||||
"limiter"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
177
modules/sound/pipewire.nix
Normal file
177
modules/sound/pipewire.nix
Normal file
|
@ -0,0 +1,177 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./easyeffects-presets.nix
|
||||
./audio-desktop-integration.nix
|
||||
];
|
||||
# Enable PipeWire with full audio stack
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
|
||||
# Enable WirePlumber session manager
|
||||
wireplumber.enable = true;
|
||||
|
||||
# Add noise suppression and audio processing packages
|
||||
extraPackages = with pkgs; [
|
||||
rnnoise-plugin # RNNoise noise suppression
|
||||
easyeffects # Modern audio effects and filters
|
||||
];
|
||||
};
|
||||
|
||||
# Install audio management and GUI applications
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Audio control and monitoring
|
||||
pavucontrol # PulseAudio volume control (works with PipeWire)
|
||||
helvum # Graphical patchbay for PipeWire
|
||||
qpwgraph # Qt-based PipeWire graph manager
|
||||
easyeffects # Audio effects and noise suppression GUI
|
||||
pwvucontrol # Native PipeWire volume control
|
||||
|
||||
# Audio utilities
|
||||
wireplumber # WirePlumber session manager
|
||||
pipewire-pulse # PulseAudio compatibility
|
||||
pipecontrol # PipeWire control utility
|
||||
alsa-utils # ALSA utilities for testing
|
||||
|
||||
# Validation script
|
||||
(writeShellScriptBin "validate-audio" (builtins.readFile ./validate-audio.sh))
|
||||
|
||||
# Optional: Professional audio tools
|
||||
# qjackctl # JACK control GUI (for JACK applications)
|
||||
# carla # Audio plugin host
|
||||
];
|
||||
|
||||
# System-wide PipeWire configuration
|
||||
environment.etc = {
|
||||
# Main PipeWire configuration
|
||||
"pipewire/pipewire.conf.d/10-noise-suppression.conf".text = ''
|
||||
context.properties = {
|
||||
default.clock.rate = 48000
|
||||
default.clock.quantum = 1024
|
||||
default.clock.min-quantum = 32
|
||||
default.clock.max-quantum = 2048
|
||||
}
|
||||
|
||||
context.modules = [
|
||||
{
|
||||
name = libpipewire-module-filter-chain
|
||||
args = {
|
||||
node.description = "Noise Canceling Source"
|
||||
media.name = "Noise Canceling Source"
|
||||
filter.graph = {
|
||||
nodes = [
|
||||
{
|
||||
type = ladspa
|
||||
name = rnnoise
|
||||
plugin = ${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so
|
||||
label = noise_suppressor_stereo
|
||||
control = {
|
||||
"VAD Threshold (%)" = 50.0
|
||||
"VAD Grace Period (ms)" = 200
|
||||
"Retroactive VAD Grace (ms)" = 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
capture.props = {
|
||||
node.name = "capture.rnnoise_source"
|
||||
node.passive = true
|
||||
audio.rate = 48000
|
||||
}
|
||||
playback.props = {
|
||||
node.name = "rnnoise_source"
|
||||
media.class = "Audio/Source"
|
||||
audio.rate = 48000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
'';
|
||||
|
||||
# WirePlumber configuration for noise suppression
|
||||
"wireplumber/wireplumber.conf.d/51-noise-suppression.conf".text = ''
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "~alsa_card.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
device.profile-set = "auto"
|
||||
device.auto-profile = true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
monitor.bluez.rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
device.name = "~bluez_card.*"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
bluez5.auto-connect = [ "hfp_hf" "hsp_hs" "a2dp_sink" ]
|
||||
bluez5.hw-volume = [ "hfp_hf" "hsp_hs" "a2dp_sink" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
'';
|
||||
|
||||
# Audio quality and latency optimization
|
||||
"pipewire/pipewire-pulse.conf.d/10-audio-quality.conf".text = ''
|
||||
pulse.properties = {
|
||||
pulse.min.req = 32/48000
|
||||
pulse.default.req = 1024/48000
|
||||
pulse.min.quantum = 32/48000
|
||||
pulse.max.quantum = 2048/48000
|
||||
}
|
||||
|
||||
stream.properties = {
|
||||
node.latency = 1024/48000
|
||||
resample.quality = 4
|
||||
channelmix.normalize = false
|
||||
channelmix.mix-lfe = false
|
||||
session.suspend-timeout-seconds = 0
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# Enable real-time audio processing
|
||||
security.rtkit.enable = true;
|
||||
|
||||
# Audio group for users
|
||||
users.groups.audio = {};
|
||||
|
||||
# Set environment variables for better audio performance
|
||||
environment.variables = {
|
||||
# PipeWire environment variables
|
||||
PIPEWIRE_LATENCY = "1024/48000";
|
||||
# Ensure applications use PipeWire
|
||||
PULSE_RUNTIME_PATH = "/run/user/$UID/pulse";
|
||||
};
|
||||
|
||||
# Enable additional audio-related services
|
||||
services = {
|
||||
# Enable udev rules for audio devices
|
||||
udev.packages = with pkgs; [
|
||||
alsa-utils
|
||||
];
|
||||
};
|
||||
|
||||
# User session configuration for audio
|
||||
systemd.user.services.pipewire-pulse.wantedBy = ["default.target"];
|
||||
}
|
204
modules/sound/validate-audio.sh
Executable file
204
modules/sound/validate-audio.sh
Executable file
|
@ -0,0 +1,204 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Audio Configuration Validation Script
|
||||
# This script helps validate that PipeWire with noise suppression is working correctly
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "🎵 PipeWire Audio Configuration Validator"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
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}"
|
||||
}
|
||||
|
||||
# Check if PipeWire is running
|
||||
echo "1. Checking PipeWire service status..."
|
||||
if systemctl --user is-active pipewire >/dev/null 2>&1; then
|
||||
success "PipeWire service is running"
|
||||
else
|
||||
error "PipeWire service is not running"
|
||||
echo " Try: systemctl --user start pipewire"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check WirePlumber
|
||||
echo ""
|
||||
echo "2. Checking WirePlumber session manager..."
|
||||
if systemctl --user is-active wireplumber >/dev/null 2>&1; then
|
||||
success "WirePlumber is running"
|
||||
else
|
||||
warning "WirePlumber is not running"
|
||||
echo " Try: systemctl --user start wireplumber"
|
||||
fi
|
||||
|
||||
# Check PipeWire-Pulse
|
||||
echo ""
|
||||
echo "3. Checking PipeWire-Pulse compatibility..."
|
||||
if systemctl --user is-active pipewire-pulse >/dev/null 2>&1; then
|
||||
success "PipeWire-Pulse is running"
|
||||
else
|
||||
warning "PipeWire-Pulse is not running"
|
||||
echo " Try: systemctl --user start pipewire-pulse"
|
||||
fi
|
||||
|
||||
# Check for RNNoise plugin
|
||||
echo ""
|
||||
echo "4. Checking for RNNoise noise suppression plugin..."
|
||||
if find /nix/store -name "librnnoise_ladspa.so" 2>/dev/null | head -1 | grep -q .; then
|
||||
success "RNNoise plugin found"
|
||||
RNNOISE_PATH=$(find /nix/store -name "librnnoise_ladspa.so" 2>/dev/null | head -1)
|
||||
info "Located at: $RNNOISE_PATH"
|
||||
else
|
||||
error "RNNoise plugin not found"
|
||||
echo " This might indicate the package is not installed correctly"
|
||||
fi
|
||||
|
||||
# Check audio devices
|
||||
echo ""
|
||||
echo "5. Checking available audio devices..."
|
||||
if command -v wpctl >/dev/null 2>&1; then
|
||||
SOURCES=$(wpctl status | grep -A 10 "Audio Sources" | grep -c "│" || echo "0")
|
||||
SINKS=$(wpctl status | grep -A 10 "Audio Sinks" | grep -c "│" || echo "0")
|
||||
|
||||
if [ "$SOURCES" -gt 0 ]; then
|
||||
success "Found $SOURCES audio source(s)"
|
||||
else
|
||||
warning "No audio sources found"
|
||||
fi
|
||||
|
||||
if [ "$SINKS" -gt 0 ]; then
|
||||
success "Found $SINKS audio sink(s)"
|
||||
else
|
||||
warning "No audio sinks found"
|
||||
fi
|
||||
else
|
||||
error "wpctl command not found"
|
||||
fi
|
||||
|
||||
# Check for GUI applications
|
||||
echo ""
|
||||
echo "6. Checking GUI audio applications..."
|
||||
|
||||
if command -v easyeffects >/dev/null 2>&1; then
|
||||
success "EasyEffects available"
|
||||
else
|
||||
warning "EasyEffects not found"
|
||||
fi
|
||||
|
||||
if command -v pavucontrol >/dev/null 2>&1; then
|
||||
success "PulseAudio Volume Control available"
|
||||
else
|
||||
warning "pavucontrol not found"
|
||||
fi
|
||||
|
||||
if command -v helvum >/dev/null 2>&1; then
|
||||
success "Helvum patchbay available"
|
||||
else
|
||||
warning "Helvum not found"
|
||||
fi
|
||||
|
||||
# Check configuration files
|
||||
echo ""
|
||||
echo "7. Checking configuration files..."
|
||||
|
||||
CONFIG_FILES=(
|
||||
"/etc/pipewire/pipewire.conf.d/10-noise-suppression.conf"
|
||||
"/etc/wireplumber/wireplumber.conf.d/51-noise-suppression.conf"
|
||||
"/etc/pipewire/pipewire-pulse.conf.d/10-audio-quality.conf"
|
||||
)
|
||||
|
||||
for config in "${CONFIG_FILES[@]}"; do
|
||||
if [ -f "$config" ]; then
|
||||
success "$(basename "$config") exists"
|
||||
else
|
||||
warning "$(basename "$config") not found"
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for noise canceling source
|
||||
echo ""
|
||||
echo "8. Checking for noise canceling source..."
|
||||
if command -v pw-dump >/dev/null 2>&1; then
|
||||
if pw-dump | jq -r '.[] | select(.info.props."node.name" == "rnnoise_source") | .info.props."node.description"' 2>/dev/null | grep -q "Noise Canceling"; then
|
||||
success "Noise Canceling Source device found"
|
||||
else
|
||||
warning "Noise Canceling Source device not found"
|
||||
info "This is normal if no microphone is connected"
|
||||
fi
|
||||
else
|
||||
warning "pw-dump not available, cannot check for noise canceling source"
|
||||
fi
|
||||
|
||||
# Performance check
|
||||
echo ""
|
||||
echo "9. Checking audio performance..."
|
||||
if command -v pw-top >/dev/null 2>&1; then
|
||||
info "You can monitor real-time performance with: pw-top"
|
||||
else
|
||||
warning "pw-top not available for performance monitoring"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "🎯 Quick Start Commands:"
|
||||
echo "========================"
|
||||
echo ""
|
||||
echo "Start audio setup wizard: audio-setup"
|
||||
echo "Test microphone: microphone-test"
|
||||
echo "Launch EasyEffects: easyeffects"
|
||||
echo "Control volumes: pavucontrol"
|
||||
echo "Audio routing: helvum"
|
||||
echo "Monitor performance: pw-top"
|
||||
echo "Device status: wpctl status"
|
||||
echo ""
|
||||
|
||||
# Check if user wants to run a test
|
||||
echo "Would you like to run a quick microphone test? (y/N)"
|
||||
read -r response
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
echo ""
|
||||
info "Starting microphone test..."
|
||||
if command -v microphone-test >/dev/null 2>&1; then
|
||||
microphone-test
|
||||
else
|
||||
echo "Recording 3 seconds of audio..."
|
||||
if command -v arecord >/dev/null 2>&1 && command -v aplay >/dev/null 2>&1; then
|
||||
arecord -d 3 -f cd /tmp/audio_test.wav 2>/dev/null && \
|
||||
echo "Playing back..." && \
|
||||
aplay /tmp/audio_test.wav 2>/dev/null && \
|
||||
rm -f /tmp/audio_test.wav
|
||||
success "Microphone test completed"
|
||||
else
|
||||
error "Audio testing tools not available"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
success "Audio configuration validation completed!"
|
||||
echo ""
|
||||
info "If you encounter issues, try:"
|
||||
echo " • systemctl --user restart pipewire pipewire-pulse wireplumber"
|
||||
echo " • Check the README.md for detailed troubleshooting"
|
||||
echo " • Run 'audio-setup' for interactive configuration"
|
|
@ -69,13 +69,6 @@
|
|||
X11Forwarding = true; # For GUI applications over SSH
|
||||
};
|
||||
};
|
||||
|
||||
# Enable sound
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
# XDG portal for desktop integration
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue