From 4b2f8815b50b97ca909148dfbee87bc4c928ec9f Mon Sep 17 00:00:00 2001
From: Tino Keitel <tino.keitel@gmx.de>
Date: Sat, 14 Mar 2009 21:05:38 -0400
Subject: [PATCH 1/2] Prefer Audiophile (Album) over Radio (Track) gain

Also adjust the ordering of the tags checked.  We now check the APE tag
first, because if a user has set it they likely would want to use that
value instead of the one added automatically by Lame at encode time.
Thanks to Tino Keitel for the patch.

This also resets the GainData struct in mp3_get_track_ape_replaygain(),
so that we don't end up using some mix of data from the LAME Tag and the
APE tag for ReplayGain.
---
 ChangeLog     |   12 +++++++++
 src/mp3file.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9c750c6..efa5d06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,18 @@
 2009-03-17  Todd Zullinger  <tmzullinger at users.sourceforge.net>
 
 	* src/mp3file.c:
+	  Prefer Audiophile (Album) over Radio (Track) gain.
+
+	  Adjust the ordering of the tags checked.  We now check the APE
+	  tag first, because if a user has set it they likely would want
+	  to use that value instead of the one added automatically by
+	  Lame at encode time.  Thanks to Tino Keitel for the patch.
+
+	  Also resets GainData struct in mp3_get_track_ape_replaygain(),
+	  so that we don't end up using some mix of data from the LAME
+	  Tag and the APE tag for ReplayGain.
+
+	* src/mp3file.c:
 	  Use LOCALDEBUG in mp3_get_track_*_replaygain().
 
 	  This replaces commented out debug code, making it easier to
diff --git a/src/mp3file.c b/src/mp3file.c
index 1285917..7e8599b 100644
--- a/src/mp3file.c
+++ b/src/mp3file.c
@@ -2089,7 +2089,6 @@ rg_fail:
  *
  * Read the specified file and scan for Ape Tag ReplayGain information.
  *
- * The function only modifies the gains if they have not previously been set.
  */
 gboolean mp3_get_track_ape_replaygain(const gchar *path, GainData *gd)
 {
@@ -2117,6 +2116,13 @@ gboolean mp3_get_track_ape_replaygain(const gchar *path, GainData *gd)
 	g_return_val_if_fail (gd, FALSE);
 	g_return_val_if_fail (path, FALSE);
 
+	gd->radio_gain = 0;
+	gd->audiophile_gain = 0;
+	gd->peak_signal = 0;
+	gd->radio_gain_set = FALSE;
+	gd->audiophile_gain_set = FALSE;
+	gd->peak_signal_set = FALSE;
+
 	file = fopen (path, "r");
 
 	if (!file)
@@ -2181,9 +2187,9 @@ gboolean mp3_get_track_ape_replaygain(const gchar *path, GainData *gd)
 		goto rg_fail;
 	if (fread(dbuf, 1, data_length, file) != data_length)
 		goto rg_fail;
-	
+
 	for (i = 0; i < entries; i++) {
-		if (gd->radio_gain_set && gd->peak_signal_set) break;
+		if (gd->radio_gain_set && gd->peak_signal_set && gd->audiophile_gain_set) break;
 		pos = pos2 + entry_length;
 		if (pos > data_length - 10) break;
 
@@ -2197,6 +2203,45 @@ gboolean mp3_get_track_ape_replaygain(const gchar *path, GainData *gd)
 
 		if (entry_length + 1 > sizeof(buf))
 			continue;
+
+		/* album gain */
+		if (!gd->audiophile_gain_set && !strcasecmp(&dbuf[pos],
+					"REPLAYGAIN_ALBUM_GAIN")) {
+			memcpy(buf, &dbuf[pos2], entry_length);
+			buf[entry_length] = '\0';
+
+			d = g_ascii_strtod(buf, &ep);
+			if ((ep == buf + entry_length - 3)
+					&& (!strncasecmp(ep, " dB", 3))) {
+			    gd->audiophile_gain = d;
+				gd->audiophile_gain_set = TRUE;
+#if LOCALDEBUG
+				printf("album gain (ape): %f\n", gd->audiophile_gain);
+#endif
+			}
+
+			continue;
+		}
+		if (!gd->peak_signal_set && !strcasecmp(&dbuf[pos],
+					"REPLAYGAIN_ALBUM_PEAK")) {
+			memcpy(buf, &dbuf[pos2], entry_length);
+			buf[entry_length] = '\0';
+
+			d = g_ascii_strtod(buf, &ep);
+			if (ep == buf + entry_length) {
+				d *= 0x800000;
+				gd->peak_signal = (guint32) floor(d + 0.5);
+				gd->peak_signal_set = TRUE;
+#if LOCALDEBUG
+				printf("album peak signal (ape): %f\n",
+					(double)gd->peak_signal / 0x800000);
+#endif
+			}
+
+			continue;
+		}
+
+		/* track gain */
 		if (!gd->radio_gain_set && !strcasecmp(&dbuf[pos],
 					"REPLAYGAIN_TRACK_GAIN")) {
 			memcpy(buf, &dbuf[pos2], entry_length);
@@ -2286,22 +2331,39 @@ gboolean mp3_read_soundcheck (const gchar *path, Track *track)
     gd.audiophile_gain_set = FALSE;
     gd.peak_signal_set = FALSE;
 
-    mp3_get_track_lame_replaygain (path, &gd);
+    mp3_get_track_ape_replaygain (path, &gd);
+    if (gd.audiophile_gain_set)
+    {
+	track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain);
+#if LOCALDEBUG
+	printf("using ape album gain\n");
+#endif
+	return TRUE;
+    }
     if (gd.radio_gain_set)
     {
 	track->soundcheck = replaygain_to_soundcheck (gd.radio_gain);
 #if LOCALDEBUG
-	printf("using lame radio gain\n");
+	printf("using ape radio gain\n");
 #endif
 	return TRUE;
     }
 
-    mp3_get_track_ape_replaygain (path, &gd);
+    mp3_get_track_lame_replaygain (path, &gd);
+    if (gd.audiophile_gain_set)
+    {
+	track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain);
+#if LOCALDEBUG
+        /* This is highly unlikely, lame does not write audiofile gain. */
+	printf("using lame album gain\n");
+#endif
+	return TRUE;
+    }
     if (gd.radio_gain_set)
     {
 	track->soundcheck = replaygain_to_soundcheck (gd.radio_gain);
 #if LOCALDEBUG
-	printf("using ape radio gain\n");
+	printf("using lame radio gain\n");
 #endif
 	return TRUE;
     }
-- 
1.6.2

