diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index 89246be1c..6b5405f87 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -469,7 +469,6 @@ static void
 AlsaSetup(AlsaOutput *ad, AudioFormat &audio_format,
 	  PcmExport::Params &params)
 {
-	unsigned int sample_rate = audio_format.sample_rate;
 	unsigned int channels = audio_format.channels;
 	int err;
 	unsigned retry = MPD_ALSA_RETRY_NR;
@@ -513,18 +512,23 @@ configure_hw:
 
 	audio_format.channels = (int8_t)channels;
 
+	const unsigned requested_sample_rate =
+		params.CalcOutputSampleRate(audio_format.sample_rate);
+	unsigned output_sample_rate = requested_sample_rate;
+
 	err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams,
-					      &sample_rate, nullptr);
+					      &output_sample_rate, nullptr);
 	if (err < 0)
 		throw FormatRuntimeError("Failed to configure sample rate %u Hz: %s",
-					 audio_format.sample_rate,
+					 requested_sample_rate,
 					 snd_strerror(-err));
 
-	if (sample_rate == 0)
+	if (output_sample_rate == 0)
 		throw FormatRuntimeError("Failed to configure sample rate %u Hz",
 					 audio_format.sample_rate);
 
-	audio_format.sample_rate = sample_rate;
+	if (output_sample_rate != requested_sample_rate)
+		audio_format.sample_rate = params.CalcInputSampleRate(output_sample_rate);
 
 	snd_pcm_uframes_t buffer_size_min, buffer_size_max;
 	snd_pcm_hw_params_get_buffer_size_min(hwparams, &buffer_size_min);
diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx
index f92d9e3ac..25cf8dbd5 100644
--- a/src/pcm/PcmExport.cxx
+++ b/src/pcm/PcmExport.cxx
@@ -98,6 +98,18 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const
 	return audio_format.GetFrameSize();
 }
 
+unsigned
+PcmExport::Params::CalcOutputSampleRate(unsigned sample_rate) const
+{
+	return sample_rate;
+}
+
+unsigned
+PcmExport::Params::CalcInputSampleRate(unsigned sample_rate) const
+{
+	return sample_rate;
+}
+
 ConstBuffer<void>
 PcmExport::Export(ConstBuffer<void> data)
 {
diff --git a/src/pcm/PcmExport.hxx b/src/pcm/PcmExport.hxx
index 8dde62b32..7102ff32f 100644
--- a/src/pcm/PcmExport.hxx
+++ b/src/pcm/PcmExport.hxx
@@ -41,6 +41,21 @@ struct PcmExport {
 		bool shift8 = false;
 		bool pack24 = false;
 		bool reverse_endian = false;
+
+		/**
+		 * Calculate the output sample rate, given a specific input
+		 * sample rate.  Usually, both are the same; however, with
+		 * DSD_U32, four input bytes (= 4 * 8 bits) are combined to
+		 * one output word (32 bits), dividing the sample rate by 4.
+		 */
+		gcc_pure
+		unsigned CalcOutputSampleRate(unsigned input_sample_rate) const;
+
+		/**
+		 * The inverse of CalcOutputSampleRate().
+		 */
+		gcc_pure
+		unsigned CalcInputSampleRate(unsigned output_sample_rate) const;
 	};
 
 	/**
diff --git a/test/test_pcm_export.cxx b/test/test_pcm_export.cxx
index 6d64bb765..2c2e32013 100644
--- a/test/test_pcm_export.cxx
+++ b/test/test_pcm_export.cxx
@@ -35,6 +35,9 @@ PcmExportTest::TestShift8()
 	PcmExport::Params params;
 	params.shift8 = true;
 
+	CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
+	CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
+
 	PcmExport e;
 	e.Open(SampleFormat::S24_P32, 2, params);
 
@@ -71,6 +74,9 @@ PcmExportTest::TestPack24()
 	PcmExport::Params params;
 	params.pack24 = true;
 
+	CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
+	CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
+
 	PcmExport e;
 	e.Open(SampleFormat::S24_P32, 2, params);
 
@@ -97,6 +103,9 @@ PcmExportTest::TestReverseEndian()
 	PcmExport::Params params;
 	params.reverse_endian = true;
 
+	CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
+	CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
+
 	PcmExport e;
 	e.Open(SampleFormat::S8, 2, params);
 
@@ -192,6 +201,9 @@ TestAlsaChannelOrder51()
 	PcmExport::Params params;
 	params.alsa_channel_order = true;
 
+	CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
+	CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
+
 	PcmExport e;
 	e.Open(F, 6, params);
 
@@ -219,6 +231,9 @@ TestAlsaChannelOrder71()
 	PcmExport::Params params;
 	params.alsa_channel_order = true;
 
+	CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
+	CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
+
 	PcmExport e;
 	e.Open(F, 8, params);