Open Bug 1746799 Opened 3 years ago Updated 28 days ago

Linux/pulseaudio media volume does not map well

Categories

(Core :: Audio/Video: cubeb, enhancement)

Firefox 95
x86_64
Linux
enhancement

Tracking

()

UNCONFIRMED

People

(Reporter: a.mcguinness, Unassigned)

References

Details

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0

Steps to reproduce:

Turn the volume control in a video player down to the minimum without being zero (youtube, but other video players have same issue)

the volume property of the video element, observed from the developer console, is 0.007. I cannot make it smaller without being zero (and muted) using the slider control in the UI.

temp1
<video class="video-stream html5-main-video" tabindex="-1" controlslist="nodownload" style="width: 1172px; height: 659px; left: 0px; top: 0px;" src="blob:https://www.youtube…9-454e-984c-4c50f3ff5ca6">

temp1.volume
0.007083511352539063

Actual results:

The volume of the channel as observed with "pactl list" is 19%

Sink Input #569
Driver: protocol-native.c
Owner Module: 10
Client: 84
Sink: 0
Sample Specification: float32le 2ch 44100Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = ""float32le"" format.rate = "4410
0" format.channels = "2" format.channel_map = ""front-left,front-right""
Corked: no
Mute: no
Volume: front-left: 12586 / 19% / -43.00 dB, front-right: 12586 / 19
% / -43.00 dB
balance 0.00
Buffer Latency: 120272 usec
Sink Latency: 15119 usec
Resample method: copy
Properties:
media.name = "lofi hip hop radio - beats to relax/study to - YouTube"
application.name = "Firefox"
native-protocol.peer = "UNIX socket client"
native-protocol.version = "34"
application.process.id = "146101"
application.process.user = "andrew"
application.process.binary = "firefox-bin"
application.language = "en_GB.UTF-8"
window.x11.display = ":0"
module-stream-restore.id = "sink-input-by-application-name:Firefox"

It is possible to get the volume down to 10%, by setting [videoElement].volume to about 0.002 from the developer console. However it is not possible to set it this precisely from the slider in the player UI.

Expected results:

The volume of the channel should have been as low as 10% or lower. It seems the mapping from the HTMLMediaElement.volume setting to the pulseaudio is a bit off.

The volume control is working as per spec - lower volume sounds quieter, higher volume sounds louder. It is just the shape of the curve that is the problem, making it difficult to set the sound to a very low volume.

If it helps, sound hardware is intel embedded

00:1f.3 Audio device: Intel Corporation Cannon Lake PCH cAVS (rev 10)

pactl info

Server String: /run/user/1001/pulse/native
Library Protocol Version: 34
Server Protocol Version: 34
Is Local: yes
Client Index: 91
Tile Size: 65472
User Name: andrew
Server Name: pulseaudio
Server Version: 14.2
Default Sample Specification: s16le 2ch 44100Hz
Default Channel Map: front-left,front-right
Default Sink: alsa_output.pci-0000_00_1f.3.analog-stereo
Default Source: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor

The Bugbug bot thinks this bug should belong to the 'Core::Audio/Video: Playback' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.

Component: Untriaged → Audio/Video: Playback
Product: Firefox → Core

Done some more digging, so I can clarify:

The slider in the PulseAudio volume control "pavucontrol" is smooth - it goes from 0% to 150%, and subjectively the volume increases evenly as you slide it up.

For reference, 10% on the slider says (-58.98dB), 25% says (-36.52dB), 50% says (-18.01dB)

The volume slider on youtube or other video players sets the HTMLMediaElement.volume property evenly from 0.0 to 1.0

However, the pavu slider position corresponds to the cube root of the HTMLMediaElement.volume

i.e. el.volume = 0.1 sets pavu volume to 22% , el.volume = 0.2 sets pavu volume to 58%

The code that's doing this mapping is almost certainly this:
https://searchfox.org/mozilla-central/source/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c#1176

Either doing this conversion is just wrong, or there's something screwy in my software or hardware that's making it undesirable.

Component: Audio/Video: Playback → Audio/Video: cubeb
OS: Unspecified → Linux
Hardware: Unspecified → x86_64

I've confirmed that cubing the volume float before calling sw_volume_from_linear has the correct behaviour for me -- i.e. the volume slider in the video player behaves like the volume slider in pavucontrol

https://searchfox.org/mozilla-central/source/third_party/rust/cubeb-pulse/src/backend/stream.rs#760

This looks stupid and doesn't exactly make sense - the code as it stands is doing what the pulseaudio docs say it should do https://freedesktop.org/software/pulseaudio/doxygen/volume.html

At a guess what I'm doing is equivalent to skipping sw_volume_from_linear and converting the float to a uint32 by multiplying by PA_VOLUME_NORM, (or maybe PA_VOLUME_MAX) but I don't know enough rust to do that.

diff --git a/third_party/rust/cubeb-pulse/src/backend/stream.rs b/third_party/rust/cubeb-pulse/src/backend/stream.rs
--- a/third_party/rust/cubeb-pulse/src/backend/stream.rs
+++ b/third_party/rust/cubeb-pulse/src/backend/stream.rs
@@ -757,7 +757,7 @@ impl<'ctx> StreamOps for PulseStream<'ct
                         self.volume = volume;
                     } else {
                         let channels = stm.get_sample_spec().channels;
-                        let vol = pulse::sw_volume_from_linear(f64::from(volume));
+                        let vol = pulse::sw_volume_from_linear(f64::from(volume*volume*volume));
                         cvol.set(u32::from(channels), vol);
 
                         let index = stm.get_index();

Raised a pull request against cubeb-pulse-rs
https://github.com/mozilla/cubeb-pulse-rs/issues/74

See Also: → 1422637, 1343681
See Also: → 1049480
You need to log in before you can comment on or make changes to this bug.