From 1e7c4dd3e6af5bb91bf5e9985725396ebd06293f Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sun, 8 May 2011 12:44:50 +0100 Subject: alsa-mixer: When setting hw volume, always round up with playback and down with capture. The previous logic in ade0a6f88464d8aecf83982d400ccfc402341920 does not work with for input volumes. This was discussed on the mailing list: https://tango.0pointer.de/pipermail/pulseaudio-discuss/2011-May/010091.html This approach can introduce a problem when setting the volumes for sources. What follows is Tanu Kaskinen's analysis: [quote] I'll quote the log: D: protocol-native.c: Client pavucontrol changes volume of source alsa_input.pci-0000_00_1b.0.analog-stereo. D: alsa-source.c: Requested volume: 0: 45% 1: 45% D: alsa-source.c: in dB: 0: -20.71 dB 1: -20.71 dB D: alsa-source.c: Got hardware volume: 0: 45% 1: 45% D: alsa-source.c: in dB: 0: -21.00 dB 1: -21.00 dB D: alsa-source.c: Calculated software volume: 0: 101% 1: 101% (accurate-enough=no) D: alsa-source.c: in dB: 0: 0.29 dB 1: 0.29 dB D: source.c: Volume going up to 29273 at 270475970821 D: source.c: Volume change to 29273 at 270475970821 was written 34 usec late D: alsa-source.c: Written HW volume did not match with the request: 0: 45% 1: 45% (request) != 0: 42% 1: 42% D: alsa-source.c: in dB: 0: -21.00 dB 1: -21.00 dB (request) != 0: -22.50 dB 1: -22.50 dB Looking at the last line, the requested volume seems to hit exactly the right step (-21.00dB), but for some reason Alsa decides to choose something else. I'm pretty sure that this happens because of rounding errors. In the first phase we ask Alsa what dB value we should set, and it returns -21.00 dB. The value is given as a long int, but we convert that to pa_cvolume. Then when we set the volume, we convert the pa_cvolume value back to a long integer. At this point I believe it gets converted to -2101. This is not visible in the debug message for some reason - the rounding algorithm must be different from what was used with the pa_cvolume -> long conversion. [/quote] The commit after this contains a patch that addresses this issue. --- src/modules/alsa/alsa-mixer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 03a5312a..e3673f8c 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -893,7 +893,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann if (e->has_dB) { long value = to_alsa_dB(f); - int rounding = value > 0 ? -1 : +1; + int rounding; if (e->volume_limit >= 0 && value > (e->max_dB * 100)) value = e->max_dB * 100; @@ -903,6 +903,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann * if the channel is available, ALSA behaves very * strangely and doesn't fail the call */ if (snd_mixer_selem_has_playback_channel(me, c)) { + rounding = +1; if (e->db_fix) { if (write_to_hw) r = snd_mixer_selem_set_playback_volume(me, c, decibel_fix_get_step(e->db_fix, &value, rounding)); @@ -925,6 +926,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann r = -1; } else { if (snd_mixer_selem_has_capture_channel(me, c)) { + rounding = -1; if (e->db_fix) { if (write_to_hw) r = snd_mixer_selem_set_capture_volume(me, c, decibel_fix_get_step(e->db_fix, &value, rounding)); -- cgit