Clipping with per-stream volume above 100% even though device volume below 100%
Submitted by Niklas Haas
Assigned to pul..@..op.org
Description
I am doing the following:
- Set my device volume to about 70% (approx. -10 dB gain)
- Play a sine wave at -0 dBFS using a simple test client:
λ import Sound.Pulse.Simple λ p <- simpleNew Nothing "pulse-simple" Play Nothing "testing" (SampleSpec (F32 LittleEndian) 48000 2) Nothing Nothing λ simpleWrite p [ 1.0 * sin (wx) | x <- [0..480005], let w = 0.01 :: Float ] λ ... λ simpleFree p
- Change the per-stream volume for this stream (“pulse-simple” in pavucontrol)
Any value below 100% is fine, but as soon as I go above 100% even by a little bit (e.g. 101%), I immediately hear obvious clipping artifacts.
- Set the per-stream volume to 100%, and change the amplitude of the sine wave produced instead (e.g. changing 1.0 to 1.1). I again hear obvious clipping artifacts (even though the signal format is floating point).
Why is this the case? Shouldn't the overall volume of 70% give me more than enough headroom to go above 100% on the per-stream volume? The only explanation I can come up with is that the conversion to integer happens before the device volume adjustment, e.g. perhaps if the device volume is being applied by ALSA instead of by PulseAudio (since it does seem that changes to the device volume are also visible in alsamixer).
If this is indeed the case and this is a limitation of the way device volumes are implemented, would it be possible to apply some sort of global “gain” setting to all sinks instead? I want to give them all 10 dB or so of mixing headroom so I can use software volume controls to go above 100% without clipping.
Obviously I can achieve this by setting up some sort of LADPSA filter or whatever in the signal path of every single stream, but that seems like a hassle to set up properly (especially since I'm using multiple audio devices). If it would be possible to just add a simple “mixing headroom” variable to daemon.conf that I can set to get headroom for free, I would be a very happy man.