music: fix opus replaygain interpretation

- Don't parse the base gain, the media player actually does apply it.
- Adjust R128 tags to LUFS -18 to be consistent w/MP3.

Resolves #521.
This commit is contained in:
Alexander Capehart 2024-02-20 11:10:20 -07:00
parent be1ee55b96
commit 07a98029c6
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 35 additions and 18 deletions

View file

@ -1,5 +1,11 @@
# Changelog
## dev
#### What's Fixed
- R128 adjustments are now adjusted to -18 LUFS to be consistent with MP3
- Fixed double application of opus base gain
## 3.4.0
#### What's New

View file

@ -99,22 +99,27 @@ private class TagWorkerImpl(
populateWithId3v2(textTags.id3v2)
populateWithVorbis(textTags.vorbis)
// If this metadata is of a vorbis file, we actually need to extract it's base gain
// and divide it by 256 to get the gain in decibels.
if (format.sampleMimeType == MimeTypes.AUDIO_OPUS &&
format.initializationData.isNotEmpty() &&
format.initializationData[0].size >= 18) {
val header = format.initializationData[0]
val gain = (((header[16]).toInt() and 0xFF) or ((header[17].toInt() shl 8))) / 256f
logD("Obtained opus base gain: $gain dB")
if (gain != 0f) {
logD("Applying opus base gain")
rawSong.replayGainTrackAdjustment =
(rawSong.replayGainTrackAdjustment ?: 0f) + gain
rawSong.replayGainAlbumAdjustment =
(rawSong.replayGainAlbumAdjustment ?: 0f) + gain
}
}
// OPUS base gain interpretation code: This is likely not needed, as the media player
// should be using the base gain already. Uncomment if that's not the case.
//if (format.sampleMimeType == MimeTypes.AUDIO_OPUS
// && format.initializationData.isNotEmpty()
// && format.initializationData[0].size >= 18) {
// val header = format.initializationData[0]
// val gain =
// (((header[16]).toInt() and 0xFF) or ((header[17].toInt() shl 8)))
// .R128ToLUFS18()
// logD("Obtained opus base gain: $gain dB")
// if (gain != 0f) {
// logD("Applying opus base gain")
// rawSong.replayGainTrackAdjustment =
// (rawSong.replayGainTrackAdjustment ?: 0f) + gain
// rawSong.replayGainAlbumAdjustment =
// (rawSong.replayGainAlbumAdjustment ?: 0f) + gain
// } else {
// logD("Ignoring opus base gain")
// }
//}
} else {
logD("No metadata could be extracted for ${rawSong.name}")
}
@ -317,14 +322,20 @@ private class TagWorkerImpl(
// the base adjustment intrinsic to the format to create the normalized adjustment. This is
// normally the only tag used for opus files, but some software still writes replay gain
// tags anyway.
(comments["r128_track_gain"]?.parseReplayGainAdjustment()?.div(256)
(comments["r128_track_gain"]?.parseR128Adjustment()
?: comments["replaygain_track_gain"]?.parseReplayGainAdjustment())
?.let { rawSong.replayGainTrackAdjustment = it }
(comments["r128_album_gain"]?.parseReplayGainAdjustment()?.div(256)
(comments["r128_album_gain"]?.parseR128Adjustment()
?: comments["replaygain_album_gain"]?.parseReplayGainAdjustment())
?.let { rawSong.replayGainAlbumAdjustment = it }
}
private fun List<String>.parseR128Adjustment() =
first().replace(REPLAYGAIN_ADJUSTMENT_FILTER_REGEX, "").toFloatOrNull()?.nonZeroOrNull()?.run {
// Convert to fixed-point and adjust to LUFS 18 to match the ReplayGain scale
this / 256f + 5
}
/**
* Parse a ReplayGain adjustment into a float value.
*