Description
I'm on 0.9.14. Currently, if I place tracks with gapless playback in playlist with hybrid replaygain, there may be sudden jump of volume on next track, and due to tracks being "unite" it is easily seen.
Current behavior
Hybrid ReplayGain uses track gain even if both tracks are from the same album and list [previousTrack, nextTrack] is a sublist of all tracks in their album.
Expected behavior
Hybrid ReplayGain uses album gain in such cases, preventing volume jump on gapless albums.
Proposed solution
The most optimal solution is to find "sequental tracks" in queue and use album gain in those ranges, using this algorithm:
I wrote that for other project so that it is python, anyway I want to show the algorithm
for playlist in playlists:
sequental_ranges = []
i = 0
while i < len(playlist["tracks"]):
start = i
# Find the end of the current sequential range
while (
(i + 1) < len(playlist["tracks"])
and playlist["tracks"][i + 1]["album_uri"] == playlist["tracks"][i]["album_uri"] # same album
and ( # same disk
(playlist["tracks"][i]["disc_number"] == playlist["tracks"][i + 1]["disc_number"] and
playlist["tracks"][i]["track_number"] + 1 == playlist["tracks"][i + 1]["track_number"])
or # next disk
(playlist["tracks"][i]["disc_number"] + 1 == playlist["tracks"][i + 1]["disc_number"] and
playlist["tracks"][i + 1]["track_number"] == 1)
)
):
i += 1
end = i
# Add the range to the list if it contains at least two tracks
if end > start:
sequental_ranges.append(range(start, end + 1))
i += 1
playlist["sequental_ranges"] = sequental_ranges
"sequental_ranges" then contains every range where you need to use album gain
There's also other solution, I think it is the one Spotify uses. It involves adding fourth option to volume normalization - "always use album gain". Looking at source code, I see that you already considered that:
finamp/lib/services/music_player_background_task.dart
Lines 897 to 919 in 1f3e37b
If it really needs AlbumItem here for this option to work and there's no easy way to get it (or pass contextNormalizationGain
) here, then I probably can't make a PR myself, as I am not familiar with Dart and this project enough. Otherwise, I'm willing to make a PR with fourth option if noone takes either approach.
Activity