strawberrymusicplayer / strawberry

:strawberry: Strawberry Music Player
https://www.strawberrymusicplayer.org/
GNU General Public License v3.0
2.65k stars 182 forks source link

Loudness Nomalization seems to be clipping even when using F32 format #1320

Closed v-fox closed 7 months ago

v-fox commented 10 months ago

Describe the bug "EBU R 128 Loudness Nomalization" seems to produce muffled output when peeking with "unsafe" values such as "-6" regardless if output format allows non-clipped overload or not.

To Reproduce

As a result, if LN is "safely" below 0 but limiter boosted to peak sound is smooth but if reversed, LN peaks to 0 but limiter has no boost, sound seems distorted.

Expected behavior Output should be the same because with F32 clipping should always happen in limiter.

Screenshots: screenshot_strawberry Clipping during big cymbal smash in the song.

used EE profile: * `~/.config/easyeffects/output/anti-V.json` (EQ step is for [KZ PR2 planar headphones](https://www.head-fi.org/showcase/kz-x-hbb-pr2.26461/), disable it otherwise) ```json { "output": { "bass_enhancer#0": { "amount": 0.0, "blend": 0.0, "bypass": false, "floor": 30.0, "floor-active": true, "harmonics": 6.000000000000009, "input-gain": 0.0, "output-gain": 0.0, "scope": 115.0 }, "blocklist": [], "equalizer#0": { "balance": 0.0, "bypass": false, "input-gain": 0.0, "left": { "band0": { "frequency": 16.0, "gain": 0.0, "mode": "RLC (BT)", "mute": false, "q": 0.5, "slope": "x2", "solo": false, "type": "Hi-pass", "width": 4.0 }, "band1": { "frequency": 30.0, "gain": -9.000001907348633, "mode": "RLC (MT)", "mute": false, "q": 0.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band2": { "frequency": 100.0, "gain": -1.0000003576278687, "mode": "RLC (MT)", "mute": false, "q": 0.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band3": { "frequency": 3000.0, "gain": -8.0, "mode": "RLC (MT)", "mute": false, "q": 1.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band4": { "frequency": 6000.0, "gain": -2.000000238418579, "mode": "RLC (MT)", "mute": false, "q": 4.0, "slope": "x2", "solo": false, "type": "Bell", "width": 4.0 }, "band5": { "frequency": 12500.0, "gain": 4.000000476837158, "mode": "RLC (MT)", "mute": false, "q": 3.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band6": { "frequency": 16000.0, "gain": -5.999999523162842, "mode": "RLC (BT)", "mute": false, "q": 3.0, "slope": "x2", "solo": false, "type": "Bell", "width": 4.0 }, "band7": { "frequency": 22000.0, "gain": 0.0, "mode": "RLC (BT)", "mute": false, "q": 0.75, "slope": "x1", "solo": false, "type": "Off", "width": 4.0 } }, "mode": "IIR", "num-bands": 8, "output-gain": 0.0, "pitch-left": 0.0, "pitch-right": 0.0, "right": { "band0": { "frequency": 16.0, "gain": 0.0, "mode": "RLC (BT)", "mute": false, "q": 0.5, "slope": "x2", "solo": false, "type": "Hi-pass", "width": 4.0 }, "band1": { "frequency": 30.0, "gain": -9.000001907348633, "mode": "RLC (MT)", "mute": false, "q": 0.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band2": { "frequency": 100.0, "gain": -1.0000003576278687, "mode": "RLC (MT)", "mute": false, "q": 0.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band3": { "frequency": 3000.0, "gain": -8.0, "mode": "RLC (MT)", "mute": false, "q": 1.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band4": { "frequency": 6000.0, "gain": -2.000000238418579, "mode": "RLC (MT)", "mute": false, "q": 4.0, "slope": "x2", "solo": false, "type": "Bell", "width": 4.0 }, "band5": { "frequency": 12500.0, "gain": 4.000000476837158, "mode": "RLC (MT)", "mute": false, "q": 3.0, "slope": "x1", "solo": false, "type": "Bell", "width": 4.0 }, "band6": { "frequency": 16000.0, "gain": -5.999999523162842, "mode": "RLC (BT)", "mute": false, "q": 3.0, "slope": "x2", "solo": false, "type": "Bell", "width": 4.0 }, "band7": { "frequency": 22000.0, "gain": 0.0, "mode": "RLC (BT)", "mute": false, "q": 0.75, "slope": "x1", "solo": false, "type": "Off", "width": 4.0 } }, "split-channels": false }, "exciter#0": { "amount": 0.0, "blend": 0.0, "bypass": false, "ceil": 16000.0, "ceil-active": true, "harmonics": 3.0, "input-gain": 0.0, "output-gain": 0.0, "scope": 8870.0 }, "limiter#0": { "alr": true, "alr-attack": 4.0, "alr-knee": 3.0, "alr-release": 768.0, "attack": 8.0, "bypass": false, "dithering": "24bit", "external-sidechain": false, "gain-boost": true, "input-gain": 6.0, "lookahead": 8.0, "mode": "Herm Thin", "output-gain": 0.0, "oversampling": "Full x4(3L)", "release": 8.0, "sidechain-preamp": 0.0, "stereo-link": 100.0, "threshold": 0.0 }, "plugins_order": [ "stereo_tools#0", "bass_enhancer#0", "exciter#0", "equalizer#0", "limiter#0" ], "stereo_tools#0": { "balance-in": 0.0, "balance-out": 0.0, "bypass": false, "delay": 0.0, "input-gain": -3.0, "middle-level": 0.0, "middle-panorama": 0.0, "mode": "LR > LR (Stereo Default)", "mutel": false, "muter": false, "output-gain": 0.0, "phasel": false, "phaser": false, "sc-level": 1.0, "side-balance": 0.0, "side-level": 0.0, "softclip": false, "stereo-base": 0.0, "stereo-phase": 0.0 } } } ````

In this example the EE profile is set up to do "-3" at input stage and "+6" before input of the LSP limiter (that is the last pre-hardware stage, not counting PW's internal format conversions), LN in Strawberry is set to "-9". This seems stable but using "+3" in limiter and "-6" in Strawberry seems to clip on peaks. The hardware output of AK4490/LM4562|LME49{72,86}X-based DAC for planar headphones is set to "-12" or "-10" dB (they need more power than normal headphones, despite being mere ~16 Ohm).

System Information:

Additional context Loudness Normalization is an incredible feature. No matter how much I fiddled about with "Replay Gain", it never worked. But this one does handle badly normalized files (in both ways, too loud and too quiet). It would be perfect if not for perceived clipping.

However, I might have hallucinated the whole thing since there is no logs for clipping/xruns anywhere, other than peaking in EE. But with limiter is should be smooth even with crazy +50 dB overload.

jonaski commented 9 months ago

@LebedevRI Can you look into this?

LebedevRI commented 9 months ago

@v-fox are you able to reliably reproduce the issue?

LebedevRI commented 9 months ago

Also, can you please show a screenshot of Settings -> Backend? My only guess here is that somehow the strawberry's own gstreamer pipeline somehow ends up needing to convert from floating-point in the middle of the process...

v-fox commented 9 months ago

are you able to reliably reproduce the issue?

Yes, in fact, it's more aggressive than I thought. It triggers more often with less loud tracks, so I had to decrease target further to -16 dB (after initial -6 to -9 to -12) while increasing limiter's boost. It was really bad with a quiet piano track. Don't remember which one was it (maybe "Piano Collections NieR Gestalt & Replicant - Kainé" or "Hills of Radiant Wind") but it had a low "Integrated Loudness" of like -12 to -24.

Also, can you please show a screenshot of Settings -> Backend?

Sure but whole thing is not getting on screen. screenshot_str_b1 screenshot_str_b2

LebedevRI commented 9 months ago

Could you please try narrowing it a bit, namely, try disabling all of the:

Does it still reproduce with all of them disabled? (Do fully restart the strawberry after changing settings before trying to reproduce!)

If not, does it reproduce with one specific setting enabled? Or perhaps a combination of settings?

v-fox commented 9 months ago

Could you please try narrowing it a bit, namely, try disabling all of the:

I've set target to LN -6 and limiter to -4 (more like -1, considering -3 on input). The distortion became immediately apparent on "Kainé" piano track (IL=-15.85 LUFS and LR=10.67 LU; input spectrum smashes 0 dB in limiter). And you were right, disabling bs2b and just restarting playback made it stop sounding like as if headphone wires are about to fall off.

And I would have bet on fading effects instead, since they make slight "crunching" glitch under pipewire, at least when manually pausing. But this seems to be unrelated.

LebedevRI commented 9 months ago

Aha. I think this is working as intended: https://salsa.debian.org/debian/libbs2b/-/blob/2cd2edd45aa0736642c9b3181731ab0d1548de0a/src/bs2b.c#L504-508 Smart, i know, right?

I would certainly suggest that you ask the upstream to stop doing that.

LebedevRI commented 9 months ago

@jonaski i'm not really sure how this can be addressed on strawberry's side. gstreamer lists bs2b in "bad" category, and original upstream is dead.

(I could supply a patch to remove bs2b from strawberry, if that's what is preferred :) )

LebedevRI commented 9 months ago

@v-fox thank you for the report! This is indeed a very not-nice issue.

v-fox commented 9 months ago

@v-fox thank you for the report! This is indeed a very not-nice issue.

@LebedevRI Thanks for pointing me to the right direction. Could simply patching out the offending code do the trick or the whole logic for bs2b is hardcoded for integers?

jonaski commented 9 months ago

Thanks @LebedevRI I don't want to remove bs2b, I use it at work to play music through headphones. So there are two alternatives as far as I can see, either disable loudness normalization when bs2b is checked, or submit the patch fixing bs2b to upstream and different distros. If https://github.com/alexmarsev/libbs2b/commit/5ca2d59888df047f1e4b028e3a2fd5be8b5a7277 is the correct way of fixing it, I suggest we patch bs2b, I can submit the patch to Fedora and openSUSE and ask Arch and Debian if they can add it. The official repository is here: https://sourceforge.net/p/bs2b/code/HEAD/tree/trunk/libbs2b/ and the last time there was any real activity was in 2009, so not much chance a new version will be released.

LebedevRI commented 9 months ago

@v-fox thank you for the report! This is indeed a very not-nice issue.

@LebedevRI Thanks for pointing me to the right direction. Could simply patching out the offending code do the trick or the whole logic for bs2b is hardcoded for integers?

I think, simply patching out the offending code (i.e. clamping) is enough, and the actual processing is done on double's. That being said, theoretically such clamping might be required, but that is not likely.

Thanks @LebedevRI I don't want to remove bs2b, I use it at work to play music through headphones. So there are two alternatives as far as I can see, either disable loudness normalization when bs2b is checked, or submit the patch fixing bs2b to upstream and different distros.

Just to spell it out explicitly: the fact that Loudness Normalization can result in values > 1.0 (> +0 dB / > +0 dBFS) is NOT a bug, is very intentional, and the fact that there is no limiter / clamping after Loudness Normalization is NOT a bug. The whole pipeline should never internally limit.

If alexmarsev/libbs2b@5ca2d59 is the correct way of fixing it, I suggest we patch bs2b, I can submit the patch to Fedora and openSUSE and ask Arch and Debian if they can add it.

I think that could be the best way forward, but there's a lot of distros/packages of bs2b :)

The official repository is here: https://sourceforge.net/p/bs2b/code/HEAD/tree/trunk/libbs2b/ and the last time there was any real activity was in 2009, so not much chance a new version will be released.

Yup. It kind-of sounds like it's time for an official fork for the project.

diizzyy commented 9 months ago

fwiw, already submitted to FreeBSD https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=275403 This will likely be committed during the weekend due to maintainer timeout (port/package policies)

jonaski commented 7 months ago

openSUSE: https://build.opensuse.org/request/show/1142856 Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=2261991

jonaski commented 7 months ago

Submitting to Debian is a bit tedious, you have to do it through the mailing-list, so I'll leave that to someone else already in the Debian system. And I could not register an account in Arch, they have closed the registration because of spam, also better someone already in the Arch system does this. Patch is added to macOS and Windows builds.

LebedevRI commented 7 months ago

https://salsa.debian.org/debian/libbs2b/-/merge_requests/2

jonaski commented 7 months ago

Thanks @LebedevRI

hosiet commented 6 months ago

I merged the libbs2b changes in Debian. Note that I am not familiar with related audio libraries, and I count on you to ensure the patch correctness. If the patch on libbs2b would introduce side effects, please do let people know.

LebedevRI commented 6 months ago

@hosiet thank you! We are reasonably sure that the patch is correct, yes.