Framework 16 speaker volume curve issue

The link to the arch wiki didn’t work with the anchors (at least for me), so I was wondering where to look exactly in that rather long article.

But I found the part for the rule you mentioned. So I created a file:
~/.config/wireplumber/wireplumber.conf.d/alsa-soft-mixer.conf

monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "alsa_output.pci-0000_c1_00.6.HiFi__Speaker__sink"
      }
    ]
    actions = {
      update-props = {
        # Do not use the hardware mixer for volume control. It
        # will only use software volume. The mixer is still used
        # to mute unused paths based on the selected port.
        api.alsa.soft-mixer = true
      }
    }
  }
]

Then `systemctl --user restart pipewire` and…

Nothing changed.

So, you may want to describe your solution a little more detailed to be helpful :wink:

1 Like

Hm, looks like the auto formatting on this forum is eating my links. I tried to link directly to the section I was referencing, sorry about that!

Here, we’re looking for “Obtain interface name for rules matching”

After running wpctl status, find the audio device in the list. For me, it was called Ryzen HD Audio Controller. Then I inspected that device and found the device.name property and used that. Maybe use the device’s device.name instead of node.name? I am very new to Linux so I am not an expert on any of this but best of luck!

Yeah the output of wpctl inspect ID has no entry named “device.name”.
But the match is not the problem here.
The file is read and the config is put on that device.
It is just that Pipewire, Wireplumber and/or the OS doesn’t care a bit…

Okay, yeah it sounds like you are not using the correct ID. At least on my setup, inspecting the correct ID gave me a device.name and not a node.name. You should try finding the ID on your system that has the property mentioned. I posted the device I used above for reference. Other than that, I’m out of ideas. GLHF!

the alsamixer sliders have dB values associated with them. Look in the upper left corner of the window.
If you set them all the 0dB, and then use software volume control, that will probably be best.
It is a shame we don’t have the data sheets for the audio chips.
It would be good if we could put a low pass filter on the Bass speaker output, because it would sound better if treble audio was not sent to a base speaker, and a high pass filter on the non-base speaker.
with “speaker-test” one can output various audio tests, sine waves at various frequencies, and pink noise or just output a .wav file.
It is actually interesting, because there are various common speaker patterns.
E.g. 5.1 with the .1 being the LFE speaker.
The common profiles are:
2.0
2.1
4.0
4.1
5.0
5.1
7.1

The FW16 laptop has just two audio channels for output, but it would have been nice if it was instead 2.2. I.e. two LFE / Bass channels and two non-bass channels.
The application could then have crafted the high and low pass filters to improve the output.

You are right, the labeling of the speakers in alsamixer is wrong.
Bass and non-bass mixer sliders are swapped.

I am starting to think, you are trolling us here.
The output of wpctl inspect ID has no device.name.

In the device section there are:

device.api = "alsa"
    device.bus = "pci"
    device.class = "sound"
    device.icon-name = "audio-card-analog"
    device.icon_name = "audio-speakers"
  * device.id = "44"
    device.profile.description = "Speaker"
    device.profile.name = "HiFi: Speaker: sink"
    device.routes = "1"

But as I said, that is not the problem. The file is found and used. The settings are made - they just don’t do anything!

I never would have thought that such a rather simple mapping is such a hard or impossible task in Linux…

Haha! No trolling here.

Alright, you’re so close! One last attempt from me:

How do you know that is not the problem if you haven’t fixed the issue?

You are not using an audio interface / device ID that has a device.name property.

This suggests you made a rule that is irrelevant to the problem you are trying to solve. Let’s try making a rule that will solve the problem!

As the wiki links I posted said, run wpctl status to list all audio devices, sinks, and sources. We don’t care about microphones here so we can ignore sources, however we need to apply the rule systematically to each of the devices and sinks until we find the right one on your system.

Start with the first device. Look at the number next to it. Let’s say it’s 01 for example. That is the ID for that device. In this example, I would type wpctl inspect 01 to list the properties. Look through all of the properties and try to find device.name If you don’t see it in the list, try again using a different audio device or sink. Keep repeating this process until you find one with a device.name property.

Once you find one with a device.name property, use that to create the rule for alsa. Reboot after saving and see if it worked. If it didn’t work, try another audio device or sink. You will need to go through all of your audio devices, not just one. Remember, you are looking for one with a device.name property and not a node.name property.

Me neither! But reading through the arch wiki provided the steps necessary and helped me, someone that is very new to Linux as a whole, troubleshoot and configure my device. I feel empowered! If I can do it, other people can too. You just have to take in the information in front of you and apply some critical thinking, and maybe a bit of improv. You’ll get it done!

If you still can’t find the correct property after all this, maybe try a different OS or wait for someone else to help. I’m a noob, after all!

1 Like

Yes, if you take the ID of a device there is a device.name in the output.
I worked with the ID of the sink and sinks do not have a device.name field.

However, indeed something finally happened when applying the config
api.alsa.soft-mixer = "true"
to the whole device, instead of just its sink.

On logout and login (which is okay, because the config is in ~/.config/…) I could control the volume and no slider at all was moving on alsamixer.
The Master and the “Bass”-Speaker are on 100% while the “Speaker” is on 37, everytime after boot/login. That is still not okay.

