Pipewire natively supports a filter to create a 7.1 virtual surround sound device that will work with any headphones or earphones. It’s not well documented, so I decided to write a step-by-step guide for enabling it in Pop!

How it Works

Sound is distorted by your head and shoulders relative to your ears in slightly different ways based on the direction the sound is coming from. The distortion, which is known as HRIR (head-related impulse response), is how our brains are able to interpret sound spatially, despite ours ears only being capable of receiving stereo audio.

Pipewire is able to achieve a convincing 7.1 surround sound effect either by using either a SOFA (spatially oriented acoustic data) spatializer, or a HRTF (head-related transfer function) convolver to interpolate a replicated 7.1 HRIR input onto a 7.1 surround input, mimicking the natural process by which we hear sound spatially.

A replicated 7.1 HRIR input is created by placing microphones in the ears of an artificial dummy, and measuring the differences in sound it experienced while listening to a 7.1 surround sound system. Which is why we perceive surround sound in headphones.

SOFA takes this technology to the next level with a more advanced algorithm that can process many additional forms of data inputs to improve the surround sound effect.

Option 1: SOFA Spatializer

Step 1: Copy the following 7.1 SOFA spatializer filter-chain config locally. This creates a virtual output sink with 7.1 surround sound channels.

mkdir -p ~/.config/pipewire/filter-chain.conf.d/
curl -o ~/.config/pipewire/filter-chain.conf.d/spatializer.conf \
    https://gist.githubusercontent.com/mmstick/039422a63c73a09e998d08608abaee43/raw/9c4dfef5a447fe25a47e3492e518e134e57ee9d4/7.1-spatializer.conf

Step 2: Download a SOFA DTF for the filter to utilize as its input.

sudo mkdir -p /usr/share/pipewire/sofa/
sudo curl -o /usr/share/pipewire/sofa/dtf.sofa \
    https://sofacoustics.org/data/database_sofa_0.6/ari/dtf%20b_nh724.sofa

Then go to Step 4 below

Option 2: HRIR Convolver

Step 1: Copy the 7.1 filter-chain config locally. This creates a virtual output sink with 7.1 surround sound channels.

mkdir -p ~/.config/pipewire/filter-chain.conf.d/
cp /usr/share/pipewire/filter-chain/sink-virtual-surround-7.1-hesuvi.conf \
    ~/.config/pipewire/filter-chain.conf.d/virtual-surround.conf

Step 2: Download a 7.1 HRIR wav file from the HRTF Database, such as Atmos or CMSS-3D. Then move it into your local pipewire configuration.

mkdir -p ~/.config/pipewire/hrir/
mv ~/Downloads/atmos.wav ~/.config/pipewire/hrir/atmos.wav

Step 3: Edit the copied virtual-surround config to use this wav file.

sed -i "s#hrir_hesuvi/hrir.wav#${HOME}/.config/pipewire/hrir/atmos.wav#g" \
    ~/.config/pipewire/filter-chain.conf.d/virtual-surround.conf

Start the filter and test it


Step 4: Start pipewire with the filter-chain config. The virtual surround device will now exist as long as this is running in the background.

pipewire -c filter-chain.conf

Step 5: Select the virtual surround sink output device and try it out.

Side Effects

There’s a slight audio latency increase from using virtual surround sound, depending on how fast the CPU is. It is a simple process though so the performance cost is slight.

Stereo audio sources should have the same sound before and after. Surround sound content will sound as they were intended to be heard, and it could help with dialogue in some movies being difficult to hear. Especially if you are able to configure the volume of the center speaker channel where dialogue is usually played.

Help

