Skip to main content

Sound Blaster X4 and Pipewire

··4 mins

For Christmas, I received a Sound Blaster X4. I wanted this because I like the idea of having two audio outputs (game and chat) and being able to mix between them on the fly. Of course, the one issue I ran into was not being able to do that mixing, because by default Linux doesn’t see the chat output for the device. After a bit of learning about ALSA and Pipewire, I was able to fix it.

Update 2024-06-19: WirePlumber updated how it looks for the customization files, so I have updated this post to reflect that. If you already followed this guide before, you can delete ~/.config/wireplumber/main.lua.d/51-alsa-custom.lua (and the empty main.lua.d directory), and then make the new config file shown in the WirePlumber alsa-custom section.

New alsa-card-profile #

To start, you will need to make a new alsa-card-profile for the Sound Blaster X4. You can define this in your home config directory for easy management.

~/.config/alsa-card-profile/mixer/profile-sets/sound-blaster-x4.conf

[General]
auto-profiles = no

[Mapping analog-stereo]
device-strings = front:%f
channel-map = left,right
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 15

[Mapping analog-surround-21]
device-strings = surround21:%f
channel-map = front-left,front-right,lfe
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 13

[Mapping analog-surround-40]
device-strings = surround40:%f
channel-map = front-left,front-right,rear-left,rear-right
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 12

[Mapping analog-surround-41]
device-strings = surround41:%f
channel-map = front-left,front-right,rear-left,rear-right,lfe
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 13

[Mapping analog-surround-50]
device-strings = surround50:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 12

[Mapping analog-surround-51]
device-strings = surround51:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 13

[Mapping analog-surround-71]
device-strings = surround71:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 12

[Mapping analog-stereo-chat-output]
description-key = gaming-headset-chat
device-strings = hw:%f,1,0
channel-map = left,right
paths-output = analog-output analog-output-lineout analog-output-speaker
direction = output
priority = 15

[Mapping analog-stereo-chat-input]
description-key = gaming-headset-chat
device-strings = hw:%f,0,0
channel-map = left,right
paths-input = analog-input analog-input-linein analog-input-mic
direction = input
intended-roles = phone
priority = 15

[Profile sound-blaster-x4-20]
output-mappings = analog-stereo analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

[Profile sound-blaster-x4-21]
output-mappings = analog-surround-21 analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

[Profile sound-blaster-x4-40]
output-mappings = analog-surround-40 analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

[Profile sound-blaster-x4-41]
output-mappings = analog-surround-41 analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

[Profile sound-blaster-x4-50]
output-mappings = analog-surround-50 analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

[Profile sound-blaster-x4-51]
output-mappings = analog-surround-51 analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

[Profile sound-blaster-x4-71]
output-mappings = analog-surround-71 analog-stereo-chat-output
input-mappings = analog-stereo-chat-input

This file starts with auto-profiles = no, which means that it won’t auto generate any profiles. It will instead only use the explicitly defined ones. Next are the mappings, which list out every input/output of the device. Finally we have the profiles, which will take the mappings and combine them together.

The mappings are pretty much copied from /usr/share/alsa-card-profile/mixer/profile-sets/default.conf, but with added descriptions. Of note, the [Mapping analog-stereo-chat-output] is what was missing from the default config, and is why there wasn’t a chat output channel present. The default (game) output is on device 0, and the chat output is on device 1:

aplay -l

...
card 3: X4 [Sound Blaster X4], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: X4 [Sound Blaster X4], device 1: USB Audio [USB Audio #1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: X4 [Sound Blaster X4], device 2: USB Audio [USB Audio #2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

So, using device-strings = hw:%f,1,0 is what lets us access it! Also of note, for some reason the [Profile sound-blaster-x4-40] does not show up, because for some reason [Mapping analog-surround-40] isn’t valid for the device. If you check aplay -L, you can see that surround40 is listed, so I am not sure why this is the case. I have left it defined just in case it decides to start working someday.

WirePlumber alsa-custom #

The only other thing you need is to configure the Sound Blaster X4 to use this new alsa-card-profile. You can define this in your home config directory as well. This is also assuming you are using WirePlumber.

~/.config/wireplumber/wireplumber.conf.d/51-alsa-custom.conf

monitor.alsa.rules = [
  {
    matches = [
      {
        device.nick = "Sound Blaster X4"
      }
    ]
    actions = {
      update-props = {
        api.alsa.use-acp = true,
        api.acp.auto-profile = false
        api.acp.auto-port = false
        device.profile-set = "sound-blaster-x4.conf"
        device.profile = "sound-blaster-x4-20"
      }
    }
  }
]

This (and the alsa-card-profile above) is pretty much taken from the ArchWiki, but with the proper device.nick.

If you followed this guide previously, you can delete the file ~/.config/wireplumber/main.lua.d/51-alsa-custom.lua (and the empty main.lua.d directory), as this isn’t used by WirePlumber anymore.

Reload #

Once those two files are in place, simply restart WirePlumber and you should be good to go!

systemctl --user restart wireplumber.service

Other Notes #

The Sound Blaster X4 also supports the digital iec958 mappings listed in the default.conf file, but I wasn’t able to get them to work with my setup, and thus ignored them in the alsa-card-profile I made. Feel free to add them if you know you will need them.