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. */
signature.asc
Description: Digital signature