• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

Spotify and loudness normalization - how can normalizaed track have higher DR than non-normalized

danadam

Addicted to Fun and Learning
Joined
Jan 20, 2017
Messages
987
Likes
1,535
are the >0 dBFS peaks from playing music with normalization off now recoverable with Spotify’s volume control?
And actually, it might not be the spotify app that is doing the clamping.
After some investigation (pulseaudio 14.2), AFAICT they are both clamping samples to 1.0.

First, pulseaudio. The sample format in the sink-input (i.e., the stream that I am sending) is float32le. The sample format in the sink (i.e., DAC) is s32le. Because of that difference a resampler is created and added to the sink-input (see sink-input.c:463). It is a simple "copy" resampler, which means it doesn't change sampling rate but only converts samples from one format to another. You can see this in the logs:
Code:
D: [pulseaudio] sink-input.c: Negotiated format: pcm, format.sample_format = "\"float32le\""  format.rate = "44100"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
I: [pulseaudio] sink-input.c: Trying to change sample spec
D: [pulseaudio] sink.c: Suspending sink alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo due to changing format, desired format = float32le rate = 44100
I: [pulseaudio] alsa-sink.c: Sink does not support sample format of float32le, set it to a verified value

...

I: [pulseaudio] resampler.c: Forcing resampler 'copy', because of fixed, identical sample rates.
D: [pulseaudio] resampler.c: Resampler:
D: [pulseaudio] resampler.c:   rate 44100 -> 44100 (method copy)
D: [pulseaudio] resampler.c:   format float32le -> s32le (intermediate float32le)
D: [pulseaudio] resampler.c:   channels 2 -> 2 (resampling 2)
The problem is, that in the pulseaudio pipeline the resampler is normally run before the volume change. So the resampler clamps the samples during the conversion to s32le, before they have a chance to be attenuated. But there is one case when that processing order is reversed. This happens when the channel_maps of sink-input and sink differ (see sink-input.c:916). To test that, I generated two float32le WAV files with 30 sec of 220 Hz tone:
  • mono, with amplitude +9 dBFS
  • stereo, with amplitude +3 dBFS
Code:
ffmpeg -hide_banner -f lavfi -i "sine=frequency=220:duration=30,volume=27.06dB" -c pcm_f32le sin.mono.wav
ffmpeg -hide_banner -f lavfi -i "sine=frequency=220:duration=30,volume=24.06dB" -c pcm_f32le -ac 2 sin.stereo.wav
(they are in the attachment, so you can test it too)
The mono file, when re-mapped by pulseaudio to stereo, will also result in +3 dBFS in each channel. I played them using "paplay" command and I changed the volume using "pavucontrol". Reducing the volume while playing the stereo file did not help. Reducing the volume while playing the mono file stopped the clipping at the expected -3 dB.
party.png


I came up with a somewhat hacky idea to trigger this behavior even for stereo files. I added the "remap-sink" module with "right,left" channel map:
Code:
]$ MASTER_SINK="alsa_output.usb-RME_ADI-2_Pro__57760455__FC0F29710C736C8-00.analog-stereo"
]$ pacmd load-module module-remap-sink sink_name=Channels_Switcheroo sink_properties=device.description=Channels_Switcheroo \
master="${MASTER_SINK}" channels=2 remix=no format=float32le \
channel_map=front-right,front-left master_channel_map=front-right,front-left
Any "normal" stream (i.e. one with "left,right" mapping) sent to this sink will swap channels and by doing so it will apply volume change too. Then the stream from this sink to the master sink will swap channels again and it will do the sample format conversion. So now, when I choose "Channels_Switcheroo" for "paplay" in "pavucontrol", reducing the volume while playing the stereo file also stops the clipping.
party.png
party.png
party.png


And now to spotify. I did set "Channels_Switcheroo" for spotify too and reduced the volume but it did not help :(. The "Physical" captures with and without normalization still show the same clipping difference as before. That makes me think that they clamp the samples too, but I don't know if on purpose or by accident.
 

Attachments

  • sin.mono.wav.zip
    57.1 KB · Views: 61
  • sin.stereo.wav.zip
    104.6 KB · Views: 56

Feelas

Senior Member
Joined
Nov 20, 2020
Messages
390
Likes
316
Digging this old thread out, from today's reading I've figured out (didn't take long) that supposedly Spotify has stopped using limiter as of sometime in the mid 2021s, see Spotify for Artists "Loudness normalization" article - the only mention of limiter being used is now in the "Loud" (aka -11dB LUFS target) setting of the normalizer.
 
Top Bottom