Ubuntu – Maintaining custom left/right audio balance (i.e. ratio) when changing volume level

pulseaudio

My headphones have aged and one of them (the left one) now plays sounds at a much lower volume than the other. So I adjusted the left-right balance, as suggested here, to (in my case) 80% on the left and 20% on the right. However, locking this balance does not do what I would expect it to do when changing the volume afterwards: Namely, increasing the volume by, say, 5% either through the pavucontrol GUI or through e.g. pactl -- set-sink-volume @DEFAULT_SINK@ +5% will add 5 percentage points to both sides, left and right, i.e. the left & right levels will be at 85% and 25% afterwards. Put differently, the ratio of 80%/20% = 4 is not being preserved and the audio will again sound disbalanced.

How can I change that and maintain the ratio of 4 at all times? Is there a corresponding setting somewhere deep down in PulseAudio or, maybe even better, is there a programmatic way (shell script) to achieve this? (I haven't been able to figure out how to retrieve – let alone adjust – the left/right volume levels individually.)

[EDIT]: As for setting different volume levels for the left and right channels, I just noticed that pactl allows passing multiple (space-separated) volume levels, one for each channel. Now, I just need to know how to retrieve the current volume level of each channel. As far as I can tell, pamixer --get-volume does not allow this (pamixer is this tool).

[EDIT 2]: Turns out pacmd list-sinks does list the volumes for all channels but, as seems typical for PulseAudio, in a way that's not exactly easy to parse. Is there no easier (future-proof) solution based on a reliable CLI?

Best Answer

You can increase or decrease the volume by dB which is a ratio, for example:

pactl -- set-sink-volume @DEFAULT_SINK@ +5dB

As far as I can see with

$ pactl list sinks | grep balance
        balance -0.50

the balance will remain constant while changing the volume by dB.

Here the relevant part of man pactl:

  set-sink-volume SINK VOLUME [VOLUME ...]
          Set  the volume of the specified sink (identified by its symbolic name or numerical
          index). VOLUME can be specified as an integer (e.g. 2000, 16384), a  linear  factor
          (e.g.  0.4,  1.100),  a  percentage  (e.g. 10%, 100%) or a decibel value (e.g. 0dB,
          20dB).
Related Question