Fix OpenSubsonic ReplayGain loudness calculation (#2893)
authorOzGav <gavnosp@hotmail.com>
Sun, 28 Dec 2025 08:27:25 +0000 (16:27 +0800)
committerGitHub <noreply@github.com>
Sun, 28 Dec 2025 08:27:25 +0000 (09:27 +0100)
* Fix OpenSubsonic ReplayGain loudness calculation

The OpenSubsonic provider was passing raw ReplayGain gain values
(in dB) directly to set_loudness(), but set_loudness() expects
integrated loudness values (in LUFS).

This caused tracks with ReplayGain tags to show incorrect loudness
values when accessed via OpenSubsonic/Navidrome. For example, a
quiet track with +0.39 dB gain was being stored as 0.39 LUFS
instead of -18.39 LUFS, resulting in massive gain reduction
(-17.39 dB) instead of a small boost.

Fixed by converting ReplayGain values to loudness before storing:
  Loudness (LUFS) = -18 - Gain (dB)

This matches the ReplayGain 2.0 specification and how the
filesystem provider handles ReplayGain tags.

Only affects users connecting to Navidrome/Subsonic servers.
Users with local filesystem music were not affected.

* Remove unnecessary comment

---------

Co-authored-by: Claude <noreply@anthropic.com>
music_assistant/providers/opensubsonic/sonic_provider.py

index 2fd6fe946aa272c6001cdd93869e62a3942b6b1e..bf967e48f074996aaab04cb9620892558d36c78d 100644 (file)
@@ -180,13 +180,20 @@ class OpenSonicProvider(MusicProvider):
         return await asyncio.to_thread(call, *args, **kwargs)
 
     def _set_loudness(self, item: SonicItem) -> None:
-        if item.replay_gain and item.replay_gain.track_gain:
+        if item.replay_gain and item.replay_gain.track_gain is not None:
+            # Convert ReplayGain values (gain in dB) to integrated loudness (LUFS)
+            track_loudness = -18 - item.replay_gain.track_gain
+            album_loudness = (
+                -18 - item.replay_gain.album_gain
+                if item.replay_gain.album_gain is not None
+                else None
+            )
             self.mass.create_task(
                 self.mass.music.set_loudness(
                     item.id,
                     self.instance_id,
-                    item.replay_gain.track_gain,
-                    item.replay_gain.album_gain,
+                    track_loudness,
+                    album_loudness,
                 )
             )