diff --git a/src/tag/Handler.cxx b/src/tag/Handler.cxx
index ad8404161..78b81763d 100644
--- a/src/tag/Handler.cxx
+++ b/src/tag/Handler.cxx
@@ -20,11 +20,17 @@
 #include "config.h"
 #include "Handler.hxx"
 #include "Builder.hxx"
+#include "AudioFormat.hxx"
 #include "util/ASCII.hxx"
 #include "util/StringFormat.hxx"
 
 #include <stdlib.h>
 
+void
+NullTagHandler::OnAudioFormat(gcc_unused AudioFormat af) noexcept
+{
+}
+
 void
 AddTagHandler::OnDuration(SongTime duration) noexcept
 {
diff --git a/src/tag/Handler.hxx b/src/tag/Handler.hxx
index 414daf965..6b0342d80 100644
--- a/src/tag/Handler.hxx
+++ b/src/tag/Handler.hxx
@@ -25,6 +25,7 @@
 #include "Chrono.hxx"
 #include "Compiler.h"
 
+struct AudioFormat;
 class TagBuilder;
 
 /**
@@ -37,6 +38,7 @@ public:
 	static constexpr unsigned WANT_DURATION = 0x1;
 	static constexpr unsigned WANT_TAG = 0x2;
 	static constexpr unsigned WANT_PAIR = 0x4;
+	static constexpr unsigned WANT_AUDIO_FORMAT = 0x8;
 
 	explicit TagHandler(unsigned _want_mask) noexcept
 		:want_mask(_want_mask) {}
@@ -56,6 +58,10 @@ public:
 		return want_mask & WANT_PAIR;
 	}
 
+	bool WantAudioFormat() const noexcept {
+		return want_mask & WANT_AUDIO_FORMAT;
+	}
+
 	/**
 	 * Declare the duration of a song.  Do not call
 	 * this when the duration could not be determined, because
@@ -76,6 +82,23 @@ public:
 	 * representation of tags.
 	 */
 	virtual void OnPair(const char *key, const char *value) noexcept = 0;
+
+	/**
+	 * Declare the audio format of a song.
+	 *
+	 * Because the #AudioFormat type is limited to formats
+	 * supported by MPD, the value passed to this method may be an
+	 * approximation (should be the one passed to
+	 * DecoderClient::Ready()).  For example, some codecs such as
+	 * MP3 are bit depth agnostic, so the decoder plugin chooses a
+	 * bit depth depending on what the codec library emits.
+	 *
+	 * This method is only called by those decoder plugins which
+	 * implement it.  Some may not have any code for calling it,
+	 * and others may decide that determining the audio format is
+	 * too expensive.
+	 */
+	virtual void OnAudioFormat(AudioFormat af) noexcept = 0;
 };
 
 class NullTagHandler : public TagHandler {
@@ -88,6 +111,7 @@ public:
 		   gcc_unused const char *value) noexcept override {}
 	void OnPair(gcc_unused const char *key,
 		    gcc_unused const char *value) noexcept override {}
+	void OnAudioFormat(AudioFormat af) noexcept override;
 };
 
 /**
diff --git a/test/read_tags.cxx b/test/read_tags.cxx
index e2ea56ad8..6d3968769 100644
--- a/test/read_tags.cxx
+++ b/test/read_tags.cxx
@@ -26,8 +26,10 @@
 #include "tag/Handler.hxx"
 #include "tag/Generic.hxx"
 #include "fs/Path.hxx"
+#include "AudioFormat.hxx"
 #include "Log.hxx"
 #include "util/ScopeExit.hxx"
+#include "util/StringBuffer.hxx"
 
 #include <stdexcept>
 
@@ -63,6 +65,10 @@ public:
 	void OnPair(const char *key, const char *value) noexcept override {
 		printf("\"%s\"=%s\n", key, value);
 	}
+
+	void OnAudioFormat(AudioFormat af) noexcept override {
+		printf("%s\n", ToString(af).c_str());
+	}
 };
 
 int main(int argc, char **argv)