From PulseAudio to PipeWire: My Fiio K5 pro Configuration

2024-07-06

-related to Linux

So I have a Fiio K5 Pro Audio DAC connected to my desktop, so that I can enjoy high resolution audio. Before writing this post, the set-up is essentially just a simple configuration under PulseAudio.

Old Configuration with PulseAudio

my set-up basically follows ひよこインフラてっく! and Chaekyung: The Fiio K5 Pro Audio DAC+AMP On Linux(ひよこインフラてっく! and Chaekyung 2021).

  • install pulseaudio, pulseaudio-alsa, and pavucontrol
  • modify /etc/pulse/daemon.conf as

    default-sample-format = s32le
    default-sample-rate = 192000
    
  • Restart the service (or just reboot), It should be working. When using 192kHz, the light on the device becomes yellow.

So what is the problem?

This set-up works pretty well, until libpulse and pulseaudio is updated to 17.0. It is still working with mpc, but mpv and Firefox no longer play videos any more because PulseAudio pipe crashes whenever I do that.

Downgrade both back to 16.1 makes them work again, but I consider this as a temporary solution. Maybe it is the time to migrate to PipeWire.

Migrate to PipeWire

I did some heavy reading on the migration process, as Leo Shen: A Brief Look at Linux’s Audio System(Shen 2020), Alynx Zhou: 从 PulseAudio 到 PipeWire(Zhou 2022), Lilydjwg: 使用 EasyEffects 调整 Bose 音箱的体验(Lilydjwg 2023) and of course ArchWiki: PipeWire(ArchWiki 2017) and GentooWiki: PipeWire(GentooWiki 2024), just in case because Linux's Audio system feels like magic to me.

Anyway, as these posts pointed out,

  • Install pipewire
  • Install pipewire-alsa to replace pulseaudio-alsa
  • Install pipewire-pulse to replace pulseaudio.
  • Install wireplumber, which is the default session manager

Now pactl info prints the follow information:

...
Server Name: PulseAudio (on PipeWire 1.2.0)
Server Version: 15.0.0
Default Sample Specification: float32le 2ch 48000Hz
Default Sink: alsa_output.usb-GuangZhou_FiiO_Electronics_Co._Ltd_FiiO_K5_Pro-00.analog-stereo
...

also pactl list short sinks

alsa_output.usb-GuangZhou_FiiO_Electronics_Co._Ltd_FiiO_K5_Pro-00.analog-stereo PipeWire        s32le 2ch 48000Hz       SUSPENDED

So the good thing is that PipeWire has actually replaced PulseAudio. The bad thing is that the sample specification is float32le 2ch 48000Hz, which is very likely not we want. Before the migration, it is s32le 2ch 192000Hz.

Configuration Structure

From my understanding (as indicated in ArchWiki: PipeWire(ArchWiki 2017) and GentooWiki: PipeWire(GentooWiki 2024)), configurations in /usr/share/pipewire are just examples, and PipeWire will not read them in any way. So the first thing is to copy pipewire.conf under this directory to ~/.config/pipewire/pipewire.conf.

GentooWiki: PipeWire(GentooWiki 2024) also mentions that configuration snippets can be put under ~/.config/pipewire/pipewire.conf.d/, and they have higher priorities and they will override the old values. So I guess the idea is

  • copy upstream example configurations (distributed under /usr/share/pipewire) to ~/.config/pipewire periodically, essentially a manual update process, avoiding "surprises"
  • Have actual personal configurations under ~/.config/pipewire/pipewire.conf.d/

Now that I understand the configuration structure (hopefully), let's start to actually configure it.

Get the Hardware Specification

This is demonstrated in ArchWiki: PipeWire(ArchWiki 2017).

Basically, first to get the card number of this DAC by aplay -l

card 0: Pro [FiiO K5 Pro], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

So it is 0, then cat /proc/asound/card0/stream0

GuangZhou FiiO Electronics Co.,Ltd FiiO K5 Pro at xxxxx, high spee : USB Audio

Playback:
  Status: Stop
  Interface 1
    Altset 1
    Format: S32_LE
    ...
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000
    ...
  Interface 1
    Altset 2
    Format: S16_LE
    ...
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000
    ...
  Interface 1
    Altset 3
    Format: SPECIAL DSD_U32_BE
    ...
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000
    ...

Then the supported formats are S32_LE, S16_LE and SPECIAL DSD_U32_BE, and supported sample rates are 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000.

Configure Sample Rates

192000kHz is enough for my daily use.

Put the follow snippet in ~/.config/pipewire/pipewire.conf.d/100-fiio-k5-pro.conf

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

Now restart the pipewire and pipewire-pulse services, pactl info shows

...
Server Name: PulseAudio (on PipeWire 1.2.0)
Server Version: 15.0.0
Default Sample Specification: float32le 2ch 192000Hz
...
Default Sink: alsa_output.usb-GuangZhou_FiiO_Electronics_Co._Ltd_FiiO_K5_Pro-00.analog-stereo
...

also pactl list short sinks

64      alsa_output.usb-GuangZhou_FiiO_Electronics_Co._Ltd_FiiO_K5_Pro-00.analog-stereo        PipeWire        s32le 2ch 192000Hz      SUSPENDED

So the sample rates seem to be correct now. Note that with this default.clock.allowed-rates configuration PipeWire can stay away with re-sampling, see ArchWiki: PipeWire(ArchWiki 2017). That is, if you are playing a 96000kHz audio, PipeWire switch the sound card to use native 96000kHz sample rate automatically. This can be checked by using pw-top.

Configure Sample Format

Maybe I misread but this seems to be not needed, according to (Taymans and Lelli 2020).

This post above also mention that we can use cat /proc/asound/card0/pcm0p/sub0/hw_params etc to see what the ALSA card is actually doing.

Next Step?

The only problem so far I encountered is that mpv sound playback is distorted when its volume is above 100%. I'll keep my current set-up for a while to see if anything else goes wrong.

Reference

ArchWiki. 2017. “Pipewire.” 2017. https://wiki.archlinux.org/title/PipeWire.
GentooWiki. 2024. “Pipewire.” 2024. https://wiki.gentoo.org/wiki/Pipewire.
Lilydjwg. 2023. “使用 Easyeffects 调整 Bose 音箱的体验.” June 21, 2023. https://blog.lilydjwg.me/2023/1/21/bose-and-easyeffects.216566.html.
Shen, Leo. 2020. “A Brief Look at Linux’s Audio System.” June 21, 2020. https://szclsya.me/posts/linux/audio-system/.
Taymans, Wim, and Michael Lelli. 2020. “Selecting an Output Sample Format with Pipewire.” December 5, 2020. https://old.reddit.com/r/archlinux/comments/k7cqy8/selecting_an_output_sample_format_with_pipewire/.
Zhou, Alynx. 2022. “从 Pulseaudio 到 Pipewire.” June 29, 2022. https://sh.alynx.one/posts/From-PulseAudio-to-PipeWire/.
ひよこインフラてっく!, and Chaekyung. 2021. “The Fiio K5 pro Audio Dac+Amp on Linux.” April 13, 2021. https://linuxreviews.org/The_Fiio_K5_Pro_Audio_DAC%2BAMP_On_Linux.