75
submitted 1 year ago* (last edited 1 year ago) by mmstick@lemmy.world to c/pop_os@lemmy.world

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.

you are viewing a single comment's thread
view the rest of the comments
[-] humblegnome@lemmy.world 2 points 1 year ago

Cheers for this guide!

i have been having difficulty trying to understand the naming conventions for the sofa files as posted in the ari databases, such that i could somehow choose one that i think would best suit. The documentation doesn’t really help, and i haven’t found a write up on it that addresses this in a mere human readable way, i am anything but a coder and don’t use matlab for anything. Any suggestions?

The following should work to automate turning on 7.1 when headphones plugged in. I would def suggest using at least two terminal instances to help with the copy/pasta goodness.

Use systemd to automate:

sudo nano /etc/systemd/system/pipewire-headphones.service

in said file use the following:

######################################

[Unit] Description=Run Pipewire with filter-chain when headphones are plugged in Wants=sys-devices-pci0000:40-0000:40:01.1-0000:41:00.0-0000:42:08.0-0000:45:00.3-usb9-9\x2d2-9\x2d2:1.0-sound-card1-controlC1.device BindsTo=sys-devices-pci0000:40-0000:40:01.1-0000:41:00.0-0000:42:08.0-0000:45:00.3-usb9-9\x2d2-9\x2d2:1.0-sound-card1-controlC1.device

[Service] ExecStart=/bin/pipewire -c /home/USER/.config/pipewire/filter-chain.conf.d/filter-chain.conf User=your_username Group=your_groupname [Install] WantedBy=default.target

######################################

Replace /path/to/pipewire with the actual path to the pipewire binary and /path/to/filter-chain.conf with the path to your filter-chain.conf configuration file. Also, replace your_username and your_groupname with your actual username and group name.

To obtain Wants, and BindsTo= path

Plug in desired device

ls /dev/input/by-id/

copy name of your device

eg: usb-Logitech_PRO_X_000000000000-event-if03

then:

sudo udevadm info --attribute-walk --path=$(udevadm info --query=path --name=/dev/input/by-id/usb-Logitech_PRO_X_000000000000-event-if03)

locate “looking at parent device” that matches to your device, add to service file.

save file.

the udevadm command will also allow you to obtain info needed for the udev rule.

Now Create udev rule.

sudo nano /etc/udev/rules.d/99-headphones.rules

enter text:

################################################

ACTION=="add", SUBSYSTEM=="input", ENV{ID_INPUT}=="1", ENV{ID_VENDOR_ID}=="046d", ENV{ID_PRODUCT}=="0aaa", ENV{PHYS}=="usb-0000:45:00.3-2/input3", ENV{SYSTEMD_WANTS}="pipewire-headphones.service"

################################################

ID_VENDOR_ID =ATTRS{id/vendor}=="046d" etc

save file.

sudo udevadm control --reload sudo systemctl daemon-reload

for manual start/stop:

sudo systemctl start pipewire-headphones.service sudo systemctl stop pipewire-headphones.service

To have service started and enabled at boot:

sudo systemctl enable - -now pipewire-headphones.service

why sudo systemctl daemon-reload

Have tested with logi headphones using the usb dac, and then the standard jack seems to work ok, in ubuntu appears as virtual-surround-sink,though I did have to choose this as my device manually. this should also stop the service if the device is unplugged.

To automate that you could edit the service Execstart entry :

ExecStart=/bin/sh -c 'pipewire -c /path/to/filter-chain.conf && pactl set-default-sink your_virtual_surround_sink_name'

Hope this is useful :)

[-] Deewens@lemmy.world 1 points 10 months 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"
this post was submitted on 20 Jul 2023
75 points (98.7% liked)

Pop!_OS (Linux)

5062 readers
1 users here now

Pop!_OS is an operating system developed by System76 for STEM and creative professionals who use their computer as a tool to discover and create. Unleash your potential on secure, reliable open source software. Based on your exceptional curiosity, we sense you have a lot of it.

Unleash your potential

Whether this is your first experience with Linux, or your latest adventure, all are welcome to discuss and ask questions about Pop!_OS and COSMIC. Keep the discussions friendly though, and remember to assume good intentions whenever you reply. We're all here because we have a shared love for Linux and open source software.

System76 Logo

Support us by buying System76 hardware for you or your company! Or by donating on the Pop!_OS website through the "Support Pop" button. Pop!_OS and COSMIC are fully funded by System76 hardware sales. All systems are assembled in the USA. With your support, we'll work to push the Linux desktop forward with COSMIC.

Links

Guides

Hardware

Recommended

Community Rules

Follow the Code of Conduct

All posts on pop_os must adhere to the Pop!_OS community Code of Conduct. https://github.com/pop-os/code-of-conduct

Be helpful

Posts to pop_os must be helpful. When responding to a user asking for help, do not provide tongue-in-cheek responses like "RTM" or links to LMGTFY. Linking to direct sources that answer the asker's question is fine, but it's advised to provide some explanation as to how you got to that source.

Critique should be constructive

We within the Pop!_OS community welcome helpful criticism or ideas on ways to improve. However, basic "It's bad" or other simple negative comments don't help anyone fix anything. When voicing a complaint about something, try to point out ways the complaint could be improved or worked around, so that we can make a better product for it.

This rule applies to both Pop!_OS and its projects as well as other products available from third-parties.

Don't post malicious "advice"

It can be funny to joke about malicious commands, however this is not the venue for it. Do not advise users to run commands which will lock up their systems, steal their data, or erase their drive. Examples of this include (but are not limited to) fork bombs, rm, etc.

Posts violating this rule will be removed, even if the post is clearly in jest. Repeated offences may lead to a ban. You may understand that the command isn't serious, but a new user might not.

No personal attacks

Posts making a personal attack on any user will not be tolerated.

No hate speech

Hate speech of any kind will not be tolerated. Any violations will be removed, and are grounds for a ban.

founded 1 year ago
MODERATORS