MusicPlayerDaemon / MPD

Music Player Daemon
https://www.musicpd.org/
GNU General Public License v2.0
2.18k stars 351 forks source link

Mixer rounding/writeback bug #822

Closed hifiberry closed 3 years ago

hifiberry commented 4 years ago

Bug report

Describe the bug

MPD updates the ALSA mixer in a way that certain volumes can't bet set

pcm.softvol {
  type softvol
  slave.pcm "ttable"
  control {
    name "Softvol"
    card 0
  }
  min_dB -90.2
  max_dB 0.0
}

Setting mixer to most values works fine, but not for all. Setting the mixer to 58%, MPD first reduces mixer to 57%, then to 56%

Expected Behavior

mpd should not change the mixer value if it has been set outside mpd

Actual Behavior

# amixer sset Softvol 58%; amixer sget Softvol; sleep 1; amixer sget Softvol
Simple mixer control 'Softvol',0
  Capabilities: volume
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: 0 - 255
  Front Left: 148 [58%]
  Front Right: 148 [58%]
Simple mixer control 'Softvol',0
  Capabilities: volume
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: 0 - 255
  Front Left: 148 [58%]
  Front Right: 148 [58%]
Simple mixer control 'Softvol',0
  Capabilities: volume
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: 0 - 255
  Front Left: 142 [56%]
  Front Right: 142 [56%]

Version

# mpd -V
Music Player Daemon 0.21.11 (0.21.11)
Copyright 2003-2007 Warren Dukes <warren.dukes@gmail.com>
Copyright 2008-2018 Max Kellermann <max.kellermann@gmail.com>
This is free software; see the source for copying conditions.  There is NO
warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Database plugins:
 simple proxy upnp

Storage plugins:
 local smbclient udisks curl

Neighbor plugins:
 smbclient upnp udisks

Decoders plugins:
 [mad] mp3 mp2
 [vorbis] ogg oga
 [oggflac] ogg oga
 [flac] flac
 [opus] opus ogg oga
 [sndfile] wav aiff aif au snd paf iff svx sf voc w64 pvf xi htk caf sd2
 [dsdiff] dff
 [dsf] dsf
 [hybrid_dsd] m4a
 [faad] aac
 [wavpack] wv
 [ffmpeg] 16sv 3g2 3gp 4xm 8svx aa3 aac ac3 adx afc aif aifc aiff al alaw amr anim apc ape asf atrac au aud avi avm2 avs bap bfi c93 cak c
in cmv cpk daud dct divx dts dv dvd dxa eac3 film flac flc fli fll flx flv g726 gsm gxf iss m1v m2v m2t m2ts m4a m4b m4v mad mj2 mjpeg mjp
g mka mkv mlp mm mmf mov mp+ mp1 mp2 mp3 mp4 mpc mpeg mpg mpga mpp mpu mve mvi mxf nc nsv nut nuv oga ogm ogv ogx oma ogg omg opus psp pva
 qcp qt r3d ra ram rl2 rm rmvb roq rpl rvc shn smk snd sol son spx str swf tak tgi tgq tgv thp ts tsp tta xa xvid uv uv2 vb vid vob voc vp
6 vmd wav webm wma wmv wsaud wsvga wv wve
 [pcm]

Filters:
 libsamplerate

Tag plugins:
 id3tag

Output plugins:
 shout null fifo pipe alsa recorder

Encoder plugins:
 null vorbis opus lame wave flac

Input plugins:
 file alsa qobuz curl ffmpeg smbclient

Playlist plugins:
 extm3u m3u pls xspf asx rss soundcloud flac cue embcue

Protocols:
 file:// alsa:// qobuz:// http:// https:// gopher:// rtp:// rtsp:// rtmp:// rtmpt:// rtmps:// smb://

Other features:
 avahi dbus udisks epoll icu inotify ipv6 systemd tcp un

Log

no relevant logs

MaxKellermann commented 4 years ago

Your MPD version is 11 bug-fix releases behind. If you choose not to apply bug fixes, I cannot provide support.

hifiberry commented 4 years ago

While I can try a newer version, according to the release notes nothing like this has been changed in the last releases.

MaxKellermann commented 4 years ago

Maybe you're right, maybe not, but let's not speculate.

hifiberry commented 4 years ago

Same with

# mpd -V
Music Player Daemon 0.21.21 (0.21.21)
scripple commented 4 years ago

This is a problem in the set/get_normalized_volume routines you borrowed from ALSA's alsamixer. They are not set and forget routines. You set one value and you get back another. And it matters based on the direction. So you can actually keep setting the same volume value in mpd and it will toggle between two values neither the one you set.

Here's the volume output reported by mpd status after a setvol command on an upward sweep from 0 to 100 using version Music Player Daemon 0.21.26 (v0.21.26+). This is for a hardware volume control with range in 1dB steps from -127 to 0 dB. The behavior will change for every alsa hardware mixer based on the range and step size of that mixer. One would hope return would be 0 - 100, but it's not. It actually has steps where increasing the value in setvol lowers the volume.

