Skip to content
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

Differences between shairport-sync's built-in SW volume and ALSA Softvol? [resolved] #651

Closed
tuomashamalainen opened this issue Jan 25, 2018 · 31 comments
Labels

Comments

@tuomashamalainen
Copy link

First of all, my thanks for the incredible work on shairport-sync. I've used it in multiple projects within the last two years and it's been rock-solid so far 👌

Background

I'm working on a sound system that features shairport-sync, Spotify Connect and Bluetooth for streaming audio. On the hardware side there is a Pi 3 connected to a BeoCreate 4-Channel Amplifier, which is a combined I2S DAC/DSP/amplifier and works with the HiFiBerry DAC driver preinstalled in Raspbian (Lite Stretch in this case). The board does not expose hardware mixer controls through ALSA, so Softvol is used to enable volume control with Spotify and Bluetooth.

Previously I've used shairport-sync's built-in software volume control, but was hoping to bring shairport-sync also behind Softvol for consistency. Both of these approaches work for volume control, seem to behave very differently from each other.

In essence, shairport-sync's built-in SW volume works just the way I want it: it has a good amount of resolution at quiet and normal listening levels where it is needed. With Softvol, however, the volume increases rapidly at the beginning of the scale and then more slowly as volume is turned up, which is rather inconvenient unless the preferred listening level is very high (way too high for pleasant normal listening in a room).

I plotted the position of iTunes volume slider against the volume level reported by alsamixer to illustrate what I mean:
screen shot 2018-01-25 at 18 23 39

The ALSA configuration I use can be found here, and the shairport-sync configuration here:

The Question

Reading the documentation, it looks like shairport-sync does use a nonlinear volume control curve, and I suppose this is what we're looking at on the chart. However, is it by design that the actual volume is so different depending on whether the built-in SW volume control or ALSA Softvol is used? The built-in SW volume control is just about perfect as far as my ears are concerned; is there a way to get the same from Softvol?

🖖

@joerg-krause
Copy link

Long time ago, I added support for the softvol plugin to shairport-sync. I've plotted the same volume attenuation graph here :-)

The thing is, that the ALSA softvol plugin does use a logarithmic curve for attenuation as you can see when plotting the preset dB values from here:

image

@tuomashamalainen
Copy link
Author

tuomashamalainen commented Jan 26, 2018

Thank you Jörg, I can't believe I missed the graph in the original thread 😊 So I'm hearing the cumulative effect of shairport-sync's vol2attn on top of ALSA's logarithmic Softvol curve.

What are the options here to get vol2attn out of the mix and only use Softvol (which alone seems to do a reasonable job too)? Anything besides writing a separate script for run_this_when_volume_is_set that linearly maps the AirPlay dB values to alsamixer control values? (Edit: like here)

@mikebrady
Copy link
Owner

Sorry — I’ve been a bit busy to comment here. I’ll try to respond tomorrow.

@mikebrady
Copy link
Owner

mikebrady commented Jan 27, 2018

Thanks for the interesting posts.

Shairport Sync always assumes that the attenuator or volume control device is strictly logarithmic, whether it's a mixer on the hardware, or whether it's ALSA softvol, or whether it's the internal SW volume control. It applies a piecewise linear transfer function from the AirPlay volume to the logarithmic volume control device, and the curves you both plotted show this. The idea is to speed up changes in volume at low levels but to slow down volume control at high volume levels, similar to what is described in the documents linked in the README. I chose to use logarithmic mixer controls because one can't be sure whether the regular (non-logarithmic) controls are linear, logarithmic or something else. But you know where you stand with logarithmic controls.

Regarding the range of the built-in SW mixer, here is my line of reasoning: if you attenuate a signal by multiplying it in a mixer by a 16-bit unsigned integer value that ranges 1 to 65536, then if 0x10000 (65,536) is 0 dB then 0x0001 (1) is -96.32 dB, and that’s how the built-in SW volume control is calibrated. Is that how ALSA softvol is done Jürg-Krause? From the graph, it’s not quite clear — it looks like 128 values but the Y values seem to go to 256, at a guess. From the code it looks like -51.0 to 50 dB are limits of some kind, but that’s not me analysing at how the code works, I'm just looking at some of the constant definitions.

One thing I could try is to add a configuration file setting to use a flat AirPlay volume to dB transfer curve.

@joerg-krause
Copy link

The softvol plugin uses a resolution of 256 (Y-axes). The dB limit is -51 min and 0 max. There was a discussion on the ALSA mailing list to allow a min of -96 dB.

@mikebrady
Copy link
Owner

Thanks. As a matter of interest, do you happen to know the line of reasoning that came up with that? In my experience, a range of less than about 60 dB means you can’t get a suitably quiet low and a suitably loud high at the same amp setting in a domestic environment. I’ve kind of settled on about 70 dB as optimum — you can get a really quiet (but not completely inaudible) low and a good loud high.

@joerg-krause
Copy link

@mikebrady Let me cite: 'There is no more reason than "some reasonable limit"'. You can follow the discussion here.

