diff --git a/NEWS b/NEWS
index d2f758909..e44865281 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,6 @@
 ver 0.21.23 (not yet released)
+* output
+  - alsa: implement channel mapping for 5.0 and 7.0
 * player
   - drain outputs at end of song in "single" mode
 
diff --git a/src/pcm/Order.cxx b/src/pcm/Order.cxx
index e728f0c9f..e75cacb94 100644
--- a/src/pcm/Order.cxx
+++ b/src/pcm/Order.cxx
@@ -21,6 +21,28 @@
 #include "PcmBuffer.hxx"
 #include "util/ConstBuffer.hxx"
 
+
+/*
+ * According to:
+ *  - https://xiph.org/flac/format.html#frame_header
+ *  - https://github.com/nu774/qaac/wiki/Multichannel--handling
+ * the source channel order (after decoding, e.g., flac, alac) is for
+ *  - 1ch:            mono
+ *  - 2ch:            left, right
+ *  - 3ch:            left, right, center
+ *  - 4ch:            front left, front right, back left, back right
+ *  - 5ch:            front left, front right, front center, back/surround left, back/surround right
+ *  - 6ch (aka 5.1):  front left, front right, front center, LFE, back/surround left, back/surround right
+ *  - 7ch:            front left, front right, front center, LFE, back center, side left, side right
+ *  - 8ch: (aka 7.1): front left, front right, front center, LFE, back left, back right, side left, side right
+ *
+ * The ALSA default channel map is (see /usr/share/alsa/pcm/surround71.conf):
+ *  - front left, front right, back left, back right, front center, LFE,  side left, side right
+ *
+ * Hence, in case of the following source channel orders 3ch, 5ch, 6ch (aka
+ * 5.1), 7ch and 8ch the channel order has to be adapted
+ */
+
 template<typename V>
 struct TwoPointers {
 	V *dest;
@@ -44,17 +66,57 @@ struct TwoPointers {
 		return *this;
 	}
 
+	TwoPointers<V> &ToAlsa50() noexcept {
+		*dest++ = src[0]; // front left
+		*dest++ = src[1]; // front right
+		*dest++ = src[3]; // surround left
+		*dest++ = src[4]; // surround right
+		*dest++ = src[2]; // front center
+		src += 5;
+		return *this;
+	}
+
 	TwoPointers<V> &ToAlsa51() noexcept {
 		return CopyTwo() // left+right
 			.SwapTwoPairs(); // center, LFE, surround left+right
 	}
 
+	TwoPointers<V> &ToAlsa70() noexcept {
+		*dest++ = src[0]; // front left
+		*dest++ = src[1]; // front right
+		*dest++ = src[5]; // side left
+		*dest++ = src[6]; // side right
+		*dest++ = src[2]; // front center
+		*dest++ = src[3]; // LFE
+		*dest++ = src[4]; // back center
+		src += 7;
+		return *this;
+	}
+
 	TwoPointers<V> &ToAlsa71() noexcept {
 		return ToAlsa51()
 			.CopyTwo(); // side left+right
 	}
 };
 
+template<typename V>
+static void
+ToAlsaChannelOrder50(V *dest, const V *src, size_t n) noexcept
+{
+	TwoPointers<V> p{dest, src};
+	for (size_t i = 0; i != n; ++i)
+		p.ToAlsa50();
+}
+
+template<typename V>
+static inline ConstBuffer<V>
+ToAlsaChannelOrder50(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
+{
+	auto dest = buffer.GetT<V>(src.size);
+	ToAlsaChannelOrder50(dest, src.data, src.size / 5);
+	return { dest, src.size };
+}
+
 template<typename V>
 static void
 ToAlsaChannelOrder51(V *dest, const V *src, size_t n) noexcept
@@ -73,6 +135,24 @@ ToAlsaChannelOrder51(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
 	return { dest, src.size };
 }
 
+template<typename V>
+static void
+ToAlsaChannelOrder70(V *dest, const V *src, size_t n) noexcept
+{
+	TwoPointers<V> p{dest, src};
+	for (size_t i = 0; i != n; ++i)
+		p.ToAlsa70();
+}
+
+template<typename V>
+static inline ConstBuffer<V>
+ToAlsaChannelOrder70(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
+{
+	auto dest = buffer.GetT<V>(src.size);
+	ToAlsaChannelOrder70(dest, src.data, src.size / 7);
+	return { dest, src.size };
+}
+
 template<typename V>
 static void
 ToAlsaChannelOrder71(V *dest, const V *src, size_t n) noexcept
@@ -97,9 +177,15 @@ ToAlsaChannelOrderT(PcmBuffer &buffer, ConstBuffer<V> src,
 		    unsigned channels) noexcept
 {
 	switch (channels) {
+	case 5: // 5.0
+		return ToAlsaChannelOrder50(buffer, src);
+
 	case 6: // 5.1
 		return ToAlsaChannelOrder51(buffer, src);
 
+	case 7: // 7.0
+		return ToAlsaChannelOrder70(buffer, src);
+
 	case 8: // 7.1
 		return ToAlsaChannelOrder71(buffer, src);