diff --git a/src/DecoderAPI.cxx b/src/DecoderAPI.cxx
index 4866c4bb8..f672b1750 100644
--- a/src/DecoderAPI.cxx
+++ b/src/DecoderAPI.cxx
@@ -518,11 +518,12 @@ decoder_replay_gain(Decoder &decoder,
 			if (rgm != REPLAY_GAIN_ALBUM)
 				rgm = REPLAY_GAIN_TRACK;
 
-			decoder.dc.replay_gain_db = 20.0 * log10f(
-				replay_gain_tuple_scale(
-					&replay_gain_info->tuples[rgm],
-					replay_gain_preamp, replay_gain_missing_preamp,
-					replay_gain_limit));
+			const auto &tuple = replay_gain_info->tuples[rgm];
+			const auto scale =
+				tuple.CalculateScale(replay_gain_preamp,
+						     replay_gain_missing_preamp,
+						     replay_gain_limit);
+			decoder.dc.replay_gain_db = 20.0 * log10f(scale);
 		}
 
 		decoder.replay_gain_info = *replay_gain_info;
diff --git a/src/ReplayGainInfo.cxx b/src/ReplayGainInfo.cxx
index 6ad9d269e..7ee788e04 100644
--- a/src/ReplayGainInfo.cxx
+++ b/src/ReplayGainInfo.cxx
@@ -21,18 +21,19 @@
 #include "ReplayGainInfo.hxx"
 
 float
