-
Notifications
You must be signed in to change notification settings - Fork 354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added log scale to AlsaMixerPlugin #20
Conversation
Why? |
I don't know if it only is relevant for Alsa, but I use mpd on an raspberry with an IQaudio DAC and needed this change to make it work more correctly with the volume in mpd. So this is just a suggestion, that can be merged in if others could use it. |
I have no idea if it's useful, but from what you just wrote, it sounds like a bug in the DAC device driver, and should be fixed there. |
Using amixer (libasound I guess) I get and set in the linear scale, which means that almost nothing is happening up until 50%. alsamixer however uses a scale that seem to be logarithmic, which makes more sense when changing the volume, so I wanted to make mpd behave like alsamixer on the volume scale.
|
If you want it to behave like alsamixer, then why does your code need explicit configuration, but alsamixer just works? |
I don't know why alsamixer "just works", as I (also) thought that alsamixer just was a nicer interface to libasound/amixer. But as my output from amixer and alsamixer shows above that is not the case. You are probably right that the correct way would be to find the root of that difference and update libasound, but I think that is more difficult and a longer way for me than this change to the mpd mixer control. |
Why don't you try to find out what alsamixer does differently? It would be desirable to improve MPD to "just work" with your hardware as well, and maybe there's an obvious trick we're missing. |
found this thread at runeaudio (http://www.runeaudio.com/forum/volume-control-linear-or-logarithmic-t254.html) and the -M flag of amixer does actually make it behave like alsamixer.
So do you have an idea of how I/we can make mpd interact with libasound by setting the prc (and hopefully also with something like the -M flag of amixer), and not by final level values as it does now where mpd calculates the linear level value from the user prc input. |
This looks like MPD already does exactly what you want, doesn't it? It shows the same value as |
yes in my updated code with the log scale ;) with the default linear calculation of level in mpd it would be:
|
It seems like amixer with the set_playback_mapped_volume makes a log calculation to dB and then set sound based on dB
http://git.alsa-project.org/?p=alsa-utils.git;a=blob_plain;f=amixer/amixer.c;hb=HEAD |
That looks like something which could be useful for MPD. |
That's a more direct way than I did. I am starting to implement that instead in my fork... |
Usually, I'd favor a general approach like the one you suggested. But in this case, a general approach is not needed, when the ALSA project itself has code for a general solution which does not need any configuration. We could easily copy |
I have now implemented the volume_mapping from alsa-utils/alsamixer (with a few changes) and rewritten AlsaMixerPlugin to use those functions to get and set volume - so much simpler now... Now mpd behaves as alsamixer on my setup. Can you have a look at my changes and comment? |
It's very hard to review your commits, because some of them add new code, the another commit replaces that new code with other code, then another one fixes a problem ... please fold those patches in a meaningful way. |
Branched my local development and committed to master only: I hope this makes it more clear what the final suggested changes are. |
This would be great and allow MPD based apps (Volumio / RuneAudio / MoodeAudio to name a few) to standardise on the way they resolve this. It would also reduce customer emails :-) Thanks for driving and supporting this change. |
If you compile mpd from my fork you can test it already now, to see if it act as expected before merging it in to main master. |
|
Yep i got that as well, but it still compiled and worked, so didn't get to look further into it... Do you know why they have that line in volume_mapping? |
Yes, because MPD defines _GNU_SOURCE globally - but ALSA doesn't. It compiles, but only without |
so we just remove the line, end of story no? small issue: |
Always round properly when you convert floating point to integer. Don't add |
@@ -43,6 +41,7 @@ | |||
#endif /* __UCLIBC__ */ | |||
|
|||
#define MAX_LINEAR_DB_SCALE 24 | |||
#define SND_CTL_TLV_DB_GAIN_MUTE -9999999 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why define that one again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you mean again? Where is it defined? Doing this fixed my issue, as min on my card actually is -9999999
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/usr/include/alsa/control.h:#define SND_CTL_TLV_DB_GAIN_MUTE -9999999
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm... it seems you are right (again...). Don't know why I decided that I saw a rounding issue earlier with this setting. I'll reset commits back and remove the _GNU_SOURCE line from the first commit.
@@ -31,8 +31,6 @@ | |||
*/ | |||
|
|||
#define _ISOC99_SOURCE /* lrint() */ | |||
#define _GNU_SOURCE /* exp10() */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ordering of commits is wrong. With this ordering, we have a commit that we know fails to build - which breaks git bisect
. Better amend the original commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get what you mean by amending the original commit. Do you suggest I "reset --hard" back to that commit and re commit without the line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. I don't know about your tools, but I use stgit, and stgit allows me to amend older commits easily. This can be done with plain git, and may involve the "reset" command, but I don't know. It's more complicated with plain git.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have only used plain git (and also managed to get it to work here, but I will have a look on stgit, that I didn't know about. Thanks!
Something went wrong. Why is there a merge commit? |
And while you're fixing your branch: it's a good idea to rebase your branch on the official master branch before (re)submitting. That is, |
Changed AlsaMixerPlugin to use the get and set normalized functions from volume_mapping of alsa-utils/alsamixer Changed volume_mapping set volume to be for all channels and not per channel added volume_mapping files to Makefile.am
got it... slowly learning the tricks of git. didn't know about the -amend trick (nice). Had to --force because it then was considered before remote/head. what is the difference to your git here at github and the one at musicpd.org? |
Both mirror the same contents. You can use either. |
Merged with a bunch of fixups. |
2 new keywords to mpd.conf:
-enable log scale instead of linear scale:
mixer_scale "log"
(everything else will use linear scale)
-extra log scale tuning parameter (used to make the scale fit alsamixer)
mixer_log_param "1.164"
(default is 1.0, 1.164 is found to make the scal fit with alsamixer)
** equations for the conversion between prc to log scale **
prc in log scale to volume level:
level = scale_log_param*(volume_max-volume_min)*(log(vol)/log(100.)-1. + volume_max+0.5
level to prc in log scale:
exp( log(100)(level-volume_max)/(scale_log_param(volume_max-volume_min)) + log(100))