Replies: 1 comment
-
Something like this could work: --- a/scanner/metadata/metadata.go
+++ b/scanner/metadata/metadata.go
@@ -173,10 +173,16 @@ func (t Tags) MbzAlbumComment() string {
}
// ReplayGain Properties
+type GainType int
-func (t Tags) RGAlbumGain() float64 { return t.getGainValue("replaygain_album_gain") }
+const (
+ AlbumGain = iota
+ TrackGain
+)
+
+func (t Tags) RGAlbumGain() float64 { return t.getGainValue(AlbumGain) }
func (t Tags) RGAlbumPeak() float64 { return t.getPeakValue("replaygain_album_peak") }
-func (t Tags) RGTrackGain() float64 { return t.getGainValue("replaygain_track_gain") }
+func (t Tags) RGTrackGain() float64 { return t.getGainValue(TrackGain) }
func (t Tags) RGTrackPeak() float64 { return t.getPeakValue("replaygain_track_peak") }
// File properties
@@ -238,18 +244,41 @@ func (t Tags) Lyrics() string {
return string(res)
}
-func (t Tags) getGainValue(tagName string) float64 {
- // Gain is in the form [-]a.bb dB
- var tag = t.getFirstTagValue(tagName)
- if tag == "" {
- return 0
+func (t Tags) getGainValue(gainType GainType) float64 {
+ var rgTagName string
+ var r128TagName string
+ if gainType == AlbumGain {
+ rgTagName = "replaygain_album_gain"
+ r128TagName = "r128_album_gain"
+ } else {
+ rgTagName = "replaygain_track_gain"
+ r128TagName = "r128_track_gain"
}
- tag = strings.TrimSpace(strings.Replace(tag, "dB", "", 1))
- var value, err = strconv.ParseFloat(tag, 64)
- if err != nil || value == math.Inf(-1) || value == math.Inf(1) {
- return 0
+
+ // ReplayGain is in the form [-]a.bb dB
+ var tag = t.getFirstTagValue(rgTagName)
+ if tag != "" {
+ tag = strings.TrimSpace(strings.Replace(tag, "dB", "", 1))
+ var value, err = strconv.ParseFloat(tag, 64)
+ if err != nil || value == math.Inf(-1) || value == math.Inf(1) {
+ return 0
+ }
+ return value
}
- return value
+
+ // R128 gain is a Q7.8 fixed point number normalized to -23dB
+ tag = t.getFirstTagValue(r128TagName)
+ if tag != "" {
+ var iValue, err = strconv.Atoi(tag)
+ if err != nil {
+ return 0
+ }
+ // Convert Q7.8 to float
+ var value = float64(iValue) / 256.0
+ // Adding 5 dB to normalize with ReplayGain level
+ return value + 5
+ }
+
+ return 0
}
func (t Tags) getPeakValue(tagName string) float64 { |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Per https://datatracker.ietf.org/doc/html/rfc7845#section-5.2.1, opus files are not supposed to use REPLAYGAIN_ style tags, and are instead expected to use corresponding R128_*_GAIN tags for volume normalization. The tags indicate a gain using the EBU R128 standard, with a target loudness of -23dB. In comparison, ReplayGain2 targets -18dB. Because of this, several players I use (e.g. Foobar2000, PowerAmp), will use the R128_*_GAIN values for replaygain, and automatically add +5dB to keep the normalization consistent with replaygain.
In the interest of following the RFCs, my music collection has a number of opus files, which I have normalized with R128 tags. Unfortunately, navidrome doesn't currently read these tags, so my opus files don't end up with any gains applied, causing volume mismatch. There are ways around this with opus output_gain, but I think it would be nice if navidrome could read the R128 values like REPLAYGAIN tags, and apply the +5dB to them.
Beta Was this translation helpful? Give feedback.
All reactions