alsa: acp: don't disable dB if negative max unless range is small

Disabling dB volumes for max_dB < 0 was added in Pulseaudio in 2021,
based on a device which had -128..-127.07 range. However, negative
max_dB is valid value for USB devices, and there are devices that have
it.

Eg. Microsoft LifeChat LX-3000 has

numid=6,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=2,min=0,max=151,step=0
  : values=150,150
  | dBminmax-min=-28.37dB,max=-0.06dB

and the dB range seems to be OK. Web search for "The decibel volume
range for element" also gives other hits with seemingly OK looking
ranges.

Don't disable dB volume unless both the max is negative and the range is
suspiciously small. This should still disable it for the device this
check was originally added for.

Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/447
Link: 10ac01a206
This commit is contained in:
Pauli Virtanen 2025-10-15 20:11:36 +03:00
parent a75cea96fb
commit da2cecf074

View file

@ -1719,11 +1719,15 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
else
e->has_dB = snd_mixer_selem_get_capture_dB_range(me, &min_dB, &max_dB) >= 0;
/* Assume decibel data to be incorrect if max_dB is negative. */
if (e->has_dB && max_dB < 0 && !e->db_fix) {
/* Assume decibel data to be incorrect if max_dB is negative and dB range is
* suspiciously small (< 10 dB). This can happen eg. if USB device is using volume
* values as arbitrary scale ignoring USB standard on their meaning.
*/
if (e->has_dB && max_dB < 0 && SPA_ABS(max_dB - min_dB) < 10*100 && !e->db_fix) {
pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("The decibel volume range for element %s (%li dB - %li dB) has negative maximum. "
"Disabling the decibel range.", buf, min_dB, max_dB);
pa_log_warn("The decibel volume range for element %s (%0.2f dB to %0.2f dB) has negative maximum "
"and suspiciously small range. "
"Disabling the decibel range.", buf, min_dB/100.0, max_dB/100.0);
e->has_dB = false;
}