Package: mp3gain
Version: 1.5.1-3
Severity: normal
Tags: patch
Forwarded: 
https://sourceforge.net/tracker/?func=detail&aid=3022522&group_id=49979&atid=458158

When invoked as "mp3gain -s i", mp3gain writes out ID3v2.4 RVA2 frames
containing the replay gain.

However, some MP3 players (apparently including Winamp) don't seem to
interpret RVA2 frames; instead, they expect to see replay gain in TXXX frames
with the same name as the tags conventional in Vorbis/APEv2. I attach a simple
patch to write those frames too.

(I've filed this as normal rather than wishlist since it's an interoperability
problem, and easy to fix; feel free to downgrade this bug if you disagree.)

Regards,
    Simon
#! /bin/sh /usr/share/dpatch/dpatch-run
## 09_txxx.dpatch by Simon McVittie <s...@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: in ID3 tags, produce TXXX frames compatible with Winamp, as well as
## DP: the correct RVA2 frames

@DPATCH@
--- mp3gain-1.5.1.orig/id3tag.c
+++ mp3gain-1.5.1/id3tag.c
@@ -420,6 +420,71 @@
 
 
 /**
+ * Decode an APEv2/Vorbis-style TXXX frame, matching
+ * /REPLAYGAIN_(ALBUM|TRACK)_(GAIN|PEAK)/ case-insensitively.
+ *
+ * Store gain information in the info structure, unless info == NULL.
+ * Return 1 if the frame is one of our TXXX frames, 0 otherwise.
+ */
+static int id3_decode_txxx_frame(const struct ID3v2FrameStruct *frame, struct 
MP3GainTagInfo *info)
+{
+       unsigned long p, k;
+       char buf[64];
+       const char *value;
+
+       /* Ignore non-TXXX frames. */
+       if (memcmp(frame->frameid, "TXXX", 4) != 0)
+               return 0;
+
+       p = frame->hskip;
+
+       /* Check text encoding; we understand only 0 (ISO-8859-1) and 3 
(UTF-8). */
+       if (p >= frame->len || (frame->data[p] != 0 && frame->data[p] != 3))
+               return 0;
+       p++;
+
+       /* Copy character data to temporary buffer. */
+       k = (frame->len - p + 1 < sizeof(buf)) ? (frame->len - p) : 
(sizeof(buf) - 2);
+       memcpy(buf, frame->data + p, k);
+       buf[k] = '\0';          /* terminate the value string */
+       buf[k+1] = '\0';        /* ensure buf contains two terminated strings, 
even for invalid frame data */
+       value = buf + strlen(buf) + 1;
+
+       /* Check identification string. */
+       if (strcasecmp(buf, "REPLAYGAIN_ALBUM_GAIN") == 0) {
+                if (info) {
+                       info->haveAlbumGain = !0;
+                       info->albumGain = atof(value);
+               }
+               return 1;
+       } else if (strcasecmp(buf, "REPLAYGAIN_TRACK_GAIN") == 0) {
+                if (info) {
+                       info->haveTrackGain = !0;
+                       info->trackGain = atof(value);
+               }
+               return 1;
+       } else if (strcasecmp(buf, "REPLAYGAIN_ALBUM_PEAK") == 0) {
+                if (info) {
+                       info->haveAlbumPeak = !0;
+                       info->albumPeak = atof(value);
+               }
+               return 1;
+       } else if (strcasecmp(buf, "REPLAYGAIN_TRACK_PEAK") == 0) {
+                if (info) {
+                       info->haveTrackPeak = !0;
+                       info->trackPeak = atof(value);
+               }
+               return 1;
+       } else if (strcasecmp(buf, "REPLAYGAIN_REFERENCE_LOUDNESS") == 0) {
+               /* we derive no information from this at the moment, but
+                * we do want to delete this frame if re-writing */
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
  * Decode a mp3gain-specific TXXX frame, either "MP3GAIN_UNDO" or
  * "MP3GAIN_MINMAX" or "MP3GAIN_ALBUM_MINMAX".
  *
@@ -1078,6 +1143,7 @@
                frame = tag.frames;
                while (frame) {
                        id3_decode_rva2_frame(frame, info);
+                       id3_decode_txxx_frame(frame, info);
                        id3_decode_mp3gain_frame(frame, info);
                        frame = frame->next;
                }
@@ -1148,6 +1214,7 @@
        pframe = &(tag.frames);
        while ((frame = *pframe)) {
                if (id3_decode_rva2_frame(frame, NULL) == 1 ||
+                   id3_decode_txxx_frame(frame, NULL) == 1 ||
                    id3_decode_mp3gain_frame(frame, NULL) == 1) {
                        /* This is a ReplayGain frame; kill it. */
                        need_update = 1;
@@ -1159,18 +1226,53 @@
                }
        }
 
-       /* Append new replaygain frames. */
+       /* Append new replaygain frames. The TXXX versions are lower-case,
+        * because that's what Winamp wants... */
+
+       if (info->haveTrackGain || info->haveTrackPeak ||
+           info->haveAlbumGain || info->haveAlbumPeak) {
+               need_update = 1;
+               frame = id3_make_frame("TXXX", "bsbs", 0, 
"replaygain_reference_loudness", 0, "89.0 dB");
+               *pframe = frame;
+               pframe = &(frame->next);
+       }
+
        if (info->haveTrackGain) {
                need_update = 1;
                frame = id3_make_rva2_frame(0, info->trackGain, 
info->haveTrackPeak, info->trackPeak);
                *pframe = frame;
                pframe = &(frame->next);
+
+               sprintf(sbuf, "%-+9.6f dB", info->trackGain);
+               frame = id3_make_frame("TXXX", "bsbs", 0, 
"replaygain_track_gain", 0, sbuf);
+               *pframe = frame;
+               pframe = &(frame->next);
+       }
+       if (info->haveTrackPeak) {
+               need_update = 1;
+               sprintf(sbuf, "%-8.6f", info->trackPeak);
+               frame = id3_make_frame("TXXX", "bsbs", 0, 
"replaygain_track_peak", 0, sbuf);
+               *pframe = frame;
+               pframe = &(frame->next);
        }
+
        if (info->haveAlbumGain) {
                need_update = 1;
                frame = id3_make_rva2_frame(1, info->albumGain, 
info->haveAlbumPeak, info->albumPeak);
                *pframe = frame;
                pframe = &(frame->next);
+
+               sprintf(sbuf, "%-+9.6f dB", info->albumGain);
+               frame = id3_make_frame("TXXX", "bsbs", 0, 
"replaygain_album_gain", 0, sbuf);
+               *pframe = frame;
+               pframe = &(frame->next);
+       }
+       if (info->haveAlbumPeak) {
+               need_update = 1;
+               sprintf(sbuf, "%-8.6f", info->albumPeak);
+               frame = id3_make_frame("TXXX", "bsbs", 0, 
"replaygain_album_peak", 0, sbuf);
+               *pframe = frame;
+               pframe = &(frame->next);
        }
 
        /* Append mp3gain-specific frames. */

Attachment: signature.asc
Description: Digital signature

Reply via email to