From 3f0139e5db88b447a408547e0a59e071214e0cec Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Wed, 12 Mar 2014 11:14:10 +0100 Subject: af_volume: add replaygain support This adds the options replaygain-track and replaygain-album. If either is set, the replaygain track or album gain will be automatically read from the track metadata and the volume adjusted accordingly. This only supports reading REPLAYGAIN_(TRACK|ALBUM)_GAIN tags. Other formats like LAME's info header would probably require support from libav. --- DOCS/man/en/af.rst | 6 ++++++ audio/filter/af_volume.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/DOCS/man/en/af.rst b/DOCS/man/en/af.rst index 65fa578dbe..902b9803fb 100644 --- a/DOCS/man/en/af.rst +++ b/DOCS/man/en/af.rst @@ -279,6 +279,12 @@ Available filters are: Sets the desired gain in dB for all channels in the stream from -200dB to +60dB, where -200dB mutes the sound completely and +60dB equals a gain of 1000 (default: 0). + ``replaygain-track`` + Adjust volume gain according to the track-gain replaygain value stored + in the file metadata. Note that this only supports reading REPLAYGAIN_* + tags, as written by mp3gain, metaflac, etc... + ``replaygain-album`` + Like replaygain-track, but using the album-gain value instead. ```` Turns soft clipping on. Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this diff --git a/audio/filter/af_volume.c b/audio/filter/af_volume.c index 6a27081b28..ca331bf9b0 100644 --- a/audio/filter/af_volume.c +++ b/audio/filter/af_volume.c @@ -28,9 +28,12 @@ #include "common/common.h" #include "af.h" +#include "demux/demux.h" struct priv { float level; // Gain level for each channel + int rgain_track; // Enable/disable track based replaygain + int rgain_album; // Enable/disable album based replaygain int soft; // Enable/disable soft clipping int fast; // Use fix-point volume control float cfg_volume; @@ -54,6 +57,23 @@ static int control(struct af_instance *af, int cmd, void *arg) } if (af_fmt_is_planar(in->format)) mp_audio_set_format(af->data, af_fmt_to_planar(af->data->format)); + if ((s->rgain_track || s->rgain_album) && af->metadata) { + char *rgain = NULL, *rest; + if (s->rgain_track) { + rgain = mp_tags_get_str(af->metadata, "REPLAYGAIN_TRACK_GAIN"); + } else if (s->rgain_album) { + rgain = mp_tags_get_str(af->metadata, "REPLAYGAIN_ALBUM_GAIN"); + } + if (rgain) { + float db = strtod(rgain, &rest); + if (rest && (rest != rgain) && isfinite(db)) + af_from_dB(1, &db, &s->level, 20.0, -200.0, 60.0); + else + mp_msg(af->log, MSGL_ERR, "Invalid replaygain value\n"); + } else { + mp_msg(af->log, MSGL_ERR, "Replaygain tags not found\n"); + } + } return af_test_output(af, in); } case AF_CONTROL_SET_VOLUME: @@ -119,6 +139,8 @@ struct af_info af_info_volume = { .priv_size = sizeof(struct priv), .options = (const struct m_option[]) { OPT_FLOATRANGE("volumedb", cfg_volume, 0, -200, 60), + OPT_FLAG("replaygain-track", rgain_track, 0), + OPT_FLAG("replaygain-album", rgain_album, 0), OPT_FLAG("softclip", soft, 0), OPT_FLAG("s16", fast, 0), {0} -- cgit v1.2.3