Merge branch 'r128tags' into 'main'

replaygain: Use R128 gain tags when available

Closes #1639

See merge request gstreamer/gstreamer!6369
This commit is contained in:
Val Packett 2024-05-03 21:08:27 +00:00
commit 696afdf3a9
5 changed files with 92 additions and 16 deletions

View file

@ -4544,6 +4544,7 @@
"GST_TAG_ALBUM_ARTIST",
"GST_TAG_ALBUM_ARTIST_SORTNAME",
"GST_TAG_ALBUM_GAIN",
"GST_TAG_ALBUM_GAIN_R128",
"GST_TAG_ALBUM_PEAK",
"GST_TAG_ALBUM_SORTNAME",
"GST_TAG_ALBUM_VOLUME_COUNT",
@ -4714,6 +4715,7 @@
"GST_TAG_TITLE_SORTNAME",
"GST_TAG_TRACK_COUNT",
"GST_TAG_TRACK_GAIN",
"GST_TAG_TRACK_GAIN_R128",
"GST_TAG_TRACK_NUMBER",
"GST_TAG_TRACK_PEAK",
"GST_TAG_USER_RATING",

View file

@ -69,8 +69,10 @@ static const GstTagEntryMatch tag_matches[] = {
{GST_TAG_ISRC, "ISRC"},
{GST_TAG_COMMENT, "COMMENT"},
{GST_TAG_TRACK_GAIN, "REPLAYGAIN_TRACK_GAIN"},
{GST_TAG_TRACK_GAIN_R128, "R128_TRACK_GAIN"},
{GST_TAG_TRACK_PEAK, "REPLAYGAIN_TRACK_PEAK"},
{GST_TAG_ALBUM_GAIN, "REPLAYGAIN_ALBUM_GAIN"},
{GST_TAG_ALBUM_GAIN_R128, "R128_ALBUM_GAIN"},
{GST_TAG_ALBUM_PEAK, "REPLAYGAIN_ALBUM_PEAK"},
{GST_TAG_REFERENCE_LEVEL, "REPLAYGAIN_REFERENCE_LOUDNESS"},
{GST_TAG_ACOUSTID_ID, "ACOUSTID_ID"},
@ -215,13 +217,15 @@ gst_vorbis_tag_add (GstTagList * list, const gchar * tag, const gchar * value)
is_track_number_tag = (strcmp (gst_tag, GST_TAG_TRACK_NUMBER) == 0);
is_disc_number_tag = (strcmp (gst_tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0);
tmp = strtoul (value, &check, 10);
tmp = g_ascii_strtoull (value, &check, 10);
if (tmp > G_MAXUINT32)
break;
if (*check == '/' && (is_track_number_tag || is_disc_number_tag)) {
guint count;
check++;
count = strtoul (check, &check, 10);
if (*check != '\0' || count == 0)
count = g_ascii_strtoull (check, &check, 10);
if (*check != '\0' || count == 0 || count > G_MAXUINT32)
break;
if (is_track_number_tag) {
gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_TRACK_COUNT,
@ -267,12 +271,25 @@ gst_vorbis_tag_add (GstTagList * list, const gchar * tag, const gchar * value)
break;
}
case G_TYPE_DOUBLE:{
if (strcmp (tag, "R128_TRACK_GAIN") == 0 ||
strcmp (tag, "R128_ALBUM_GAIN") == 0) {
gint tmp;
gchar *check;
tmp = g_ascii_strtoll (value, &check, 10);
if (*check != '\0' || tmp < -32768 || tmp > 32767)
break;
gst_tag_list_add (list, GST_TAG_MERGE_APPEND, gst_tag,
(gdouble)tmp / 256., NULL);
break;
}
gchar *c;
c = g_strdup (value);
g_strdelimit (c, ",", '.');
gst_tag_list_add (list, GST_TAG_MERGE_APPEND, gst_tag,
g_strtod (c, NULL), NULL);
g_ascii_strtod (c, NULL), NULL);
g_free (c);
break;
}
@ -726,8 +743,13 @@ gst_tag_to_vorbis_comments (const GstTagList * list, const gchar * tag)
if (!gst_tag_list_get_double_index (list, tag, i, &value))
g_return_val_if_reached (NULL);
g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", value);
result = g_strconcat (vorbis_tag, "=", buf, NULL);
if (strcmp (tag, GST_TAG_TRACK_GAIN_R128) == 0 ||
strcmp (tag, GST_TAG_ALBUM_GAIN_R128) == 0) {
result = g_strdup_printf ("%s=%u", vorbis_tag, (gint)(value * 256.));
} else {
g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", value);
result = g_strconcat (vorbis_tag, "=", buf, NULL);
}
break;
}
default:{

View file

@ -26,14 +26,18 @@
* @see_also: #GstRgLimiter, #GstRgAnalysis
*
* This element applies volume changes to streams as lined out in the proposed
* [ReplayGain standard](https://wiki.hydrogenaud.io/index.php?title=ReplayGain).
* It interprets the ReplayGain meta data tags and carries out the adjustment
* (by using a volume element internally).
* [ReplayGain standard](https://wiki.hydrogenaud.io/index.php?title=ReplayGain)
* and in the [EBU R 128](https://tech.ebu.ch/publications/r128/) standard.
* It interprets the ReplayGain and R128 meta data tags and carries out the
* adjustment (by using a volume element internally).
* If R128 tags are present, ReplayGain tags are ignored.
*
* The relevant tags are:
* * #GST_TAG_TRACK_GAIN
* * #GST_TAG_TRACK_GAIN_R128
* * #GST_TAG_TRACK_PEAK
* * #GST_TAG_ALBUM_GAIN
* * #GST_TAG_ALBUM_GAIN_R128
* * #GST_TAG_ALBUM_PEAK
* * #GST_TAG_REFERENCE_LEVEL
*
@ -479,7 +483,9 @@ gst_rg_volume_tag_event (GstRgVolume * self, GstEvent * event)
{
GstTagList *tag_list;
gboolean has_track_gain, has_track_peak, has_album_gain, has_album_peak;
gboolean has_track_gain_r128, has_album_gain_r128;
gboolean has_ref_level;
gdouble track_gain_r128, album_gain_r128;
g_return_val_if_fail (event != NULL, NULL);
g_return_val_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG, event);
@ -491,16 +497,21 @@ gst_rg_volume_tag_event (GstRgVolume * self, GstEvent * event)
has_track_gain = gst_tag_list_get_double (tag_list, GST_TAG_TRACK_GAIN,
&self->track_gain);
has_track_gain_r128 = gst_tag_list_get_double (tag_list,
GST_TAG_TRACK_GAIN_R128, &track_gain_r128);
has_track_peak = gst_tag_list_get_double (tag_list, GST_TAG_TRACK_PEAK,
&self->track_peak);
has_album_gain = gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_GAIN,
&self->album_gain);
has_album_gain_r128 = gst_tag_list_get_double (tag_list,
GST_TAG_ALBUM_GAIN_R128, &album_gain_r128);
has_album_peak = gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_PEAK,
&self->album_peak);
has_ref_level = gst_tag_list_get_double (tag_list, GST_TAG_REFERENCE_LEVEL,
&self->reference_level);
if (!has_track_gain && !has_track_peak && !has_album_gain && !has_album_peak)
if (!has_track_gain && !has_track_gain_r128 && !has_track_peak &&
!has_album_gain && !has_album_gain_r128 && !has_album_peak)
return event;
if (has_ref_level && (has_track_gain || has_album_gain)
@ -517,6 +528,25 @@ gst_rg_volume_tag_event (GstRgVolume * self, GstEvent * event)
self->album_gain += RG_REFERENCE_LEVEL - self->reference_level;
}
/*
* R128 tags can be present together with RG tags, should take priority,
* and should not take interference from RG reference level or peak tags.
*/
if (has_track_gain_r128) {
has_track_peak = FALSE;
self->track_gain = track_gain_r128 + 5.;
GST_DEBUG_OBJECT (self,
"decoded R128 track gain %d as %" GAIN_FORMAT,
track_gain_r128, self->track_gain);
}
if (has_album_gain_r128) {
has_album_peak = FALSE;
self->album_gain = album_gain_r128 + 5.;
GST_DEBUG_OBJECT (self,
"decoded R128 album gain %d as %" GAIN_FORMAT,
album_gain_r128, self->album_gain);
}
/* Ignore values that are obviously invalid. */
if (G_UNLIKELY (has_track_gain && !VALID_GAIN (self->track_gain))) {
GST_DEBUG_OBJECT (self,
@ -553,15 +583,17 @@ gst_rg_volume_tag_event (GstRgVolume * self, GstEvent * event)
self->album_peak = 1.0;
}
self->has_track_gain |= has_track_gain;
self->has_track_gain |= has_track_gain | has_track_gain_r128;
self->has_track_peak |= has_track_peak;
self->has_album_gain |= has_album_gain;
self->has_album_gain |= has_album_gain | has_album_gain_r128;
self->has_album_peak |= has_album_peak;
tag_list = gst_tag_list_copy (tag_list);
gst_tag_list_remove_tag (tag_list, GST_TAG_TRACK_GAIN);
gst_tag_list_remove_tag (tag_list, GST_TAG_TRACK_GAIN_R128);
gst_tag_list_remove_tag (tag_list, GST_TAG_TRACK_PEAK);
gst_tag_list_remove_tag (tag_list, GST_TAG_ALBUM_GAIN);
gst_tag_list_remove_tag (tag_list, GST_TAG_ALBUM_GAIN_R128);
gst_tag_list_remove_tag (tag_list, GST_TAG_ALBUM_PEAK);
gst_tag_list_remove_tag (tag_list, GST_TAG_REFERENCE_LEVEL);

View file

@ -264,11 +264,15 @@ _priv_gst_tag_initialize (void)
gst_tag_register_static (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED,
G_TYPE_UINT, _("serial"), _("serial number of track"), NULL);
gst_tag_register_static (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META,
G_TYPE_DOUBLE, _("replaygain track gain"), _("track gain in db"), NULL);
G_TYPE_DOUBLE, _("replaygain track gain"), _("track gain in dB"), NULL);
gst_tag_register_static (GST_TAG_TRACK_GAIN_R128, GST_TAG_FLAG_META,
G_TYPE_DOUBLE, _("r128 track gain"), _("track gain in dB (r128)"), NULL);
gst_tag_register_static (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META,
G_TYPE_DOUBLE, _("replaygain track peak"), _("peak of the track"), NULL);
gst_tag_register_static (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META,
G_TYPE_DOUBLE, _("replaygain album gain"), _("album gain in db"), NULL);
G_TYPE_DOUBLE, _("replaygain album gain"), _("album gain in dB"), NULL);
gst_tag_register_static (GST_TAG_ALBUM_GAIN_R128, GST_TAG_FLAG_META,
G_TYPE_DOUBLE, _("r128 album gain"), _("album gain in dB (r128)"), NULL);
gst_tag_register_static (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META,
G_TYPE_DOUBLE, _("replaygain album peak"), _("peak of the album"), NULL);
gst_tag_register_static (GST_TAG_REFERENCE_LEVEL, GST_TAG_FLAG_META,

View file

@ -793,9 +793,17 @@ gboolean gst_tag_list_take (GstTagList ** old_taglist,
/**
* GST_TAG_TRACK_GAIN:
*
* track gain in db (double)
* track gain in dB (double)
*/
#define GST_TAG_TRACK_GAIN "replaygain-track-gain"
/**
* GST_TAG_TRACK_GAIN_R128:
*
* track gain in dB (double)
*
* Since: 1.26
*/
#define GST_TAG_TRACK_GAIN_R128 "r128-track-gain"
/**
* GST_TAG_TRACK_PEAK:
*
@ -805,9 +813,17 @@ gboolean gst_tag_list_take (GstTagList ** old_taglist,
/**
* GST_TAG_ALBUM_GAIN:
*
* album gain in db (double)
* album gain in dB (double)
*/
#define GST_TAG_ALBUM_GAIN "replaygain-album-gain"
/**
* GST_TAG_ALBUM_GAIN_R128:
*
* track gain in dB (double)
*
* Since: 1.26
*/
#define GST_TAG_ALBUM_GAIN_R128 "r128-album-gain"
/**
* GST_TAG_ALBUM_PEAK:
*