-replay_gain_tuple_scale(const ReplayGainTuple *tuple, float preamp, float missing_preamp, bool peak_limit)
+ReplayGainTuple::CalculateScale(float preamp, float missing_preamp,
+				bool peak_limit) const
 {
 	float scale;
 
-	if (replay_gain_tuple_defined(tuple)) {
-		scale = pow(10.0, tuple->gain / 20.0);
+	if (IsDefined()) {
+		scale = pow(10.0, gain / 20.0);
 		scale *= preamp;
 		if (scale > 15.0)
 			scale = 15.0;
 
-		if (peak_limit && scale * tuple->peak > 1.0)
-			scale = 1.0 / tuple->peak;
+		if (peak_limit && scale * peak > 1.0)
+			scale = 1.0 / peak;
 	} else
 		scale = missing_preamp;
 
@@ -40,9 +41,8 @@ replay_gain_tuple_scale(const ReplayGainTuple *tuple, float preamp, float missin
 }
 
 void
-replay_gain_info_complete(ReplayGainInfo &info)
+ReplayGainInfo::Complete()
 {
-	if (!replay_gain_tuple_defined(&info.tuples[REPLAY_GAIN_ALBUM]))
-		info.tuples[REPLAY_GAIN_ALBUM] =
-			info.tuples[REPLAY_GAIN_TRACK];
+	if (!tuples[REPLAY_GAIN_ALBUM].IsDefined())
+		tuples[REPLAY_GAIN_ALBUM] = tuples[REPLAY_GAIN_TRACK];
 }
diff --git a/src/ReplayGainInfo.hxx b/src/ReplayGainInfo.hxx
index 2b2d3d3db..8846a6ed3 100644
--- a/src/ReplayGainInfo.hxx
+++ b/src/ReplayGainInfo.hxx
@@ -21,6 +21,7 @@
 #define MPD_REPLAY_GAIN_INFO_HXX
 
 #include "check.h"
+#include "Compiler.h"
 
 #include <cmath>
 
@@ -34,40 +35,35 @@ enum ReplayGainMode {
 struct ReplayGainTuple {
 	float gain;
 	float peak;
+
+	void Clear() {
+		gain = INFINITY;
+		peak = 0.0;
+	}
+
+	gcc_pure
+	bool IsDefined() const {
+		return !std::isinf(gain);
+	}
+
+	gcc_pure
+	float CalculateScale(float preamp, float missing_preamp,
+			     bool peak_limit) const;
 };
 
 struct ReplayGainInfo {
 	ReplayGainTuple tuples[2];
+
+	void Clear() {
+		tuples[REPLAY_GAIN_ALBUM].Clear();
+		tuples[REPLAY_GAIN_TRACK].Clear();
+	}
+
+	/**
+	 * Attempt to auto-complete missing data.  In particular, if
+	 * album information is missing, track gain is used.
+	 */
+	void Complete();
 };
 
-static inline void
-replay_gain_tuple_init(ReplayGainTuple *tuple)
-{
-	tuple->gain = INFINITY;
-	tuple->peak = 0.0;
-}
-
-static inline void
-replay_gain_info_init(struct ReplayGainInfo *info)
-{
-	replay_gain_tuple_init(&info->tuples[REPLAY_GAIN_ALBUM]);
-	replay_gain_tuple_init(&info->tuples[REPLAY_GAIN_TRACK]);
-}
-
-static inline bool
-replay_gain_tuple_defined(const ReplayGainTuple *tuple)
-{
-	return !std::isinf(tuple->gain);
-}
-
-float
-replay_gain_tuple_scale(const ReplayGainTuple *tuple, float preamp, float missing_preamp, bool peak_limit);
-
-/**
- * Attempt to auto-complete missing data.  In particular, if album
- * information is missing, track gain is used.
- */
-void
-replay_gain_info_complete(ReplayGainInfo &info);
-
 #endif
diff --git a/src/decoder/FlacMetadata.cxx b/src/decoder/FlacMetadata.cxx
index 783394982..917da7d87 100644
--- a/src/decoder/FlacMetadata.cxx
+++ b/src/decoder/FlacMetadata.cxx
@@ -64,10 +64,9 @@ bool
 flac_parse_replay_gain(ReplayGainInfo &rgi,
 		       const FLAC__StreamMetadata *block)
 {
+	rgi.Clear();
+
 	bool found = false;
-
-	replay_gain_info_init(&rgi);
-
 	if (flac_find_float_comment(block, "replaygain_album_gain",
 				    &rgi.tuples[REPLAY_GAIN_ALBUM].gain))
 		found = true;
diff --git a/src/decoder/MadDecoderPlugin.cxx b/src/decoder/MadDecoderPlugin.cxx
index 085497504..c7ed8781d 100644
--- a/src/decoder/MadDecoderPlugin.cxx
+++ b/src/decoder/MadDecoderPlugin.cxx
@@ -260,7 +260,7 @@ parse_id3_replay_gain_info(ReplayGainInfo &rgi,
 	struct id3_frame *frame;
 	bool found = false;
 
-	replay_gain_info_init(&rgi);
+	rgi.Clear();
 
 	for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
 		if (frame->nfields < 3)
@@ -872,7 +872,7 @@ MadDecoder::DecodeFirstFrame(Tag **tag)
 			if (decoder != nullptr && !found_replay_gain &&
 			    lame.track_gain) {
 				ReplayGainInfo rgi;
-				replay_gain_info_init(&rgi);
+				rgi.Clear();
 				rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
 				rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
 				decoder_replay_gain(*decoder, &rgi);
diff --git a/src/decoder/MpcdecDecoderPlugin.cxx b/src/decoder/MpcdecDecoderPlugin.cxx
index 654feaaf1..dc258623c 100644
--- a/src/decoder/MpcdecDecoderPlugin.cxx
+++ b/src/decoder/MpcdecDecoderPlugin.cxx
@@ -169,7 +169,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
 	}
 
 	ReplayGainInfo rgi;
-	replay_gain_info_init(&rgi);
+	rgi.Clear();
 	rgi.tuples[REPLAY_GAIN_ALBUM].gain = MPC_OLD_GAIN_REF  - (info.gain_album  / 256.);
 	rgi.tuples[REPLAY_GAIN_ALBUM].peak = pow(10, info.peak_album / 256. / 20) / 32767;
 	rgi.tuples[REPLAY_GAIN_TRACK].gain = MPC_OLD_GAIN_REF  - (info.gain_title  / 256.);
diff --git a/src/decoder/OpusDecoderPlugin.cxx b/src/decoder/OpusDecoderPlugin.cxx
index c50f98a5b..887b33a64 100644
--- a/src/decoder/OpusDecoderPlugin.cxx
+++ b/src/decoder/OpusDecoderPlugin.cxx
@@ -283,7 +283,7 @@ inline DecoderCommand
 MPDOpusDecoder::HandleTags(const ogg_packet &packet)
 {
 	ReplayGainInfo rgi;
-	replay_gain_info_init(&rgi);
+	rgi.Clear();
 
 	TagBuilder tag_builder;
 
diff --git a/src/decoder/VorbisComments.cxx b/src/decoder/VorbisComments.cxx
index 9830e733e..8fd078ff4 100644
--- a/src/decoder/VorbisComments.cxx
+++ b/src/decoder/VorbisComments.cxx
@@ -49,11 +49,11 @@ vorbis_comment_value(const char *comment, const char *needle)
 bool
 vorbis_comments_to_replay_gain(ReplayGainInfo &rgi, char **comments)
 {
+	rgi.Clear();
+
 	const char *temp;
 	bool found = false;
 
-	replay_gain_info_init(&rgi);
-
 	while (*comments) {
 		if ((temp =
 		     vorbis_comment_value(*comments, "replaygain_track_gain"))) {
diff --git a/src/decoder/WavpackDecoderPlugin.cxx b/src/decoder/WavpackDecoderPlugin.cxx
index 62934713f..98555c5e8 100644
--- a/src/decoder/WavpackDecoderPlugin.cxx
+++ b/src/decoder/WavpackDecoderPlugin.cxx
@@ -224,10 +224,9 @@ static bool
 wavpack_replaygain(ReplayGainInfo &rgi,
 		   WavpackContext *wpc)
 {
+	rgi.Clear();
+
 	bool found = false;
-
-	replay_gain_info_init(&rgi);
-
 	found |= wavpack_tag_float(wpc, "replaygain_track_gain",
 				   &rgi.tuples[REPLAY_GAIN_TRACK].gain);
 	found |= wavpack_tag_float(wpc, "replaygain_track_peak",
diff --git a/src/filter/ReplayGainFilterPlugin.cxx b/src/filter/ReplayGainFilterPlugin.cxx
index 5fb59b741..4d6173e9b 100644
--- a/src/filter/ReplayGainFilterPlugin.cxx
+++ b/src/filter/ReplayGainFilterPlugin.cxx
@@ -76,7 +76,7 @@ public:
 	ReplayGainFilter()
 		:mixer(nullptr), mode(REPLAY_GAIN_OFF),
 		volume(PCM_VOLUME_1) {
-		replay_gain_info_init(&info);
+		info.Clear();
 	}
 
 	void SetMixer(Mixer *_mixer, unsigned _base) {
@@ -91,9 +91,9 @@ public:
 	void SetInfo(const ReplayGainInfo *_info) {
 		if (_info != NULL) {
 			info = *_info;
-			replay_gain_info_complete(info);
+			info.Complete();
 		} else
-			replay_gain_info_init(&info);
+			info.Clear();
 
 		Update();
 	}
@@ -126,8 +126,10 @@ void
 ReplayGainFilter::Update()
 {
 	if (mode != REPLAY_GAIN_OFF) {
-		float scale = replay_gain_tuple_scale(&info.tuples[mode],
-		    replay_gain_preamp, replay_gain_missing_preamp, replay_gain_limit);
+		const auto &tuple = info.tuples[mode];
+		float scale = tuple.CalculateScale(replay_gain_preamp,
+						   replay_gain_missing_preamp,
+						   replay_gain_limit);
 		FormatDebug(replay_gain_domain,
 			    "scale=%f\n", (double)scale);
 
diff --git a/test/dump_playlist.cxx b/test/dump_playlist.cxx
index 6517473d2..d8a8084b0 100644
--- a/test/dump_playlist.cxx
+++ b/test/dump_playlist.cxx
@@ -120,12 +120,12 @@ decoder_replay_gain(gcc_unused Decoder &decoder,
 		    const ReplayGainInfo *rgi)
 {
 	const ReplayGainTuple *tuple = &rgi->tuples[REPLAY_GAIN_ALBUM];
-	if (replay_gain_tuple_defined(tuple))
+	if (tuple->IsDefined())
 		g_printerr("replay_gain[album]: gain=%f peak=%f\n",
 			   tuple->gain, tuple->peak);
 
 	tuple = &rgi->tuples[REPLAY_GAIN_TRACK];
-	if (replay_gain_tuple_defined(tuple))
+	if (tuple->IsDefined())
 		g_printerr("replay_gain[track]: gain=%f peak=%f\n",
 			   tuple->gain, tuple->peak);
 }
diff --git a/test/dump_rva2.cxx b/test/dump_rva2.cxx
index a77568c99..3d47431ec 100644
--- a/test/dump_rva2.cxx
+++ b/test/dump_rva2.cxx
@@ -67,7 +67,7 @@ int main(int argc, char **argv)
 	}
 
 	ReplayGainInfo replay_gain;
-	replay_gain_info_init(&replay_gain);
+	replay_gain.Clear();
 
 	bool success = tag_rva2_parse(tag, replay_gain);
 	id3_tag_delete(tag);
@@ -78,12 +78,12 @@ int main(int argc, char **argv)
 	}
 
 	const ReplayGainTuple *tuple = &replay_gain.tuples[REPLAY_GAIN_ALBUM];
-	if (replay_gain_tuple_defined(tuple))
+	if (tuple->IsDefined())
 		g_printerr("replay_gain[album]: gain=%f peak=%f\n",
 			   tuple->gain, tuple->peak);
 
 	tuple = &replay_gain.tuples[REPLAY_GAIN_TRACK];
-	if (replay_gain_tuple_defined(tuple))
+	if (tuple->IsDefined())
 		g_printerr("replay_gain[track]: gain=%f peak=%f\n",
 			   tuple->gain, tuple->peak);
 
diff --git a/test/run_decoder.cxx b/test/run_decoder.cxx
index 53e6ede2a..f4662e8af 100644
--- a/test/run_decoder.cxx
+++ b/test/run_decoder.cxx
@@ -130,12 +130,12 @@ decoder_replay_gain(gcc_unused Decoder &decoder,
 		    const ReplayGainInfo *rgi)
 {
 	const ReplayGainTuple *tuple = &rgi->tuples[REPLAY_GAIN_ALBUM];
-	if (replay_gain_tuple_defined(tuple))
+	if (tuple->IsDefined())
 		g_printerr("replay_gain[album]: gain=%f peak=%f\n",
 			   tuple->gain, tuple->peak);
 
 	tuple = &rgi->tuples[REPLAY_GAIN_TRACK];
-	if (replay_gain_tuple_defined(tuple))
+	if (tuple->IsDefined())
 		g_printerr("replay_gain[track]: gain=%f peak=%f\n",
 			   tuple->gain, tuple->peak);
 }