@tuomashamalainen Do you here any difference between the built-in software volume control and the ALSA softvol plugin? When I look at my graph from the original thread I would say that the curve is just the same as yours showing the built-in volume, right?

@mikebrady
Copy link
Owner

Thanks for the information.

@tuomashamalainen
Copy link
Author

tuomashamalainen commented Jan 28, 2018

Thank you both so far, very insightful.

Do you here any difference between the built-in software volume control and the ALSA softvol plugin? When I look at my graph from the original thread I would say that the curve is just the same as yours showing the built-in volume, right?

There is a big difference in loudness at the same setting of the source volume slider (iOS or iTunes) between built-in software attenuator and ALSA softvol. To achieve about the same, comfortable listening level on my system:
screen shot 2018-01-28 at 23 49 07
With ALSA softvol, if I pretend that the source has no volume control and instead adjust volume via alsamixer directly, the mixer control's behaviour is much more in line with how the source volume control works with shairport-sync's built-in software attenuator.

This is what led me to believe that with ALSA softvol the system does this "human hearing compensation" twice – first in shairport-sync and then again in the softvol plugin. As said, shairport-sync's built-in software attenuator is essentially perfect to my ears, and ALSA softvol is also pretty good used on its own*. Alone both essentially "sound" more or less like the blue curve (what my ears "expect") in the original post, whereas together it's the green curve that I hear and find non-intuitive, if you catch my drift.

Having the option to map AirPlay volume linearly to the mixer controls would indeed in my opinion be a way to solve this – I guess the other is to hack the volume scale of softvol plugin to be "compatible" with shairport-sync, but that sounds much more difficult to me...

* Although I am seeing what @mikebrady mentioned about the dB range with ALSA softvol – it could go lower before it mutes. Modifying min_dB for pcm.softvol in ALSA configuration to be lower seems to help though, but I'm not entirely clear if this is a good thing to do in terms of sound quality...

@joerg-krause
Copy link

@tuomashamalainen Can you post your configuration file for both volume controls, please?

@tuomashamalainen
Copy link
Author

These are the same as linked to the original post. /etc/asound.conf looks like this. When configured for ALSA softvol, shairport-sync.conf looks like this. When used with the built-in attenuator, I change the alsa section to bypass softvol like this (otherwise identical):

alsa = {
    output_device = "plughw:0";
}

@joerg-krause
Copy link

Yes, I did the same and I am getting the same results:

image

I played a song with Spotify Connect and Shairport-Sync using both the ALSA softvol plugin and a step value of 16 for setting the volume.

As you can see Spotify curve is linear resulting in the mapped softvol graph shown above. This is the correct behaviour. The Shairport curve shows the volume as the built-in attenuator works. This leads to the cumulative effect you described. Which is not correct.

Looks like the volume control for the ALSA softvol plugin needs to be fixed...

@joerg-krause
Copy link

Mapping the amixer values from the curves above I get the following graph:

image

This shows that the cumulative effect decreases the logarithmic curve of the softvol plugin.

For reference: This are the values from amixer and the corresponding ALSA softvol value from the dB preset table:

Volume Step Amixer   ALSA softvol plugin dB preset value  
Index Spotify Shairport Spotify Shairport
0 0 0 0 0
1 15 36 254 413
2 31 73 368 969
3 47 106 532 2072
4 63 121 769 2927
5 79 135 1112 4040
6 95 149 1608 5577
7 111 164 2325 7879
8 127 178 3361 10876
9 143 192 4858 15013
10 159 207 7022 21206
11 175 215 10150 25496
12 191 223 14671 30653
13 207 231 21206 36853
14 223 239 30653 44307
15 239 247 44307 53268
16 255 255 64043 64043

@mikebrady
Copy link
Owner

mikebrady commented Jan 29, 2018

Thanks. Three things:

  1. I've pushed a development update which has a new volume_control_profile setting -- "standard" or "flat", so you can set a flat transfer function. Please look in the shairport-sync.conf.sample file that's installed when you do a # make install for information about it.

  2. I don't think the curves above tell the full story because they don't include information about the different attenuation ranges. IMHO a range of 51 dB isn't adequate, and I think this is the source of the problem, because the "human hearing compensation" is not being carried out twice, AFAIKS. In any case, you can experiment with a flat transfer function 😀.

  3. It's hard to follow the reasoning about limiting the range to 51 dB -- it seems arbitrary, and IMHO a decision about how much of it to use should be left to the application.

Finally, just for information, in Shairport Sync, the SW volume control multiplications are done in 32-bit integer form, then truncated and dithered to the output size. If you have 24- or 32-bit output available, then this can be done with a very low level of dither.

@tuomashamalainen
Copy link
Author

tuomashamalainen commented Jan 30, 2018

Thanks for taking the time @mikebrady, I'll give the new setting a try.

I don't think the curves above tell the full story because they don't include information about the different attenuation ranges. IMHO a range of 51 dB isn't adequate, and I think this is the source of the problem, because the "human hearing compensation" is not being carried out twice, AFAIKS. In any case, you can experiment with a flat transfer function 😀.

You may be right about this. Without changing anything else I lowered the min_dB in /etc/asound.conf for pcm.softvol even more...

 min_dB -90.2
 max_dB -6.2

