mikebrady / shairport-sync

AirPlay and AirPlay 2 audio player
Other
7.3k stars 574 forks source link

Changing the volume range in dB #1337

Closed kiwi-ed closed 3 years ago

kiwi-ed commented 3 years ago

Hi Mike,

I'm using SPS 3.3.8 and I'm trying to match the volume range of SPS to that of MPD (0 dB <-> -40 dB). From what I can figure from the conf docs it should be:

   volume_range_db = 40.0 ;
   volume_max_db = 0.0;
   volume_control_profile = "flat"; // optional?

However I still get the default being 0 dB <-> -27 dB (from debug)

What do you think I'm missing? (Let's not discuss the rugby...)

Thanks!

Ed.

mikebrady commented 3 years ago

[Updated -- I re-read your message!]

The settings you have given are correct, but can you say where you are picking up the 0 to -27 dB range?

Regarding the rugby (just a few km from here, BTW), let's just say we were all pretty happy. OTOH you win on Prime Ministers.

kiwi-ed commented 3 years ago

Hi,

Alsamixer gives me 0 dB <-> -127 dB. SPS actually bottoms out as -28 after a recheck. How is the volume derived? Does the (in my case ) iPad send a 0-100 scale dependent on the physical volume buttons or slider then that's converted to suit the range with ALSA's mixer / DAC? Or is the value 0 <-> -127 sent from the iPad?

I don't actually use mixers really as most of the applications on board use hw: PCM's not plughw: for higher rates.

In general, does SPS look at something within ALSA to get the volume constraints?

Thanks.

mikebrady commented 3 years ago

Thanks.

AirPlay sources like the iPad/iOS/macOS send a volume level of from 0.00 down to -30.00 with -144 signifying a mute. This is mapped on to a mixer by Shairport Sync. If you don't specify the name of a mixer using the mixer_control_name, an internal software mixer is used which has a range of 0 dB down to approximately -96 dB.

A consequence of not specifying a mixer name (obviously enough) is that no external mixers are controlled by Shairport Sync. Thus, whatever levels any mixers happen to have due to other uses and other programs will be unaffected by Shairport Sync.

So if your device actually has a mixer with a range of 0 down to -127 dB but you do not name it in the mixer_control_name setting in Shairport Sync, its level will be unaffected by the Shairport Sync volume. And also, the volume range of 40 dB you specified will be applied to the software mixer. Instead of a range of 0 to -96, it would have a range of 0 to -40.

Earlier I was wondering where you saw the values 0 to -28. Could you say and maybe post some?

Also, I don't understand it when you write:

most of the applications on board use hw: PCM's not plughw: for higher rates.

In fact, many hardware devices ("hw: PCM's") do have mixers attached to them.

kiwi-ed commented 3 years ago

Hi

Appreciate the update. Just to clarify the volume itself has always worked well, it's just the inability to change the range. The volume value on change in my case is picked up via a monitor application that uses the DBus PropertiesChanged callback. Once the call back is triggered I look for the AirplayVolume value. Below is some DBus debug:

PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <0.0>})
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-1.875>})
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-3.75>})
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-5.6145248413085938>})
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-6.7877092361450195>})
Toward lowest volume
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-22.5>})
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-24.375>})
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-26.25>}
PropertiesChanged: ('org.gnome.ShairportSync.RemoteControl', {'AirplayVolume': <-28.125>}   < == lowest / mute 

Interestingly my platform only provides two mixers when requested by amixer. There's no default or Master when comparing to other Linux boxes I have sitting around...

Simple mixer control 'Behringer',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 32767
  Mono:
  Front Left: Playback 32767 [100%] [0.00dB] [on]
  Front Right: Playback 32767 [100%] [0.00dB] [on]
Simple mixer control 'Behringer',1
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 32767
  Mono: Playback 32767 [100%] [0.00dB] [on]

The platform is running system-V Linux 4.1.32. Headless, no display nor keyboard. It's purely a device full of music service endpoints. It only has one USB DAC connected at any time but can be any old DAC.

Regarding "most of the applications on board use hw: PCM's not plughw: for higher rates." It's just for applications like MPD and Roon etc so the apps have full control over bit rate with no down-sampling. Until now I've never had to look under the hood about mixers so it's an area where I'm a little vague. It's also hard to find a definitive statement on where the mixers (amixer in my case) sit in the grand flow of ALSA PCM data. Two questions: If connected via the ALSA API do they effect PCMs with plugs (plughw: ) and non-plugs (hw:)? Am I correct to assume with the exception of the 'default' / 'Master' mixers, a mixer referenced by name only effects the PCM with the matching name? Side point, do mixers introduce any distortion that you know of?

Thanks again, appreciate your feedback!

mikebrady commented 3 years ago

Thanks for the comprehensive update! I'll take a careful look and report back.

mikebrady commented 3 years ago

Okay, so the D-Bus debug is reporting AirPlay volume -- that's the volume number that comes from the source, e.g. iOS or macOS. It ranges from 0.0 to -30.0. The values seem to scale linearly with the position of the volume slider. An extra value, -144.0, means mute.

As mentioned above, this is applied through a transfer function, which could be fancy or "flat", to the dB attenuation control of whatever mixer Shairport Sync is using. If you restrict the volume range to 40 dB (as you did), then the top 40 dB of the mixer's range are used. Thus, -30 (the minimum volume) on AirPlay volume would map to -40 on the mixer and 0 on AirPlay could map to 0 on the mixer's attenuator. D-Bus does not report the attenuation applied to the mixer, only the AirPlay volume. If you don't specify a mixer name to Shairport Sync, it will use its own software mixer.

Regarding your other two questions, I have always assumed that a mixer is attached to a DAC so that it [digitally] attenuates all audio signals that come through, wherever they come from, on their way to the DAC. That being so, it means that audio coming from plugins and so on must be affected, since it must pass through the mixer on the way out.

And, I've always assumed that mixers/attenuators are well implemented and don't introduce appreciable distortion -- i.e. I have always presumed that the hardware designers knew what they were doing. Thus I'd always recommend using them where possible.

The problem is, of course, if you're sharing a DAC with other programs, then whatever you do to the mixer will affect the other programs and vice versa.

The scope of operation of the mixers attached to audio hardware would obviously be dependent on the hardware itself. The "master" volume level may be implemented by Linux system itself -- I don't actually know about that; not a big desktop Linux user.

kiwi-ed commented 3 years ago

Thanks Mike! It's really good when one can get some decent, sensible and specific answers to questions - appreciated! The DBus value makes total sense now so I can work with that. As a test I wrote an asound pcm that included a sofvol mixer with the same name as the card. The new pcm was used in SPS and a new mixer (with the same name) popped up in amixer. Volume slider in amixer changed with SPS volume. So I think I'll stick with that for now.

Again, thanks!

Ed.

kiwi-ed commented 3 years ago

Just thinking about this, I'd still like to pick up the volume from DBus in my monitor app. So I'm thinking of hijacking the DBus value with the mixer value. Could you give me the two functions that 1) send the current DBus volume value to the DBus server 2) the point where the mixer modified value has been chosen.

One other point now I'm thinking about all this - when sending volumes back to SPS over DBus is the new range (mixer or in conf) used or is it still the iPad range?

Cheers,

Ed.

mikebrady commented 3 years ago

Hi Ed. I may have to disappoint you here, I'm afraid.

In summary, control over volume is always retained by the source -- the iOS/macOS/tvOS/homeOS app providing the audio. To change the volume on SPS, SPS effectively asks the source, via remote control, to change the volume and, if the source agrees, it passes the new volume to SPS.

  1. The D-Bus AirPlay volume is read only -- it's a property you can read but not set.
  2. If remote control of the source is working, you can use the D-Bus SetAirplayVolume command to ask the source to set the volume. The source will then send a new AirPlay volume back to Shairport Sync which will then map it to the mixer as normal.

The problem with this is that it remote control does not work on AirPlay 2. And even with AirPlay 1, some third party players do not respond to remote control requests, so do not provide the "RemoteControl" suite of facilities. Most players do not provide the "AdvancedRemoteControl" facilities.

kiwi-ed commented 3 years ago

Hi, understood. Might keep things as they are.. Thanks for all the help!

KR, Ed.