Any help with finding a way to automate this when plugging in headphones would be great.

  • @Deewens
    link
    English
    11 year ago

    Hi, thanks for this! However, I am struggling a bit to understand some part, especially the one about Wants and Bindto, using the udevadm command. Maybe you could explain a bit more details what you are doing? This is the output of the udevadm cmd. I am using the same headset (Logitech G Pro X), and I am trying to have the same audio experience as the one I get one Windows using Logitech G Hub, but it is really hard to understand everything.

    looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.3/0003:046D:0AAA.0006/input/input35/event28':
        KERNEL=="event28"
        SUBSYSTEM=="input"
        DRIVER==""
        ATTR{power/async}=="disabled"
        ATTR{power/control}=="auto"
        ATTR{power/runtime_active_kids}=="0"
        ATTR{power/runtime_active_time}=="0"
        ATTR{power/runtime_enabled}=="disabled"
        ATTR{power/runtime_status}=="unsupported"
        ATTR{power/runtime_suspended_time}=="0"
        ATTR{power/runtime_usage}=="0"
    
      looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.3/0003:046D:0AAA.0006/input/input35':
        KERNELS=="input35"
        SUBSYSTEMS=="input"
        DRIVERS==""
        ATTRS{capabilities/abs}=="0"
        ATTRS{capabilities/ev}=="20013"
        ATTRS{capabilities/ff}=="0"
        ATTRS{capabilities/key}=="100000000000000 0 0 0"
        ATTRS{capabilities/led}=="80"
        ATTRS{capabilities/msc}=="10"
        ATTRS{capabilities/rel}=="0"
        ATTRS{capabilities/snd}=="0"
        ATTRS{capabilities/sw}=="0"
        ATTRS{id/bustype}=="0003"
        ATTRS{id/product}=="0aaa"
        ATTRS{id/vendor}=="046d"
        ATTRS{id/version}=="0111"
        ATTRS{inhibited}=="0"
        ATTRS{name}=="Logitech PRO X"
        ATTRS{phys}=="usb-0000:00:14.0-1/input3"
        ATTRS{power/async}=="disabled"
        ATTRS{power/control}=="auto"
        ATTRS{power/runtime_active_kids}=="0"
        ATTRS{power/runtime_active_time}=="0"
        ATTRS{power/runtime_enabled}=="disabled"
        ATTRS{power/runtime_status}=="unsupported"
        ATTRS{power/runtime_suspended_time}=="0"
        ATTRS{power/runtime_usage}=="0"
        ATTRS{properties}=="0"
        ATTRS{uniq}=="000000000000"
    
      looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.3/0003:046D:0AAA.0006':
        KERNELS=="0003:046D:0AAA.0006"
        SUBSYSTEMS=="hid"
        DRIVERS=="hid-generic"
        ATTRS{country}=="00"
        ATTRS{power/async}=="enabled"
        ATTRS{power/control}=="auto"
        ATTRS{power/runtime_active_kids}=="0"
        ATTRS{power/runtime_active_time}=="0"
        ATTRS{power/runtime_enabled}=="disabled"
        ATTRS{power/runtime_status}=="unsupported"
        ATTRS{power/runtime_suspended_time}=="0"
        ATTRS{power/runtime_usage}=="0"
    
      looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.3':
        KERNELS=="1-1:1.3"
        SUBSYSTEMS=="usb"
        DRIVERS=="usbhid"
        ATTRS{authorized}=="1"
        ATTRS{bAlternateSetting}==" 0"
        ATTRS{bInterfaceClass}=="03"
        ATTRS{bInterfaceNumber}=="03"
        ATTRS{bInterfaceProtocol}=="00"
        ATTRS{bInterfaceSubClass}=="00"
        ATTRS{bNumEndpoints}=="01"
        ATTRS{physical_location/dock}=="no"
        ATTRS{physical_location/horizontal_position}=="left"
        ATTRS{physical_location/lid}=="no"
        ATTRS{physical_location/panel}=="top"
        ATTRS{physical_location/vertical_position}=="upper"
        ATTRS{power/async}=="enabled"
        ATTRS{power/runtime_active_kids}=="0"
        ATTRS{power/runtime_enabled}=="enabled"
        ATTRS{power/runtime_status}=="suspended"
        ATTRS{power/runtime_usage}=="0"
        ATTRS{supports_autosuspend}=="1"
    
      looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1':
        KERNELS=="1-1"
        SUBSYSTEMS=="usb"
        DRIVERS=="usb"
        ATTRS{authorized}=="1"
        ATTRS{avoid_reset_quirk}=="0"
        ATTRS{bConfigurationValue}=="1"
        ATTRS{bDeviceClass}=="00"
        ATTRS{bDeviceProtocol}=="00"
        ATTRS{bDeviceSubClass}=="00"
        ATTRS{bMaxPacketSize0}=="64"
        ATTRS{bMaxPower}=="100mA"
        ATTRS{bNumConfigurations}=="1"
        ATTRS{bNumInterfaces}==" 4"
        ATTRS{bcdDevice}=="0031"
        ATTRS{bmAttributes}=="80"
        ATTRS{busnum}=="1"
        ATTRS{configuration}==""
        ATTRS{devnum}=="8"
        ATTRS{devpath}=="1"
        ATTRS{idProduct}=="0aaa"
        ATTRS{idVendor}=="046d"
        ATTRS{ltm_capable}=="no"
        ATTRS{manufacturer}=="Logitech"
        ATTRS{maxchild}=="0"
        ATTRS{physical_location/dock}=="no"
        ATTRS{physical_location/horizontal_position}=="left"
        ATTRS{physical_location/lid}=="no"
        ATTRS{physical_location/panel}=="top"
        ATTRS{physical_location/vertical_position}=="upper"
        ATTRS{power/active_duration}=="28449032"
        ATTRS{power/async}=="enabled"
        ATTRS{power/autosuspend}=="2"
        ATTRS{power/autosuspend_delay_ms}=="2000"
        ATTRS{power/connected_duration}=="28449032"
        ATTRS{power/control}=="on"
        ATTRS{power/level}=="on"
        ATTRS{power/persist}=="1"
        ATTRS{power/runtime_active_kids}=="1"
        ATTRS{power/runtime_active_time}=="28448749"
        ATTRS{power/runtime_enabled}=="forbidden"
        ATTRS{power/runtime_status}=="active"
        ATTRS{power/runtime_suspended_time}=="0"
        ATTRS{power/runtime_usage}=="1"
        ATTRS{product}=="PRO X"
        ATTRS{quirks}=="0x0"
        ATTRS{removable}=="removable"
        ATTRS{rx_lanes}=="1"
        ATTRS{serial}=="000000000000"
        ATTRS{speed}=="12"
        ATTRS{tx_lanes}=="1"
        ATTRS{urbnum}=="11392870"
        ATTRS{version}==" 2.00"
    
      looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1':
        KERNELS=="usb1"
        SUBSYSTEMS=="usb"
        DRIVERS=="usb"
        ATTRS{authorized}=="1"
        ATTRS{authorized_default}=="1"
        ATTRS{avoid_reset_quirk}=="0"
        ATTRS{bConfigurationValue}=="1"
        ATTRS{bDeviceClass}=="09"
        ATTRS{bDeviceProtocol}=="01"
        ATTRS{bDeviceSubClass}=="00"
        ATTRS{bMaxPacketSize0}=="64"
        ATTRS{bMaxPower}=="0mA"
        ATTRS{bNumConfigurations}=="1"
        ATTRS{bNumInterfaces}==" 1"
        ATTRS{bcdDevice}=="0606"
        ATTRS{bmAttributes}=="e0"
        ATTRS{busnum}=="1"
        ATTRS{configuration}==""
        ATTRS{devnum}=="1"
        ATTRS{devpath}=="0"
        ATTRS{idProduct}=="0002"
        ATTRS{idVendor}=="1d6b"
        ATTRS{interface_authorized_default}=="1"
        ATTRS{ltm_capable}=="no"
        ATTRS{manufacturer}=="Linux 6.6.6-76060606-generic xhci-hcd"
        ATTRS{maxchild}=="16"
        ATTRS{power/active_duration}=="40312872"
        ATTRS{power/async}=="enabled"
        ATTRS{power/autosuspend}=="0"
        ATTRS{power/autosuspend_delay_ms}=="0"
        ATTRS{power/connected_duration}=="40312872"
        ATTRS{power/control}=="auto"
        ATTRS{power/level}=="auto"
        ATTRS{power/runtime_active_kids}=="4"
        ATTRS{power/runtime_active_time}=="40312872"
        ATTRS{power/runtime_enabled}=="enabled"
        ATTRS{power/runtime_status}=="active"
        ATTRS{power/runtime_suspended_time}=="0"
        ATTRS{power/runtime_usage}=="0"
        ATTRS{power/wakeup}=="disabled"
        ATTRS{power/wakeup_abort_count}==""
        ATTRS{power/wakeup_active}==""
        ATTRS{power/wakeup_active_count}==""
        ATTRS{power/wakeup_count}==""
        ATTRS{power/wakeup_expire_count}==""
        ATTRS{power/wakeup_last_time_ms}==""
        ATTRS{power/wakeup_max_time_ms}==""
        ATTRS{power/wakeup_total_time_ms}==""
        ATTRS{product}=="xHCI Host Controller"
        ATTRS{quirks}=="0x0"
        ATTRS{removable}=="unknown"
        ATTRS{rx_lanes}=="1"
        ATTRS{serial}=="0000:00:14.0"
        ATTRS{speed}=="480"
        ATTRS{tx_lanes}=="1"
        ATTRS{urbnum}=="39733"
        ATTRS{version}==" 2.00"
    
      looking at parent device '/devices/pci0000:00/0000:00:14.0':
        KERNELS=="0000:00:14.0"
        SUBSYSTEMS=="pci"
        DRIVERS=="xhci_hcd"
        ATTRS{ari_enabled}=="0"
        ATTRS{broken_parity_status}=="0"
        ATTRS{class}=="0x0c0330"
        ATTRS{consistent_dma_mask_bits}=="64"
        ATTRS{d3cold_allowed}=="1"
        ATTRS{dbc}=="disabled"
        ATTRS{dbc_bInterfaceProtocol}=="01"
        ATTRS{dbc_bcdDevice}=="0010"
        ATTRS{dbc_idProduct}=="0010"
        ATTRS{dbc_idVendor}=="1d6b"
        ATTRS{device}=="0xa36d"
        ATTRS{dma_mask_bits}=="64"
        ATTRS{driver_override}=="(null)"
        ATTRS{enable}=="1"
        ATTRS{index}=="5"
        ATTRS{irq}=="145"
        ATTRS{label}=="Onboard - Other"
        ATTRS{local_cpulist}=="0-11"
        ATTRS{local_cpus}=="fff"
        ATTRS{msi_bus}=="1"
        ATTRS{msi_irqs/145}=="msi"
        ATTRS{numa_node}=="-1"
        ATTRS{power/async}=="enabled"
        ATTRS{power/control}=="on"
        ATTRS{power/runtime_active_kids}=="1"
        ATTRS{power/runtime_active_time}=="40315796"
        ATTRS{power/runtime_enabled}=="forbidden"
        ATTRS{power/runtime_status}=="active"
        ATTRS{power/runtime_suspended_time}=="0"
        ATTRS{power/runtime_usage}=="1"
        ATTRS{power/wakeup}=="enabled"
        ATTRS{power/wakeup_abort_count}=="0"
        ATTRS{power/wakeup_active}=="0"
        ATTRS{power/wakeup_active_count}=="0"
        ATTRS{power/wakeup_count}=="0"
        ATTRS{power/wakeup_expire_count}=="0"
        ATTRS{power/wakeup_last_time_ms}=="0"
        ATTRS{power/wakeup_max_time_ms}=="0"
        ATTRS{power/wakeup_total_time_ms}=="0"
        ATTRS{power_state}=="D0"
        ATTRS{revision}=="0x10"
        ATTRS{subsystem_device}=="0x08ea"
        ATTRS{subsystem_vendor}=="0x1028"
        ATTRS{vendor}=="0x8086"
    
      looking at parent device '/devices/pci0000:00':
        KERNELS=="pci0000:00"
        SUBSYSTEMS==""
        DRIVERS==""
        ATTRS{power/async}=="enabled"
        ATTRS{power/control}=="auto"
        ATTRS{power/runtime_active_kids}=="14"
        ATTRS{power/runtime_active_time}=="0"
        ATTRS{power/runtime_enabled}=="disabled"
        ATTRS{power/runtime_status}=="unsupported"
        ATTRS{power/runtime_suspended_time}=="0"
        ATTRS{power/runtime_usage}=="0"
        ATTRS{waiting_for_supplier}=="0"