Pipewire

install pipewire

pacman -S pipewire wireplumber pipewire-audio pipewire-alsa pipewire-pulse 

needed for steam and gaming, remember to enable multilib

pacman -S lib32-pipewire lib32-libpulse

maybe needed for non onboard snd cards

pacman -S alsa-firmware

make user wireplumber.conf.d

mkdir -p ~/.config/wireplumber/wireplumber.conf.d

PipeWire Hi-Res Audio Configuration Guide for Arch Linux

Overview

By default, PipeWire on Arch Linux may resample all audio to 48kHz, preventing proper hi-res audio playback (96kHz, 192kHz, 384kHz, DSD, etc.). This guide shows how to configure PipeWire and WirePlumber to enable bit-perfect, sample-rate-switching audio output.

Problem Signs

  • Your DAC/audio interface displays “PCM 48kHz” regardless of source material
  • Hi-res FLAC files (96kHz+) are being downsampled
  • cat /proc/asound/cardX/pcm0p/sub0/hw_params shows rate: 48000 even when playing 96kHz content
  • pw-top shows correct sample rate, but hardware receives 48kHz

Prerequisites

  • Arch Linux with PipeWire and WirePlumber installed
  • A hi-res capable DAC/audio interface (USB DAC, Fiio, etc.)
  • Hi-res audio files for testing (96kHz/24-bit FLAC or higher)

Configuration Steps

1. Remove Conflicting ALSA Configuration

First, check if you have an .asoundrc file that’s forcing resampling:

cat ~/.asoundrc

If it exists and contains type plug or similar resampling configurations, back it up and remove it:

mv ~/.asoundrc ~/.asoundrc.backup

2. Configure PipeWire

Create or edit the PipeWire configuration file:

mkdir -p ~/.config/pipewire/pipewire.conf.d
vim ~/.config/pipewire/pipewire.conf.d/99-hires.conf

Add the following content:

context.properties = {
    default.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 352800 384000 ]
}

Note: Do NOT set default.clock.rate - this allows PipeWire to switch rates dynamically.

3. Disable ALSA Card Profiles (ACP)

ACP can interfere with sample rate switching. Create a WirePlumber config:

mkdir -p ~/.config/wireplumber/wireplumber.conf.d
vim ~/.config/wireplumber/wireplumber.conf.d/50-alsa-config.conf

Add:

monitor.alsa.rules = [
  {
    matches = [
      { device.name = "~alsa_card.*" }
    ]
    actions = {
      update-props = {
        api.alsa.use-acp = false
      }
    }
  }
]

4. Configure Device-Specific Settings

Create a configuration for your specific audio device. Replace QX13 with your device name (check with aplay -l):

vim ~/.config/wireplumber/wireplumber.conf.d/51-device-format.conf

Add (adjust device name pattern as needed):

monitor.alsa.rules = [
  {
    matches = [
      { node.name = "~alsa_output.*YOUR_DEVICE_NAME.*" }
    ]
    actions = {
      update-props = {
        audio.format = "S32LE"
        audio.rate = 0
        audio.allowed-rates = "44100,48000,88200,96000,176400,192000,352800,384000"
        node.max-latency = 0
        api.alsa.period-size = 128
        api.alsa.headroom = 128
      }
    }
  }
]

Key settings explained: - audio.format = "S32LE": 32-bit signed little-endian (highest quality) - audio.rate = 0: Passthrough mode (no resampling) - node.max-latency = 0: Disables latency constraints that can lock sample rates - api.alsa.period-size = 128: Buffer size for low latency

5. Restart Audio Services

systemctl --user restart wireplumber pipewire pipewire-pulse

Verification

Check Hardware Sample Rate

While playing a 96kHz FLAC file:

cat /proc/asound/card4/pcm0p/sub0/hw_params

You should see:

rate: 96000 (96000/1)
format: S32_LE

Check PipeWire Status

pw-top

Look at the “RATE” column - it should show the actual source file’s sample rate.

Check Device Node Properties

Find your device:

wpctl status | grep -i "your_device_name"

Inspect the node (replace ID with yours):

wpctl inspect <ID>

Verify: - audio.rate = "0" (passthrough enabled) - audio.allowed-rates includes your target rates - api.alsa.use-acp = false (on the device card)

Test Different Sample Rates

Test files of different sample rates to verify switching:

# Check file sample rate
ffprobe your_audio_file.flac 2>&1 | grep "Stream.*Audio"

# Play and verify hardware rate
cat /proc/asound/card4/pcm0p/sub0/hw_params

Your DAC should display: - 44.1kHz for CD rips - 48kHz for some digital sources - 96kHz, 192kHz, etc. for hi-res files

Music Player Configuration

Strawberry / Clementine

  • Backend: GStreamer (default)
  • Output: autoaudiosink or pipewiresink
  • Do NOT enable resampling options
  • Do NOT use ALSA direct output (PipeWire handles this better)

MPD

Add to ~/.config/mpd/mpd.conf:

audio_output {
    type            "pipewire"
    name            "PipeWire Output"
}

VLC

  • Tools → Preferences → Audio
  • Output module: Automatic
  • PipeWire will be used automatically

Troubleshooting

Issue: Still shows 48kHz

