aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Alexander Treuman <jat@spatialrift.net>2007-08-22 16:42:08 +0000
committerJ. Alexander Treuman <jat@spatialrift.net>2007-08-22 16:42:08 +0000
commitfe4b16ed96d24f5a33832fe906c1a7d2c0e59182 (patch)
treee375f82427e344fea8384914c9ae32e49e7ab32b
parent5e1deab05f71f64a881eb708025f16029e011c47 (diff)
downloadmpd-fe4b16ed96d24f5a33832fe906c1a7d2c0e59182.tar.gz
mpd-fe4b16ed96d24f5a33832fe906c1a7d2c0e59182.tar.xz
mpd-fe4b16ed96d24f5a33832fe906c1a7d2c0e59182.zip
inputPlugins/mp3_plugin: parse LAME tags for ReplayGain info
Parse ReplayGain info in LAME tags and use it if no ID3v2 ReplayGain tags are found. This is currently a bit unsafe, as apparently some LAME tags have bogus ReplayGain values. But I'm finding a lot of MP3s with valid LAME tags that fail the LAME tag CRC check. So until I figure out why that's happening, it's an unreliable method for checking if the LAME tag is valid. A big thanks to tmz for writing the original patch. git-svn-id: https://svn.musicpd.org/mpd/trunk@6798 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to '')
-rw-r--r--src/inputPlugins/mp3_plugin.c150
1 files changed, 104 insertions, 46 deletions
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index 3c958705a..43783070d 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -41,17 +41,17 @@
#include <unistd.h>
#include <errno.h>
-#define FRAMES_CUSHION 2000
+#define FRAMES_CUSHION 2000
-#define READ_BUFFER_SIZE 40960
+#define READ_BUFFER_SIZE 40960
-#define DECODE_SKIP -3
-#define DECODE_BREAK -2
-#define DECODE_CONT -1
-#define DECODE_OK 0
+#define DECODE_SKIP -3
+#define DECODE_BREAK -2
+#define DECODE_CONT -1
+#define DECODE_OK 0
-#define MUTEFRAME_SKIP 1
-#define MUTEFRAME_SEEK 2
+#define MUTEFRAME_SKIP 1
+#define MUTEFRAME_SEEK 2
/* the number of samples of silence the decoder inserts at start */
#define DECODERDELAY 529
@@ -498,16 +498,20 @@ enum {
XING_SCALE = 0x00000008L
};
+struct version {
+ int major;
+ int minor;
+};
+
struct lame {
- char encoder[10]; /* 9 byte encoder name/version ("LAME3.97b") */
-#if 0
- /* See related comment in parse_lame() */
- float peak; /* replaygain peak */
- float trackGain; /* replaygain track gain */
- float albumGain; /* replaygain album gain */
-#endif
- int encoderDelay; /* # of added samples at start of mp3 */
- int encoderPadding; /* # of added samples at end of mp3 */
+ char encoder[10]; /* 9 byte encoder name/version ("LAME3.97b") */
+ struct version version; /* struct containing just the version */
+ float peak; /* replaygain peak */
+ float trackGain; /* replaygain track gain */
+ float albumGain; /* replaygain album gain */
+ int encoderDelay; /* # of added samples at start of mp3 */
+ int encoderPadding; /* # of added samples at end of mp3 */
+ int crc; /* CRC of the first 190 bytes of this frame */
};
static int parse_xing(struct xing *xing, struct mad_bitptr *ptr, int *oldbitlen)
@@ -585,52 +589,94 @@ fail:
static int parse_lame(struct lame *lame, struct mad_bitptr *ptr, int *bitlen)
{
+ int adj = 0;
+ int name;
+ int orig;
+ int sign;
+ int gain;
int i;
/* Unlike the xing header, the lame tag has a fixed length. Fail if
* not all 36 bytes (288 bits) are there. */
- if (*bitlen < 288) return 0;
+ if (*bitlen < 288)
+ return 0;
- for (i = 0; i < 9; i++) lame->encoder[i] = (char)mad_bit_read(ptr, 8);
+ for (i = 0; i < 9; i++)
+ lame->encoder[i] = (char)mad_bit_read(ptr, 8);
lame->encoder[9] = '\0';
+ *bitlen -= 72;
+
/* This is technically incorrect, since the encoder might not be lame.
* But there's no other way to determine if this is a lame tag, and we
* wouldn't want to go reading a tag that's not there. */
- if (strncmp(lame->encoder, "LAME", 4) != 0) return 0;
+ if (strncmp(lame->encoder, "LAME", 4) != 0)
+ return 0;
-#if 0
- /* Apparently lame versions <3.97b1 do not calculate replaygain. I'm
- * using lame 3.97b2, and while it does calculate replaygain, it's
- * setting the values to 0. Using --replaygain-(fast|accurate) doesn't
- * make any difference. Leaving this code unused until we have a way
- * of testing it. -- jat */
+ if (sscanf(lame->encoder+4, "%u.%u",
+ &lame->version.major, &lame->version.minor) != 2)
+ return 0;
- mad_bit_read(ptr, 16);
+ DEBUG("detected LAME version %i.%i (\"%s\")\n",
+ lame->version.major, lame->version.minor, lame->encoder);
- mad_bit_read(ptr, 32); /* peak */
+ /* The reference volume was changed from the 83dB used in the
+ * ReplayGain spec to 89dB in lame 3.95.1. Bump the gain for older
+ * versions, since everyone else uses 89dB instead of 83dB.
+ * Unfortunately, lame didn't differentiate between 3.95 and 3.95.1, so
+ * it's impossible to make the proper adjustment for 3.95.
+ * Fortunately, 3.95 was only out for about a day before 3.95.1 was
+ * released. -- tmz */
+ if (lame->version.major < 3 ||
+ (lame->version.major == 3 && lame->version.minor < 95))
+ adj = 6;
- mad_bit_read(ptr, 6); /* header */
- bits = mad_bit_read(ptr, 1); /* sign bit */
- lame->trackGain = mad_bit_read(ptr, 9); /* gain*10 */
- lame->trackGain = (bits ? -lame->trackGain : lame->trackGain) / 10;
+ mad_bit_read(ptr, 16);
- mad_bit_read(ptr, 6); /* header */
- bits = mad_bit_read(ptr, 1); /* sign bit */
- lame->albumGain = mad_bit_read(ptr, 9); /* gain*10 */
- lame->albumGain = (bits ? -lame->albumGain : lame->albumGain) / 10;
+ lame->peak = mad_f_todouble(mad_bit_read(ptr, 32) << 5); /* peak */
+ DEBUG("LAME peak found: %f\n", lame->peak);
+
+ lame->trackGain = 0;
+ name = mad_bit_read(ptr, 3); /* gain name */
+ orig = mad_bit_read(ptr, 3); /* gain originator */
+ sign = mad_bit_read(ptr, 1); /* sign bit */
+ gain = mad_bit_read(ptr, 9); /* gain*10 */
+ if (gain && name == 1 && orig != 0) {
+ lame->trackGain = ((sign ? -gain : gain) / 10.0) + adj;
+ DEBUG("LAME track gain found: %f\n", lame->trackGain);
+ }
- mad_bit_read(ptr, 16);
+ /* tmz reports that this isn't currently written by any version of lame
+ * (as of 3.97). Since we have no way of testing it, don't use it.
+ * Wouldn't want to go blowing someone's ears just because we read it
+ * wrong. :P -- jat */
+ lame->albumGain = 0;
+#if 0
+ name = mad_bit_read(ptr, 3); /* gain name */
+ orig = mad_bit_read(ptr, 3); /* gain originator */
+ sign = mad_bit_read(ptr, 1); /* sign bit */
+ gain = mad_bit_read(ptr, 9); /* gain*10 */
+ if (gain && name == 2 && orig != 0) {
+ lame->albumGain = ((sign ? -gain : gain) / 10.0) + adj;
+ DEBUG("LAME album gain found: %f\n", lame->trackGain);
+ }
#else
- mad_bit_read(ptr, 96);
+ mad_bit_read(ptr, 16);
#endif
+ mad_bit_read(ptr, 16);
+
lame->encoderDelay = mad_bit_read(ptr, 12);
lame->encoderPadding = mad_bit_read(ptr, 12);
- mad_bit_read(ptr, 96);
+ DEBUG("encoder delay is %i, encoder padding is %i\n",
+ lame->encoderDelay, lame->encoderPadding);
- *bitlen -= 288;
+ mad_bit_read(ptr, 80);
+
+ lame->crc = mad_bit_read(ptr, 16);
+
+ *bitlen -= 216;
return 1;
}
@@ -694,18 +740,30 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
data->foundXing = 1;
data->muteFrame = MUTEFRAME_SKIP;
- if (gaplessPlaybackEnabled && data->inStream->seekable &&
- parse_lame(&lame, &ptr, &bitlen)) {
- data->dropSamplesAtStart = lame.encoderDelay + DECODERDELAY;
- data->dropSamplesAtEnd = lame.encoderPadding;
- }
-
if ((xing.flags & XING_FRAMES) && xing.frames) {
mad_timer_t duration = data->frame.header.duration;
mad_timer_multiply(&duration, xing.frames);
data->totalTime = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000;
data->maxFrames = xing.frames;
}
+
+ if (parse_lame(&lame, &ptr, &bitlen)) {
+ if (gaplessPlaybackEnabled &&
+ data->inStream->seekable) {
+ data->dropSamplesAtStart = lame.encoderDelay +
+ DECODERDELAY;
+ data->dropSamplesAtEnd = lame.encoderPadding;
+ }
+
+ /* Album gain isn't currently used. See comment in
+ * parse_lame() for details. -- jat */
+ if (replayGainInfo && !*replayGainInfo &&
+ lame.trackGain) {
+ *replayGainInfo = newReplayGainInfo();
+ (*replayGainInfo)->trackGain = lame.trackGain;
+ (*replayGainInfo)->trackPeak = lame.peak;
+ }
+ }
}
if (!data->maxFrames) return -1;