mirror of
https://github.com/librespot-org/librespot.git
synced 2026-04-27 00:05:55 +03:00
[GH-ISSUE #1025] normalization: spotify no longer uses a limiter by default, so librespot probably shouldn't either #487
Labels
No labels
A-Alsa
SpotifyAPI
Tokio 1.0
audio
bug
can't reproduce
compilation
dependencies
duplicate
enhancement
good first issue
help wanted
high priority
imported
imported
invalid
new api
pull-request
question
reverse engineering
wiki
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/librespot#487
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @hkbakke on GitHub (Jul 24, 2022).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/1025
The default normalization method in librespot is "dynamic". However, spotify has made some changes to conform to the commonly used standards that other services uses, so they no longer uses a limiter for the default setting "normal" in spotify, so I think librespot shouldn't either. I don't know which LUFS level that librespot targets by default, but the default should now be -14 dB LUFS with no limiting.
https://artists.spotify.com/en/help/article/loudness-normalization
https://www.youtube.com/watch?v=449C4NSVPzw
@roderickvd commented on GitHub (Jul 24, 2022):
I am not a mastering engineer but I believe that this documentation by Spotify mixes up LUFS and dBFS.
When Spotify receives new music they calculate ReplayGain values targeting -14 LUFS, this is their baseline. These values are stored in a custom Ogg packet and we in fact retrieve those.
Then during playback (the normalization settings) Spotify does not recompute LUFS. It can only work in dB (FS). When choosing “Normal” levels they take the RG values as in the Ogg packet.
For “Loud” or “Quiet” it is just a matter of applying gain: +3/-9 according to that documentation. This is where the Spotify documentation gets it wrong. You cannot adjust sample values by X and expect the LUFS to change by the same X.
Adding to this I fact the documentation is outdated, as upon logon we receive configuration metadata which hints that the amount of gain is no longer as per the docs, and neither is the threshold.
All of this is currently in librespot, including those attack and release times.
Again I am not a mastering engineer, so if I’m wrong then do tell what we should change specifically and how.
@hkbakke commented on GitHub (Jul 24, 2022):
Basically, as far as I can see from the source code, it seems like "Basic" is now more inline with the spotify defaults, not "dynamic".
I don't really know the details of the source code of librespot, but a good implementation for fidelity adjust gains by the RG metadata, but if it is a very dynamic track that can't be increased by the amount in the RG tags without clipping, takes into concideration the max peak RG tag to ensure the maximum level of the track never clips when deciding the final gain setting. For very dynamic tracks this means that the volume target will not reach the target LUFS level, but the fidelity is fully preserved. This is, as far as I know, now the default behaviour for quiet and normal in official spotify clients. This is also how most services and fidelity oriented applications implements it.
I am not saying that librespot does not do this correctly in the "dynamic" case, but what I'm saying is that there is no need for a limiter at all as the default, as long as you take into concideration the max peak tags which I assume exists also for spotify streamed content.
Previously in the default spotify "normal" case, spotify would forcefully increase the track to the target level by limiting the peaks so the track could be increased by the amount indicated in the RG gain tag. This compromises fidelity and is no longer used unless "Loud" is chosen as the target. As far as I know spotify was the only streaming service that used limiting to force dynamic tracks up to the target levels so this change was very needed for the default setting.
@roderickvd commented on GitHub (Jul 24, 2022):
If this were the case with Spotify then why specify attack, release and thresholds at all? Such parameters only make sense for a limiter.
From the docs I do not read that the official clients now work like the basic limiter. I didn’t want to watch the full 40 minutes of the YT video you posted but any particular things I should watch?
Last time we worked on the limiter was not so long ago, and we did some extensive auditioning against the Spotify client then to ensure the sound was alike. Especially on classical tracks with huge dynamic range this would have been very noticeable — for basic normalization the tracks would then be extremely quiet and they were not. When do you say this would have changed?
@hkbakke commented on GitHub (Jul 24, 2022):
The limiter is still used for the "Loud" normalization target, so the parameters are still needed for some users. However, it could also be that Spotify is always running the limiter, but in contrast to other services that only uses the RG tags to decide on a volume target, spotify adapts the limiter parameters to make the limiter ineffective for the "normal" and "quiet" targets instead of entirely bypassing it. It seems convoluted when coming from other implementations, but makes some sense as the limiter is still in use for some users. I do not know how the limiter works and if this is a possible implemetation though.
However, doing a null operation via the more complex limiter makes me somewhat uncomfortable and I personally would feel better if the audio never touched the "magic" limiter at all if the end result is supposed to be the same :)
The changes was implemented in the first half of 2021 I think, so if you say that the current implementations has been tested against very dynamic tracks and the dynamics have been preserved in it's entirety without clipping or limiting, the current implementation is probably correct.
Also my official spotify client now has been updated with the following description: "Volume level - Adjust the volume for your environment. Loud may diminish audio quality. No effect on audio quality in Normal or Quiet".
I do not know the spotify internals, so this issue was mainly targeting the need to have a limiter on by default when it is not supposed to do any limiting except in the "Loud" case. If you have verified that it is not doing any limiting by default everything is OK and this issue may be closed. I will do some verification myself tomorrow and reopen the issue again if limiting is actually happening by default in librespot. I have verified that it does not in the official spotify client.
@hkbakke commented on GitHub (Jul 24, 2022):
I verified now. Everything good! Sorry for wasting your time! I was thrown off because I had volume differences between the official spotify client and librespot, when there should be none and then I saw that the limiter was on by default in the source.
After you confirmed that it should work as the original spotify client even in dynamic mode I started looking at other culprits and found that a technicality related to the volume control implementation when librespot was in use on my streaming platform (ropieee xl) was the cause.
To be more precise, --volume-ctrl fixed was used, but without --mixer softvol (or any other mixer) so the gain was not applied properly.
@roderickvd commented on GitHub (Jul 25, 2022):
That’s fine. Good to have it somewhat independently verified now 😄