...and the softvol scale is now much closer to shairport-sync's built-in attenuator – there's now sufficient resolution at lower volumes and the comfortable listening level is found closer to the middle of the source volume slider (of course I pulled that 90,2 out of my hat, maybe it can match even closer). Does this actually circumvent the 51 dB range limit of ALSA softvol or does the range extension take place somewhere else? What kind of implications does this have on sound quality?

@joerg-krause
Copy link

I've set the min_dB value to -70 dB for comparing with the default value of -51 dB:

image

It is true that with a larger dB range of 70 dB the shairport curve gets closer to the default softvol curve at 51 dB.

@mikebrady Thanks for the new flat transfer function which I will test tomorrow 😄

@joerg-krause
Copy link

I've just tested the flat volume control and it works as expected 😄 Good job!

@mikebrady
Copy link
Owner

Good stuff. I guess it's a feature that should be left in.

@joerg-krause
Copy link

Good stuff. I guess it's a feature that should be left in.

Absolutely! With it shairport-syncs volume control is the same as every other audio player using the ALSA softvol plugin. Too bad I didn't notice it before.

@mikebrady mikebrady changed the title Differences between shairport-sync's built-in SW volume and ALSA Softvol? Differences between shairport-sync's built-in SW volume and ALSA Softvol? [resolved] Feb 16, 2018
@shokoladas
Copy link

shokoladas commented Feb 23, 2018

Finally, just for information, in Shairport Sync, the SW volume control multiplications are done in 32-bit integer form, then truncated and dithered to the output size. If you have 24- or 32-bit output available, then this can be done with a very low level of dither.

Thanks for info,so now i can use SW without hardware mixer with good quality.
Maybe you guys have any idea why shairport-sync->loopback(alsa_in alsa_out)->jconvolver->hardware has lower max volume than Jriver->loopback(alsa_in alsa_out)->jconvolver->hardware . everything being equal except shairport and jriver. How can i debug?
need no say i use equal loudness correction for shairport-sync,but it should have no effect for 0.0dB output. audio output device is alsa default for both sources

@mikebrady
Copy link
Owner

I'm afraid that's outside my area of competence -- sorry. Maybe @joerg-krause can comment.

@joerg-krause
Copy link

Sorry, I'm completely out of my depth here.

@shokoladas
Copy link

Find out what was wrong. So stupid reason, but took a while to find out. I was streaming from TIDAL app which by default uses loudness normalization feature. So volume was different.

@mikebrady
Copy link
Owner

Thanks. Just for clarity, where does TIDAL come in to the picture? Are you saying that you were comparing streaming from TIDAL on a Mac/iOS device to Shairport Sync with playing from JRiver onto the same output device?

@shokoladas
Copy link

Yes.Correct.(my system is shairport or DLNA receiver to alsa dmix->loopback->alsa bridge->jack->some custom math->output) If i stream from iphone to shairport then volume depends on iphone's TIDAL app setting loudness normalization. But if i stream from iphone or android device TIDAL app but over third party app which streams over a DLNA.Than the volume does'n depent on TIDAL's loudness normalization setting. Thats no problem ,but was confusing to find out. Somehow streaming over third party apps discard info about tidal loudness settings.Just pure stream goes.

For some other reasons i have changed from avlinux to kxstudio and shairport-sync now works some seconds but stops and reports Segmentation fault. After reading some posts i am not sure if the reason is known? Is it non solved question?

@mikebrady
Copy link
Owner

Thanks for the clarification. TBH I have never used either AV Linux or KX Studio, so I can't really help there. However, the sequence Shairport Sync > ALSA dmix > loopback > ALSA bridge > jack > more stuff > output is pretty dizzying, and I would say, fragile and extremely hard to debug!

@shokoladas
Copy link

I agree it is pain in the ass such setup, it is just for development process for using plugins LADSPA and so in carla host.
I have kind of a feature request for shairport-sync. Should i start a new issue better?

@mikebrady
Copy link
Owner

Sure, but no promises!

@rsm123
Copy link

rsm123 commented May 1, 2021

Thanks for the flat/standard volume control options. When I use external amplifier in my car with i2s DAC, any single click change in volume on iphone makes a drastic dB level change. Is there a way to reduce the level of change in gain either with flat or standard volume setting?

@mikebrady
Copy link
Owner

Thanks for the post. I'm afraid there isn't anything that can be done directly to alter the change in gain for each click.

However, in a car setting -- which is potentially quite noisy -- it could be that the range of attenuation offered by the mixer is too great. This would lead to a situation where, for much of the travel of the volume-control slider (and correspondingly the clicks to change volume), the change in volume is inaudible, leaving the "useful" part of the volume adjustment confined to the upper end of the slider.

If that is so, consider using the volume_range_db setting to reduce the dynamic range of the volume control to, say, 60 dB, or maybe a little less. This would result in the "useful" part of the volume adjustment taking up a greater proportion of the slider's travel.

@github-actions
Copy link

This issue has been inactive for 60 days so will be closed 7 days from now. To prevent this, please remove the "stale" label or post a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants