Fix / workaround for non-linear volume control on Linux

Alright, it’s the time of the year where I find time to tinker a little. This time I wanted to find out why changing the volume didn’t feel “linear” for my beloved Teufel CONCEPT 8 2.1 sound system that’s connected to my PC via USB.

First of all I probably have to clarify what I mean by “didn’t feel linear”. I remember learning that human sound perception isn’t linear at all, so that’s probably not accurate. But what I mean here is that: When I slide the volume slider (or make discrete jumps via pactl set-sink-volume alsa_output.usb-NXP_SEMICONDUCTORS_Teufel_CONCEPT_8-00.analog-stereo 60%, for example), the loudest point is reached at already 40, maybe 45%, and after that it doesn’t get any louder. Or maybe it does? But if so, only marginally, and definitely not at the rate it does left of the 40% mark.

So I did some googling, but that turned up nothing specific to these speakers. And also nothing much helpful in general. I suspected some kind of quirk that nobody bothered adding a workaround for in the kernel so far. So I dove into the Linux kernel sources and tried a bunch of changes in sound/usb/mixer_quirks.c – e.g. setting cval->dbMin to different values for the USB ID of the Teufel CONCEPT 8, but also played around with cval->max as well as cval->res. It was rather tedious, because after every change I had to reboot, lacking the knowledge on how to test the changes “on the fly”. While I did observe changes to how the volume changed – e.g. the range where the volume changes fast shifted to the higher end – none of them yielded the results I wanted, i.e. “linear” volume change and no “dead zones” along the slider. So after a while I concluded that with my limited knowledge of the system’s inner workings, I could not understand how the numbers related to what I observed. So I wanted to learn more about the Linux USB audio subsystem, but gave up after a while because I figured that this would take up more time than I was willing to invest.

Just when I wanted to give up completely, I came across a bug report where someone recommended to choose the “Pro Audio” profile for the audio device instead of the “Analog Stereo Output” profile to get rid of this issue. And what can I say: works for me! The PipeWire FAQ states that using the “Pro Audio” profile “disables the hardware mixers, it only enables software volume/mute“. That’s probably what fixes the issue for me. I’d still love to understand why the issue exists in the first place though, and what the underlying layers are doing to mess up something seemingly simple as the volume slider. Maybe next Xmas holidays…?

See below a screenshot of the KDE System Settings / Sound. You can also use pavucontrol or its -qt variant to change the setting.

Leave a Reply

Your email address will not be published. Required fields are marked *