Check: 1. Device is not busy: fuser -v /dev/snd/* 2. Configs are loaded: pw-dump | grep "use-acp" 3. Node properties: wpctl inspect <device_id> | grep rate

Solution:

# Force reload
systemctl --user restart wireplumber pipewire pipewire-pulse

# Clear metadata
pw-metadata -n settings 0 clock.force-rate 0

Issue: Audio glitches or dropouts

Increase buffer sizes in 51-device-format.conf:

api.alsa.period-size = 256
api.alsa.headroom = 256

Then restart services.

Issue: Device shows wrong sample rate

Verify file is actually hi-res:

ffprobe file.flac 2>&1 | grep Audio

Many “hi-res” downloads are actually 44.1kHz upsampled.

Issue: WirePlumber warnings

If you see warnings about old Lua configs:

rm -rf ~/.config/wireplumber/main.lua.d/

WirePlumber 0.5+ uses .conf files, not Lua.

Issue: Can’t access device directly

If getting “Device busy” errors with direct ALSA:

# Stop PipeWire temporarily
systemctl --user stop wireplumber pipewire pipewire-pulse

# Test direct ALSA
aplay -D hw:CARD=YourCard,DEV=0 file.wav

# Restart
systemctl --user start wireplumber pipewire pipewire-pulse

Advanced: Per-Application Settings

You can configure different settings per application:

monitor.alsa.rules = [
  {
    matches = [
      { application.name = "strawberry" }
    ]
    actions = {
      update-props = {
        node.latency = "256/96000"
        resample.quality = 15
      }
    }
  }
]

Checking System Capabilities

List Audio Devices

aplay -l

Check Device Capabilities

cat /proc/asound/card*/stream0

Look for supported rates and formats.

Check USB Audio Class

lsusb -v | grep -A 20 "Your Device"

Verify bcdUSB 2.00 or higher for hi-res support.

Files Summary

After configuration, you should have:

~/.config/pipewire/pipewire.conf.d/99-hires.conf
~/.config/wireplumber/wireplumber.conf.d/50-alsa-config.conf
~/.config/wireplumber/wireplumber.conf.d/51-device-format.conf

And removed or backed up:

~/.asoundrc (if it existed)

References

Credits

ixaxaar Configuration developed through troubleshooting a Fiio QX13 USB DAC on Arch Linux.

Fix recording sample rate

Using JACK system for recording in something like Audacity, will alway be at what the pipewire default sample rate is (most cases 48000hz). To work around this problem create a shell script and force samplerate to the dired value

#!/bin/bash
pw-metadata -n settings 0 clock.force-rate 96000
audacity
pw-metadata -n settings 0 clock.force-rate 0

Inspect PipeWire server settings

pw-cli info 0


Legacy stuff

51-alsa-acp.conf

monitor.alsa.rules = [
  {
    matches = [
      {
        device.name = "~alsa_card.*"
      }
    ]
    actions = {
      update-props = {
        api.alsa.use-acp = true,
        api.acp.auto-profile = false
        api.acp.auto-port = false
      }
    }
  }
]

51-disable-suspension.conf

see https://wiki.archlinux.org/title/PipeWire#Noticeable_audio_delay_or_audible_pop/crack_when_starting_playback

monitor.alsa.rules = [
  {
    matches = [
      {
        # Matches all sources
        node.name = "~alsa_input.*"
      },
      {
        # Matches all sinks
        node.name = "~alsa_output.*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]
# bluetooth devices
monitor.bluez.rules = [
  {
    matches = [
      {
        # Matches all sources
        node.name = "~bluez_input.*"
      },
      {
        # Matches all sinks
        node.name = "~bluez_output.*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]

51-soundblasterz.conf

setting device.profile-set to analog-only.conf to disable S/PDIFF

monitor.alsa.rules = [
  {
    matches = [
      {
        device.name = "alsa_card.pci-0000_06_00.0"
      }
    ]
    actions = {
      update-props = {
        device.description = "SB-Z"
        device.product.name = "SB-Z"
        device.profile-set = "analog-only.conf"
      }
    }
  }
]

51-arctis-rename.conf

monitor.alsa.rules = [
  {
    matches = [
      {
        device.name = "alsa_card.usb-SteelSeries_Arctis_Nova_Pro_Wireless-00"
      }
    ]
    actions = {
      update-props = {
        device.description = "Arctis"
        device.product.name = "Arctis"
      }
    }
  }
]

51-nvidia-disable-hdmi-devices.conf

monitor.alsa.rules = [
  {
    matches = [
      {
        device.name = "alsa_card.pci-0000_0a_00.1"
      }
    ]
    actions = {
      update-props = {
        device.disabled = true,
      }
    }
  }
]

forcing specific profiles for specific cards

This seems like a fucking broken mess at the moment, could not find a proper solution to set this in wireplumber. For now just using a bash script to run at startup of DE.

#!/bin/bash
for i in $(pactl list cards short|cut -d$'\t' -f2); do
  if [[ $i =~ alsa_card.pci ]]; then
    pactl set-card-profile alsa_card.pci-0000_06_00.0 output:analog-surround-21
  fi
  if [[ $i =~ SteelSeries_Arctis_Nova_Pro_Wireless ]]; then
    pactl set-card-profile alsa_card.usb-SteelSeries_Arctis_Nova_Pro_Wireless-00 output:iec958-stereo+input:mono-fallback
  fi
done

Last modified: Tue Oct 6 10:13:47 2026