So, actually it is not exactly what I want but already a good compromise. That way bass is still a bit too light but at least consistent.

My absolute favorite would be to have (and keep) Speaker and Bass-Speaker on 100% and simply control the master slider…
But that seems to be a riddle hard to solve…

1 Like

HI Folks,

Can I get a list of the following?

  • Distro and kernel version

  • BIOS version

  • Confirm you noticed what you describe as a better result from disabling Linux Audio in BIOS? Yes or no

  • For in OS workarounds, please list them and how you view the result (improved, same, worse)

Thanks

2 Likes

Woo! Support to the rescue!

Distro and kernel version: arch 6.18.5, and fedora 6.18.6

BIOS version: 3.04

Better result from disabling Linux Audio in BIOS: no

OS workarounds:

  • Added ~/.config/wireplumber/wireplumber.conf.d/alsa-soft-mixer.conf file containing this:
    •  monitor.alsa.rules = [
        {
          matches = [
            {
              "device.name" = "alsa_card.pci-0000_c2_00.6"
            }
          ]
          actions = {
            update-props = {
              api.alsa.soft-mixer = true
            }
          }
        }
      ]
      
  • Then restarted wireplumber and set volume for the sound card to max through alsamixer
  • This has improved the speaker response by making it possible to adjust the volume through gnome smoothly from quiet to loud with the bass + treble in sync.
  • The audio is still worse (muddier and quieter) than before my mainboard swap.

I did a mainboard upgrade from the original 16 to the hx370. This audio issue only started happening after the upgrade. The audio had been excellent on my 7840hs. All other hardware is the same except for the mainboard.

Distro and Kernel: Fedora 43, Kernel 6.18.6-200.fc43.x86_64

BIOS: 3.04

If I set Audio to Windows, I have no internal audio device at all. I need to set it to Linux Audio.
So: no. Result is not better when I disable it. It is much worse.

The only workaround seems to be the software mixer. While the “Speaker” (bass speaker) level is on 36% after reboot.

I wish Framework would fix that with a decent config for their chosen hardware :slight_smile:
Thank you!

For me, the best results so far were with soft-mixer and Linux audio in BIOS (using NixOS unstable).

With Linux audio compatibility on, the issue is that alsamixer shows 3 mixers for default:1card: Master, Speaker and Bass Speaker; if I set Speaker and Bass Speaker to max, then adjust Master, I get good and cohesive audio quality all the way. Main problem is that wireplumber/pipewire insist in trying to change the Speaker mixer only, which messes audio quality, specially on lower volumes.

soft-mixer works just because it allows me to leave all 3 “hardware mixers” at max in alsamixer, and switches PipeWire to control a “software master” instead; I’d say best outcome would be to figure out a way to make Wireplumber understand sink’s main mixer is Master, and leave the others alone, but I couldn’t figure out how to do that with the api.alsaproperties overrides.

I now have what I wanted!

If I control main volume, it takes “Master” and not “Speaker” - yay!

How?
I had to edit the file: /usr/share/alsa/ucm2/HDA/HiFi-analog.conf
That change will surely be overwritten by system updates. There are ways to come around that too…

This file is the place where WirePlumber gets its info from, what to use as main volume.
As I can not upload the file here, I try to explain the changes to be made:

First make sure to create a copy of that file!

In the top of the file change
Define.spkvol "Speaker"Define.spkvol "Master"

Then the section If.spk (line 170) must change to

If.spk {
	Condition {
		Type String
		Empty "${var:spkvol}"
	}
	False.SectionDevice."Speaker" {
		Comment "Speaker"

		If.seq {
			Condition {
				Type ControlExists
				Control "name='Bass Speaker Playback Switch'"
			}
			True {
				EnableSequence [
					cset "name='Speaker Playback Volume' 100%"
					cset "name='Bass Speaker Playback Volume' 100%"
					cset "name='Speaker Playback Switch' on"
					cset "name='Bass Speaker Playback Switch' on"
				]

				DisableSequence [
					cset "name='Speaker Playback Switch' off"
					cset "name='Bass Speaker Playback Switch' off"
				]
			}
			False {
				EnableSequence [
					cset "name='Speaker Playback Volume' 100%"
					cset "name='Speaker Playback Switch' on"
				]

				DisableSequence [
					cset "name='Speaker Playback Switch' off"
				]
			}
		}

		Value {
			PlaybackPriority 100
			PlaybackPCM "hw:${CardId}"
			PlaybackMixerElem "${var:spkvol}"
			PlaybackVolume "${var:spkvol} Playback Volume"
			PlaybackSwitch "${var:spkvol} Playback Switch"
		}

		If.master {
			Condition {
				Type String
				String1 "${var:spkvol}"
				String2 "Master"
			}
			False.Value.PlaybackMasterElem "Master"
		}
	}
}

After that, type
rm -r ~/.local/state/wireplumber && systemctl --user restart pipewire pipewire-pulse wireplumber
to delete the cache and restart all the sound stuff.

That’s all.

I found no clean way to implement the changes somewhere in Home.
The only way to do so is to copy the file, make the changes and mount it over the original one. Needs entries in fstab then…

Link to repo!

3 Likes