0, 1, 2, 3, 4, 5, 6, 8, 8, 9, 10, 11, 12, 13, 15, 15, 16, 17, 19, 19, 20, 22, 22, 24, 24, 26, 26, 27, 28, 29, 30, 31, 32, 34, 34, 35, 36, 38, 38, 39, 41, 41, 43, 43, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 63, 60, 65, 63, 65, 68, 65, 71, 68, 71, 71, 73, 73, 76, 73, 79, 76, 79, 79, 82, 79, 82, 86, 82, 86, 86, 89, 86, 89, 93, 89, 93, 93, 96, 93, 96, 100, 96, 100, 100

alsamixer's normalize volume routines are not good and that's what you're using. They waste resolution of the hardware and have bands of input numbers on the 0-100 scale that cannot be realized by the hardware. If you watch how they're used in alsamixer when you say ask for 90 and it can't get it it just jumps up to 93. That's what you do too but this behavior requires every mpd client based on alsa to be aware of this and report this oddity to the user. Otherwise you get what see above. Up, down, up, down. That happens because the hardware can't reach those values on the odd cubic root scale ALSA made up. Also any number you go to is likely to produce a different value based on whether it is above or below the current value.

Please remove the set/get normalized volume routines and replace them with something better. They only exist to try and quickly skip over the very quiet values at the bottom.

Try linear dB steps if the output device has less than 100 dB dynamic range. You'll have dead steps but it will be repeatable and the volume status will always be what was set. For a mixer with dynamic range greater than 100 dB try linear dB steps from say 100 downto 15 or 10. That's 85 or 90 dB of attenuation range and no one is likely use lower as it's so quiet. So just compress the remainder in linear > 1 dB steps to use up the extra. Something like that. You'll see my chart below that going from 0 ot 1 in mpd is a 22dB increase. But going from 94-100 is only a 1 dB increase in an oscillation -1dB 0dB pattern.

You don't even need mpd to see this. Load up alsamixer (not amixer it doesn't use these normalize routines) on various computers and select a hardware mixer and walk the volume up and down by 1. Watch the output jump around.

I assure you the problem is in set/get normalized volume in MPD/src/mixer/plugins/volume_mapping.c which is called by the alsa mixer.

Below are the actual dB hardware values set by mpd for the sweep from 0 to 100. 0 -127.00dB 1 -105.00dB 2 -93.00dB 3 -85.00dB 4 -78.00dB 5 -73.00dB 6 -69.00dB 7 -65.00dB 8 -65.00dB 9 -65.00dB 10 -59.00dB 11 -56.00dB 12 -53.00dB 13 -51.00dB 14 -49.00dB 15 -49.00dB 16 -47.00dB 17 -45.00dB 18 -43.00dB 19 -43.00dB 20 -41.00dB 21 -39.00dB 22 -39.00dB 23 -37.00dB 24 -37.00dB 25 -35.00dB 26 -35.00dB 27 -34.00dB 28 -33.00dB 29 -32.00dB 30 -31.00dB 31 -30.00dB 32 -29.00dB 33 -28.00dB 34 -28.00dB 35 -27.00dB 36 -26.00dB 37 -25.00dB 38 -25.00dB 39 -24.00dB 40 -23.00dB 41 -23.00dB 42 -22.00dB 43 -22.00dB 44 -21.00dB 45 -20.00dB 46 -20.00dB 47 -19.00dB 48 -19.00dB 49 -18.00dB 50 -18.00dB 51 -17.00dB 52 -17.00dB 53 -16.00dB 54 -16.00dB 55 -15.00dB 56 -15.00dB 57 -14.00dB 58 -14.00dB 59 -13.00dB 60 -13.00dB 61 -12.00dB 62 -13.00dB 63 -11.00dB 64 -12.00dB 65 -11.00dB 66 -10.00dB 67 -11.00dB 68 -9.00dB 69 -10.00dB 70 -9.00dB 71 -9.00dB 72 -8.00dB 73 -8.00dB 74 -7.00dB 75 -8.00dB 76 -6.00dB 77 -7.00dB 78 -6.00dB 79 -6.00dB 80 -5.00dB 81 -6.00dB 82 -5.00dB 83 -4.00dB 84 -5.00dB 85 -4.00dB 86 -4.00dB 87 -3.00dB 88 -4.00dB 89 -3.00dB 90 -2.00dB 91 -3.00dB 92 -2.00dB 93 -2.00dB 94 -1.00dB 95 -1.00dB 96 -1.00dB 97 0.00dB 98 -1.00dB 99 0.00dB 100 0.00dB

TookaFace commented 4 years ago

I also have this problem with mpd 0.22 and hardware volume, setting volume is inconsistent, mostly in 100-80 volume range.

mpc volume 100
volume:100%   repeat: off   random: on    single: off   consume: off
pi@moode:~ $ mpc volume 98
volume: 96%   repeat: off   random: on    single: off   consume: off
pi@moode:~ $ mpc volume 98
volume:100%   repeat: off   random: on    single: off   consume: off
pi@moode:~ $ mpc volume 98
volume: 96%   repeat: off   random: on    single: off   consume: off
mpc volume 92
volume: 89%   repeat: off   random: on    single: off   consume: off
pi@moode:~ $ mpc volume 92
volume: 92%   repeat: off   random: on    single: off   consume: off