From 257277903e23c3e4cb2565524b34f80b73ac20da Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <icculus@icculus.org>
Date: Tue, 19 Jul 2022 02:16:08 -0400
Subject: [PATCH] audio: first attempt at rewriting the channel converters.

This is not ready for production use!
---
 src/audio/SDL_audio_c.h  |    2 +-
 src/audio/SDL_audiocvt.c | 1580 ++++++++++++++++++++++++++------------
 2 files changed, 1109 insertions(+), 473 deletions(-)

diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h
index bfa0760de..3f22cd614 100644
--- a/src/audio/SDL_audio_c.h
+++ b/src/audio/SDL_audio_c.h
@@ -25,7 +25,7 @@
 #include "../SDL_internal.h"
 
 #ifndef DEBUG_CONVERT
-#define DEBUG_CONVERT 0
+#define DEBUG_CONVERT 1
 #endif
 
 #if DEBUG_CONVERT
diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c
index 0b95b417c..1117420e9 100644
--- a/src/audio/SDL_audiocvt.c
+++ b/src/audio/SDL_audiocvt.c
@@ -63,61 +63,41 @@
 # endif
 #endif
 
-#if HAVE_SSE3_INTRINSICS
-/* Convert from stereo to mono. Average left and right. */
-static void SDLCALL
-SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
-{
-    const __m128 divby2 = _mm_set1_ps(0.5f);
-    float *dst = (float *) cvt->buf;
-    const float *src = dst;
-    int i = cvt->len_cvt / 8;
+/*
+ * CHANNEL LAYOUTS AS SDL EXPECTS THEM:
+ *
+ * (Even if the platform expects something else later, that
+ * SDL will swizzle between the app and the platform).
+ *
+ * Abbreviations:
+ * - FRONT=single mono speaker
+ * - FL=front left speaker
+ * - FR=front right speaker
+ * - FC=front center speaker
+ * - BL=back left speaker
+ * - BR=back right speaker
+ * - SR=side right speaker
+ * - SL=side left speaker
+ * - BC=back center speaker
+ * - LFE=low-frequency speaker
+ *
+ * These are listed in the order they are laid out in
+ * memory, so "FL+FR" means "the front left speaker is
+ * layed out in memory first, then the front right, then
+ * it repeats for the next audio frame".
+ *
+ * 1 channel (mono) layout: FRONT
+ * 2 channels (stereo) layout: FL+FR
+ * 3 channels (2.1) layout: FL+FR+LFE
+ * 4 channels (quad) layout: FL+FR+BL+BR
+ * 5 channels (4.1) layout: FL+FR+LFE+BL+BR
+ * 6 channels (5.1) layout: FL+FR+FC+LFE+BL+BR
+ * 7 channels (6.1) layout: FL+FR+FC+LFE+BC+SL+SR
+ * 8 channels (7.1) layout: FL+FR+FC+LFE+BL+BR+SL+SR
+ */
 
-    LOG_DEBUG_CONVERT("stereo", "mono (using SSE3)");
-    SDL_assert(format == AUDIO_F32SYS);
-
-    /* Do SSE blocks as long as we have 16 bytes available.
-       Just use unaligned load/stores, if the memory at runtime is
-       aligned it'll be just as fast on modern processors */
-    while (i >= 4) {   /* 4 * float32 */
-        _mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_loadu_ps(src), _mm_loadu_ps(src+4)), divby2));
-        i -= 4; src += 8; dst += 4;
-    }
-
-    /* Finish off any leftovers with scalar operations. */
-    while (i) {
-        *dst = (src[0] + src[1]) * 0.5f;
-        dst++; i--; src += 2;
-    }
-
-    cvt->len_cvt /= 2;
-    if (cvt->filters[++cvt->filter_index]) {
-        cvt->filters[cvt->filter_index] (cvt, format);
-    }
-}
-#endif
-
-/* Convert from stereo to mono. Average left and right. */
-static void SDLCALL
-SDL_ConvertStereoToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
-{
-    float *dst = (float *) cvt->buf;
-    const float *src = dst;
-    int i;
-
-    LOG_DEBUG_CONVERT("stereo", "mono");
-    SDL_assert(format == AUDIO_F32SYS);
-
-    for (i = cvt->len_cvt / 8; i; --i, src += 2) {
-        *(dst++) = (src[0] + src[1]) * 0.5f;
-    }
-
-    cvt->len_cvt /= 2;
-    if (cvt->filters[++cvt->filter_index]) {
-        cvt->filters[cvt->filter_index] (cvt, format);
-    }
-}
 
+#if 0  /* !!! FIXME: these need to be updated to match the new scalar code. */
 #if HAVE_AVX_INTRINSICS
 /* MSVC will always accept AVX intrinsics when compiling for x64 */
 #if defined(__clang__) || defined(__GNUC__)
@@ -303,24 +283,147 @@ SDL_Convert51ToStereo_NEON(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     }
 }
 #endif
+#endif
 
-/* Convert from 5.1 to stereo. Average left and right, distribute center, discard LFE. */
+
+/* Channel conversion is now mostly following this scheme, borrowed from FNA
+   (which is following the scheme of XNA)...
+   https://github.com/FNA-XNA/FAudio/blob/master/src/matrix_defaults.inl */
+
+/* CONVERT FROM MONO... */
+/* Mono duplicates to stereo and all other channels are silenced. */
+
+#define CVT_MONO_TO(toname, tonamestr, num_channels, zeroingcode) \
+    static void SDLCALL SDL_ConvertMonoTo##toname(SDL_AudioCVT * cvt, SDL_AudioFormat format) { \
+        const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 1; \
+        float *dst = ((float *) (cvt->buf + cvt->len_cvt * num_channels)) - num_channels; \
+        int i; \
+        LOG_DEBUG_CONVERT("mono", tonamestr); \
+        SDL_assert(format == AUDIO_F32SYS); \
+        SDL_assert(num_channels >= 2); \
+        for (i = cvt->len_cvt / sizeof (float); i; i--, src--, dst -= num_channels) { \
+            dst[0] = dst[1] = *src; \
+            zeroingcode; \
+        } \
+        cvt->len_cvt *= num_channels; \
+        if (cvt->filters[++cvt->filter_index]) { \
+            cvt->filters[cvt->filter_index] (cvt, format); \
+        } \
+    }
+CVT_MONO_TO(Stereo, "stereo", 2, {});
+CVT_MONO_TO(21, "2.1", 3, { dst[2] = 0.0f; });
+CVT_MONO_TO(Quad, "quad", 4, { dst[2] = dst[3] = 0.0f; });
+CVT_MONO_TO(41, "4.1", 5, { dst[2] = dst[3] = dst[4] = 0.0f; });
+CVT_MONO_TO(51, "5.1", 6, { dst[2] = dst[3] = dst[4] = dst[5] = 0.0f; });
+CVT_MONO_TO(61, "6.1", 7, { dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = 0.0f; });
+CVT_MONO_TO(71, "7.1", 8, { dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = dst[7] = 0.0f; });
+#undef CVT_MONO_TO
+
+
+
+/* CONVERT FROM STEREO... */
+/* Stereo duplicates to two front speakers and all other channels are silenced. */
+
+#if HAVE_SSE3_INTRINSICS
+/* Convert from stereo to mono. Average left and right. */
 static void SDLCALL
-SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const __m128 divby2 = _mm_set1_ps(0.5f);
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i = cvt->len_cvt / 8;
+
+    LOG_DEBUG_CONVERT("stereo", "mono (using SSE3)");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    /* Do SSE blocks as long as we have 16 bytes available.
+       Just use unaligned load/stores, if the memory at runtime is
+       aligned it'll be just as fast on modern processors */
+    while (i >= 4) {   /* 4 * float32 */
+        _mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_loadu_ps(src), _mm_loadu_ps(src+4)), divby2));
+        i -= 4; src += 8; dst += 4;
+    }
+
+    /* Finish off any leftovers with scalar operations. */
+    while (i) {
+        *dst = (src[0] + src[1]) * 0.5f;
+        dst++; i--; src += 2;
+    }
+
+    cvt->len_cvt /= 2;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+#endif
+
+/* Convert from stereo to mono. Average left and right. */
+static void SDLCALL
+SDL_ConvertStereoToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
     float *dst = (float *) cvt->buf;
     const float *src = dst;
     int i;
-    const float two_fifths = 1.0f / 2.5f;
 
-    LOG_DEBUG_CONVERT("5.1", "stereo");
+    LOG_DEBUG_CONVERT("stereo", "mono");
     SDL_assert(format == AUDIO_F32SYS);
 
-    /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
-    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) {
-        const float front_center_distributed = src[2] * 0.5f;
-        dst[0] = (src[0] + front_center_distributed + src[4]) * two_fifths;  /* left */
-        dst[1] = (src[1] + front_center_distributed + src[5]) * two_fifths;  /* right */
+    for (i = cvt->len_cvt / (sizeof (float) * 2); i; --i, src += 2) {
+        *(dst++) = (src[0] + src[1]) * 0.5f;
+    }
+
+    cvt->len_cvt /= 2;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+#define CVT_STEREO_TO(toname, tonamestr, num_channels, zeroingcode) \
+    static void SDLCALL SDL_ConvertStereoTo##toname(SDL_AudioCVT * cvt, SDL_AudioFormat format) { \
+        int i; \
+        const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 2; \
+        float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 2) * num_channels))) - num_channels; \
+        LOG_DEBUG_CONVERT("stereo", tonamestr); \
+        SDL_assert(format == AUDIO_F32SYS); \
+        SDL_assert(num_channels >= 3); \
+        for (i = cvt->len_cvt / (sizeof (float) * 2); i; --i, dst -= num_channels, src -= 2) { \
+            dst[0] = src[0]; \
+            dst[1] = src[1]; \
+            zeroingcode; \
+        } \
+        cvt->len_cvt = (cvt->len_cvt / 2) * num_channels; \
+        if (cvt->filters[++cvt->filter_index]) { \
+            cvt->filters[cvt->filter_index] (cvt, format); \
+        } \
+    }
+
+CVT_STEREO_TO(21, "2.1", 3, { dst[2] = 0.0f; });
+CVT_STEREO_TO(Quad, "quad", 4, { dst[2] = dst[3] = 0.0f; });
+CVT_STEREO_TO(41, "4.1", 5, { dst[2] = dst[3] = dst[4] = 0.0f; });
+CVT_STEREO_TO(51, "5.1", 6, { dst[2] = dst[3] = dst[4] = dst[5] = 0.0f; });
+CVT_STEREO_TO(61, "6.1", 7, { dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = 0.0f; });
+CVT_STEREO_TO(71, "7.1", 8, { dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = dst[7] = 0.0f; });
+#undef CVT_STEREO_TO
+
+
+
+/* CONVERT FROM 2.1... */
+/* 2.1 duplicates to two front speakers (and LFE when available) and all other channels are silenced. */
+
+/* Convert from 2.1 to mono. Average left and right, drop LFE. */
+static void SDLCALL
+SDL_Convert21ToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("2.1", "mono");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 2); i; --i, src += 3) {
+        *(dst++) = (src[0] + src[1]) * 0.5f;
     }
 
     cvt->len_cvt /= 3;
@@ -329,8 +432,63 @@ SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     }
 }
 
+#define CVT_21_TO(toname, tonamestr, num_channels, customcode) \
+    static void SDLCALL SDL_Convert21To##toname(SDL_AudioCVT * cvt, SDL_AudioFormat format) { \
+        int i; \
+        float lf, rf, lfe; \
+        const float *src = (const float *) (cvt->buf + cvt->len_cvt); \
+        float *dst = (float *) (cvt->buf + ((cvt->len_cvt / 3) * num_channels)); \
+        LOG_DEBUG_CONVERT("2.1", tonamestr); \
+        SDL_assert(format == AUDIO_F32SYS); \
+        SDL_assert(num_channels >= 2); \
+        for (i = cvt->len_cvt / (sizeof (float) * 3); i; --i) { \
+            dst -= num_channels; \
+            src -= 2; \
+            lf = src[0]; \
+            rf = src[1]; \
+            lfe = src[2]; \
+            dst[0] = lf; \
+            dst[1] = rf; \
+            customcode; \
+        } \
+        cvt->len_cvt = (cvt->len_cvt / 3) * num_channels; \
+        if (cvt->filters[++cvt->filter_index]) { \
+            cvt->filters[cvt->filter_index] (cvt, format); \
+        } \
+    }
+
+CVT_21_TO(Stereo, "stereo", 2, { (void) lfe; });
+CVT_21_TO(Quad, "quad", 4, { (void) lfe; dst[2] = dst[3] = 0.0f; });
+CVT_21_TO(41, "4.1", 5, { dst[2] = lfe; dst[3] = dst[4] = 0.0f; });
+CVT_21_TO(51, "5.1", 6, { dst[2] = 0.0f; dst[3] = lfe; dst[4] = dst[5] = 0.0f; });
+CVT_21_TO(61, "6.1", 7, { dst[2] = 0.0f; dst[3] = lfe; dst[4] = dst[5] = dst[6] = 0.0f; });
+CVT_21_TO(71, "7.1", 8, { dst[2] = 0.0f; dst[3] = lfe; dst[4] = dst[5] = dst[6] = dst[7] = 0.0f; });
+#undef CVT_21_TO
+
+
+/* CONVERT FROM QUAD... */
+
+static void SDLCALL
+SDL_ConvertQuadToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("quad", "mono");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    /* !!! FIXME: could benefit from SIMD */
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4) {
+        *(dst++) = (src[0] + src[1] + src[3] + src[4]) * 0.25f;
+    }
+
+    cvt->len_cvt /= 4;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
 
-/* Convert from quad to stereo. Average left and right. */
 static void SDLCALL
 SDL_ConvertQuadToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -341,142 +499,685 @@ SDL_ConvertQuadToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     LOG_DEBUG_CONVERT("quad", "stereo");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4, dst += 2) {
-        dst[0] = (src[0] + src[2]) * 0.5f; /* left */
-        dst[1] = (src[1] + src[3]) * 0.5f; /* right */
+    /* !!! FIXME: could benefit from SIMD */
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float bl = src[2];
+        const float br = src[3];
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right)...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.421000004f) + (bl * 0.358999997f) + (br * 0.219999999f);
+        *(dst++) = (fr * 0.421000004f) + (br * 0.358999997f) + (bl * 0.219999999f);
     }
 
-    cvt->len_cvt /= 2;
+    cvt->len_cvt = (cvt->len_cvt / 4) * 2;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-
-/* Convert from 7.1 to 5.1. Distribute sides across front and back. */
 static void SDLCALL
-SDL_Convert71To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
-{
-    float *dst = (float *) cvt->buf;
-    const float *src = dst;
-    int i;
-    const float two_thirds = 1.0f / 1.5f;
-
-    LOG_DEBUG_CONVERT("7.1", "5.1");
-    SDL_assert(format == AUDIO_F32SYS);
-
-    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 6) {
-        const float surround_left_distributed = src[6] * 0.5f;
-        const float surround_right_distributed = src[7] * 0.5f;
-        dst[0] = (src[0] + surround_left_distributed) * two_thirds;  /* FL */
-        dst[1] = (src[1] + surround_right_distributed) * two_thirds; /* FR */
-        dst[2] = src[2] * two_thirds; /* CC */
-        dst[3] = src[3] * two_thirds; /* LFE */
-        dst[4] = (src[4] + surround_left_distributed) * two_thirds;  /* BL */
-        dst[5] = (src[5] + surround_right_distributed) * two_thirds; /* BR */
-    }
-
-    cvt->len_cvt /= 8;
-    cvt->len_cvt *= 6;
-    if (cvt->filters[++cvt->filter_index]) {
-        cvt->filters[cvt->filter_index] (cvt, format);
-    }
-}
-
-/* Convert from 7.1 to 6.1 */
-/* SDL's 6.1 layout: LFE+FC+FR+SR+BackSurround+SL+FL */
-/* SDL's 7.1 layout: FL+FR+FC+LFE+BL+BR+SL+SR */
-static void SDLCALL
-SDL_Convert71To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_ConvertQuadTo21(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
     float *dst = (float *) cvt->buf;
     const float *src = dst;
     int i;
 
-    LOG_DEBUG_CONVERT("7.1", "6.1");
+    LOG_DEBUG_CONVERT("quad", "2.1");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 7) {
-        dst[0] = src[3]; /* LFE */
-        dst[1] = src[2]; /* FC */
-        dst[2] = src[1]; /* FR */
-        dst[3] = src[7]; /* SR */
-        dst[4] = (src[4] + src[5]) / 0.2f;  /* BackSurround */
-        dst[5] = src[6]; /* SL */
-        dst[6] = src[0]; /* FL */
+    /* !!! FIXME: could benefit from SIMD */
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float bl = src[2];
+        const float br = src[3];
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right)...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.421000004f) + (bl * 0.358999997f) + (br * 0.219999999f);
+        *(dst++) = (fr * 0.421000004f) + (br * 0.358999997f) + (bl * 0.219999999f);
+        *(dst++) = 0.0f;  /* lfe */
     }
 
-    cvt->len_cvt /= 8;
-    cvt->len_cvt *= 7;
+    cvt->len_cvt = (cvt->len_cvt / 4) * 3;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-/* Convert from 6.1 to 7.1 */
-/* SDL's 6.1 layout: LFE+FC+FR+SR+BackSurround+SL+FL */
-/* SDL's 7.1 layout: FL+FR+FC+LFE+BL+BR+SL+SR */
 static void SDLCALL
-SDL_Convert61To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_ConvertQuadTo41(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 4;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 4) * 5))) - 5;
+    int i;
+
+    LOG_DEBUG_CONVERT("quad", "4.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src -= 4, dst -= 5) {
+        dst[4] = src[3];
+        dst[3] = src[2];
+        dst[2] = 0.0f;  /* LFE */
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 4) * 5;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_ConvertQuadTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 4;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 4) * 6))) - 6;
+    int i;
+
+    LOG_DEBUG_CONVERT("quad", "5.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src -= 4, dst -= 6) {
+        dst[5] = src[3];
+        dst[4] = src[2];
+        dst[3] = 0.0f;  /* LFE */
+        dst[2] = 0.0f;  /* FC */
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 4) * 6;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_ConvertQuadTo61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 4;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 4) * 7))) - 7;
+    int i;
+
+    LOG_DEBUG_CONVERT("quad", "6.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    /* !!! FIXME: I'm skeptical XNA/FNA's conversion is right, here. */
+
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src -= 4, dst -= 7) {
+        const float bl = src[2];
+        const float br = src[3];
+        dst[6] = br * 0.796000004f;
+        dst[5] = bl * 0.796000004f;
+        dst[4] = (bl + br) * 0.5f;  /* average BL+BR to BC */
+        dst[3] = 0.0f;  /* LFE */
+        dst[2] = 0.0f;  /* FC */
+        dst[1] = src[1] * 0.939999998f;
+        dst[0] = src[0] * 0.939999998f;
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 4) * 7;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_ConvertQuadTo71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 4;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 4) * 8))) - 8;
+    int i;
+
+    LOG_DEBUG_CONVERT("quad", "7.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src -= 4, dst -= 8) {
+        dst[7] = 0.0f;  /* SR */
+        dst[6] = 0.0f;  /* SL */
+        dst[5] = src[3];
+        dst[4] = src[2];
+        dst[3] = 0.0f;  /* LFE */
+        dst[2] = 0.0f;  /* FC */
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 4) * 8;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+
+/* CONVERT FROM 4.1... */
+
+static void SDLCALL
+SDL_Convert41ToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
     float *dst = (float *) cvt->buf;
     const float *src = dst;
     int i;
 
-    LOG_DEBUG_CONVERT("6.1", "7.1");
+    LOG_DEBUG_CONVERT("4.1", "mono");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7, dst += 8) {
-        dst[0] = src[6]; /* FL */
-        dst[1] = src[2]; /* FR */
-        dst[2] = src[1]; /* FC */
-        dst[3] = src[0]; /* LFE */
-        dst[4] = src[4]; /* BL */
-        dst[5] = src[4]; /* BR */
-        dst[6] = src[5]; /* SL */
-        dst[7] = src[3]; /* SR */
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src += 5) {
+        *(dst++) = (src[0] + src[1] + src[3] + src[4]) * 0.25f;
     }
 
-    cvt->len_cvt /= 7;
-    cvt->len_cvt *= 8;
+    cvt->len_cvt /= 5;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert41ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("4.1", "stereo");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src += 5) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float bl = src[3];
+        const float br = src[4];
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.374222219f) + (bl * 0.319111109f) + (br * 0.195555553f);
+        *(dst++) = (fr * 0.374222219f) + (br * 0.319111109f) + (bl * 0.195555553f);
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 5) * 2;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert41To21(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("4.1", "2.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src += 5) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float lfe = src[2];
+        const float bl = src[3];
+        const float br = src[4];
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.374222219f) + (bl * 0.319111109f) + (br * 0.195555553f);
+        *(dst++) = (fr * 0.374222219f) + (br * 0.319111109f) + (bl * 0.195555553f);
+        *(dst++) = lfe;
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 5) * 3;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert41ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("4.1", "quad");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src += 5) {
+        /* !!! FIXME: FNA/XNA mixes a little of the LFE into every channel...but this can't possibly be right, right...? I just drop the LFE and copy the channels. */
+        *(dst++) = src[0];
+        *(dst++) = src[1];
+        *(dst++) = src[3];
+        *(dst++) = src[4];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 5) * 4;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert41To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 5;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 5) * 6))) - 6;
+    int i;
+
+    LOG_DEBUG_CONVERT("4.1", "5.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src -= 5, dst -= 6) {
+        dst[5] = src[4];
+        dst[4] = src[3];
+        dst[3] = src[2];
+        dst[2] = 0.0f;  /* FC */
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 5) * 6;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert41To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 5;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 4) * 7))) - 7;
+    int i;
+
+    LOG_DEBUG_CONVERT("4.1", "6.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    /* !!! FIXME: I'm skeptical XNA/FNA's conversion is right, here. */
+
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src -= 5, dst -= 7) {
+        const float bl = src[3];
+        const float br = src[4];
+        dst[6] = br * 0.796000004f;
+        dst[5] = bl * 0.796000004f;
+        dst[4] = (bl + br) * 0.5f;  /* average BL+BR to BC */
+        dst[3] = src[2];
+        dst[2] = 0.0f;  /* FC */
+        dst[1] = src[1] * 0.939999998f;
+        dst[0] = src[0] * 0.939999998f;
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 5) * 7;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert41To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 5;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 5) * 8))) - 8;
+    int i;
+
+    LOG_DEBUG_CONVERT("4.1", "7.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 5); i; --i, src -= 5, dst -= 8) {
+        dst[7] = 0.0f;  /* SR */
+        dst[6] = 0.0f;  /* SL */
+        dst[5] = src[4];
+        dst[4] = src[3];
+        dst[3] = src[2];
+        dst[2] = 0.0f;  /* FC */
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 5) * 8;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+
+
+/* CONVERT FROM 5.1... */
+
+static void SDLCALL
+SDL_Convert51ToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("5.1", "mono");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6) {
+        *(dst++) = (src[0] + src[1] + src[2] + src[4] + src[5]) * 0.200000003f;
+    }
+
+    cvt->len_cvt /= 6;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("5.1", "stereo");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float bl = src[4];
+        const float br = src[5];
+        const float extra = 0.090909094f / 4.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * (0.294545442f+extra)) + (fc * (0.208181813f+extra)) + (bl * (0.251818180f+extra)) + (br * (0.154545456f+extra));
+        *(dst++) = (fr * (0.294545442f+extra)) + (fc * (0.208181813f+extra)) + (br * (0.251818180f+extra)) + (bl * (0.154545456f+extra));
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 6) * 2;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert51To21(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("5.1", "2.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bl = src[4];
+        const float br = src[5];
+
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.324000001f) + (fc * 0.229000002f) + (bl * 0.277000010f) + (br * 0.170000002f);
+        *(dst++) = (fr * 0.324000001f) + (fc * 0.229000002f) + (br * 0.277000010f) + (bl * 0.170000002f);
+        *(dst++) = lfe;
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 6) * 3;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert51ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("5.1", "quad");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float bl = src[4];
+        const float br = src[5];
+        const float extra = 0.047619049f / 2.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+        *(dst++) = (fl * (0.558095276f+extra)) + (fc * (0.394285709f+extra));
+        *(dst++) = (fr * (0.558095276f+extra)) + (fc * (0.394285709f+extra));
+        *(dst++) = bl;  /* !!! FIXME: XNA/FNA quiets the back speakers here to ~58%, but I'm copying them through. Not sure why they do it like that. */
+        *(dst++) = br;  /* !!! FIXME: XNA/FNA quiets the back speakers here to ~58%, but I'm copying them through. Not sure why they do it like that. */
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 6) * 4;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert51To41(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("5.1", "4.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bl = src[4];
+        const float br = src[5];
+        *(dst++) = (fl * 0.586000025f) + (fc * 0.414000005f);
+        *(dst++) = (fr * 0.586000025f) + (fc * 0.414000005f);
+        *(dst++) = lfe;
+        *(dst++) = bl;  /* !!! FIXME: XNA/FNA quiets the back speakers here to ~58%, but I'm copying them through. Not sure why they do it like that. */
+        *(dst++) = br;  /* !!! FIXME: XNA/FNA quiets the back speakers here to ~58%, but I'm copying them through. Not sure why they do it like that. */
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 6) * 5;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-/* Convert from 5.1 to 6.1 */
-/* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
-/* SDL's 6.1 layout: LFE+FC+FR+SR+BackSurround+SL+FL */
 static void SDLCALL
 SDL_Convert51To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
-    float *dst = (float *) cvt->buf;
-    const float *src = dst;
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 6;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 6) * 7))) - 7;
     int i;
 
     LOG_DEBUG_CONVERT("5.1", "6.1");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 7) {
-        dst[0] = src[3]; /* LFE */
-        dst[1] = src[2]; /* FC */
-        dst[2] = src[1]; /* FR */
-        dst[3] = src[5]; /* SR */
-        dst[4] = (src[4] + src[5]) / 0.2f;  /* BackSurround */
-        dst[5] = src[4]; /* SL */
-        dst[6] = src[0]; /* FL */
+    /* !!! FIXME: I'm skeptical XNA/FNA's conversion is right, here. Why is it quieting the back speakers instead of copying them through as-is? */
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src -= 6, dst -= 7) {
+        const float bl = src[4];
+        const float br = src[5];
+        dst[6] = br * 0.796000004f;
+        dst[5] = bl * 0.796000004f;
+        dst[4] = (bl + br) * 0.5f;  /* average BL+BR to BC */
+        dst[3] = src[3];
+        dst[2] = src[2] * 0.939999998f;
+        dst[1] = src[1] * 0.939999998f;
+        dst[0] = src[0] * 0.939999998f;
     }
 
-    cvt->len_cvt /= 6;
-    cvt->len_cvt *= 7;
+    cvt->len_cvt = (cvt->len_cvt / 6) * 7;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 6;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 6) * 8))) - 8;
+    int i;
+
+    LOG_DEBUG_CONVERT("5.1", "7.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src -= 6, dst -= 8) {
+        dst[7] = 0.0f;  /* SR */
+        dst[6] = 0.0f;  /* SL */
+        dst[5] = src[5];
+        dst[4] = src[4];
+        dst[3] = src[3];
+        dst[2] = src[2];
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 6) * 8;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+
+
+/* CONVERT FROM 6.1... */
+
+static void SDLCALL
+SDL_Convert61ToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("6.1", "mono");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7) {
+        *(dst++) = (src[0] + src[1] + src[2] + src[4] + src[5] + src[6]) * 0.166666672f;
+    }
+
+    cvt->len_cvt /= 7;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert61ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("6.1", "stereo");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float bc = src[4];
+        const float sl = src[5];
+        const float sr = src[6];
+        const float extra = 0.076923080f / 5.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * (0.247384623f+extra)) + (fc * (0.174461529f+extra)) + (bc * (0.174461529f+extra)) + (sl * (0.226153851f+extra)) + (sr * (0.100615382f+extra));
+        *(dst++) = (fr * (0.247384623f+extra)) + (fc * (0.174461529f+extra)) + (bc * (0.174461529f+extra)) + (sr * (0.226153851f+extra)) + (sl * (0.100615382f+extra));
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 7) * 2;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert61To21(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("6.1", "2.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bc = src[4];
+        const float sl = src[5];
+        const float sr = src[6];
+
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.247384623f) + (fc * 0.174461529f) + (bc * 0.174461529f) + (sl * 0.226153851f) + (sr * 0.100615382f);
+        *(dst++) = (fr * 0.247384623f) + (fc * 0.174461529f) + (bc * 0.174461529f) + (sr * 0.226153851f) + (sl * 0.100615382f);
+        *(dst++) = lfe;
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 7) * 3;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert61ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("6.1", "quad");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float bc = src[4];
+        const float sl = src[5];
+        const float sr = src[6];
+        const float extra = 0.040000003f / 3.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+        const float extra2 = 0.040000003f / 2.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+        *(dst++) = (fl * (0.463679999f+extra)) + (fc * (0.327360004f+extra)) + (sl * (0.168960005f+extra));
+        *(dst++) = (fr * (0.463679999f+extra)) + (fc * (0.327360004f+extra)) + (sr * (0.168960005f+extra));
+        *(dst++) = (bc * (0.327360004f+extra2)) + (sl * (0.431039989f+extra2));
+        *(dst++) = (bc * (0.327360004f+extra2)) + (sr * (0.431039989f+extra2));
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 7) * 4;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert61To41(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("6.1", "4.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bc = src[4];
+        const float sl = src[5];
+        const float sr = src[6];
+        *(dst++) = (fl * 0.483000010f) + (fc * 0.340999991f) + (sl * 0.175999999f);
+        *(dst++) = (fr * 0.483000010f) + (fc * 0.340999991f) + (sr * 0.175999999f);
+        *(dst++) = lfe;
+        *(dst++) = (bc * 0.340999991f) + (sl * 0.449000001f);
+        *(dst++) = (bc * 0.340999991f) + (sr * 0.449000001f);
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 7) * 5;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-/* Convert from 6.1 to 5.1 */
-/* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
-/* SDL's 6.1 layout: LFE+FC+FR+SR+BackSurround+SL+FL */
 static void SDLCALL
 SDL_Convert61To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -487,220 +1188,292 @@ SDL_Convert61To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     LOG_DEBUG_CONVERT("6.1", "5.1");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7, dst += 6) {
-        dst[0] = src[6]; /* FL */
-        dst[1] = src[2]; /* FR */
-        dst[2] = src[1]; /* FC */
-        dst[3] = src[0]; /* LFE */
-        dst[4] = src[5]; /* BL */
-        dst[5] = src[3]; /* BR */
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bc = src[4];
+        const float sl = src[5];
+        const float sr = src[6];
+        /* !!! FIXME: XNA/FNA quiets the front speakers a bunch, but leaves the back speakers at about the same volume. I'm not sure that's right. */
+        *(dst++) = (fl * 0.611000001f) + (sl * 0.223000005f);
+        *(dst++) = (fr * 0.611000001f) + (sr * 0.223000005f);
+        *(dst++) = (fc * 0.611000001f);  /* !!! FIXME: XNA/FNA silence the FC speaker to ~61%, but I'm not sure this is right. */
+        *(dst++) = lfe;
+        *(dst++) = (bc * 0.432000011f) + (sl * 0.568000019f);
+        *(dst++) = (bc * 0.432000011f) + (sr * 0.568000019f);
     }
 
-    cvt->len_cvt /= 7;
-    cvt->len_cvt *= 6;
+    cvt->len_cvt = (cvt->len_cvt / 7) * 6;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-/* Convert from 5.1 to quad. Distribute center across front, discard LFE. */
 static void SDLCALL
-SDL_Convert51ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_Convert61To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    const float *src = ((const float *) (cvt->buf + cvt->len_cvt)) - 7;
+    float *dst = ((float *) (cvt->buf + ((cvt->len_cvt / 7) * 8))) - 8;
+    int i;
+
+    LOG_DEBUG_CONVERT("6.1", "7.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src -= 7, dst -= 8) {
+        const float bc = src[4];
+        dst[7] = src[6];
+        dst[6] = src[5];
+        dst[5] = (bc * 0.707000017f);
+        dst[4] = (bc * 0.707000017f);
+        dst[3] = src[3];
+        dst[2] = src[2];
+        dst[1] = src[1];
+        dst[0] = src[0];
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 7) * 8;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+
+/* CONVERT FROM 7.1... */
+
+static void SDLCALL
+SDL_Convert71ToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
     float *dst = (float *) cvt->buf;
     const float *src = dst;
     int i;
-    const float two_thirds = 1.0f / 1.5f;
 
-    LOG_DEBUG_CONVERT("5.1", "quad");
+    LOG_DEBUG_CONVERT("7.1", "mono");
     SDL_assert(format == AUDIO_F32SYS);
 
-    /* SDL's 4.0 layout: FL+FR+BL+BR */
-    /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
-    for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) {
-        const float front_center_distributed = src[2] * 0.5f;
-        dst[0] = (src[0] + front_center_distributed) * two_thirds;  /* FL */
-        dst[1] = (src[1] + front_center_distributed) * two_thirds;  /* FR */
-        dst[2] = src[4] * two_thirds;  /* BL */
-        dst[3] = src[5] * two_thirds;  /* BR */
+    /* !!! FIXME: we can probably SIMD this. */
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        *(dst++) = (src[0] + src[1] + src[2] + src[4] + src[5] + src[6] + src[7]) * 0.143142849f;
     }
 
-    cvt->len_cvt /= 6;
-    cvt->len_cvt *= 4;
+    cvt->len_cvt /= 8;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-
-/* Upmix mono to stereo (by duplication) */
 static void SDLCALL
-SDL_ConvertMonoToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_Convert71ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
-    const float *src = (const float *) (cvt->buf + cvt->len_cvt);
-    float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
     int i;
 
-    LOG_DEBUG_CONVERT("mono", "stereo");
+    LOG_DEBUG_CONVERT("7.1", "stereo");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / sizeof (float); i; --i) {
-        src--;
-        dst -= 2;
-        dst[0] = dst[1] = *src;
+    /* !!! FIXME: we can probably SIMD this. */
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float bl = src[4];
+        const float br = src[5];
+        const float sl = src[6];
+        const float sr = src[7];
+        const float extra = 0.066666670f / 6.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * (0.211866662f+extra)) + (fc * (0.150266662f+extra)) + (bl * (0.181066677f+extra)) + (br * (0.111066669f+extra)) + (sl * (0.194133341f+extra)) + (sr * (0.085866667f+extra));
+        *(dst++) = (fr * (0.211866662f+extra)) + (fc * (0.150266662f+extra)) + (br * (0.181066677f+extra)) + (bl * (0.111066669f+extra)) + (sr * (0.194133341f+extra)) + (sl * (0.085866667f+extra));
     }
 
-    cvt->len_cvt *= 2;
+    cvt->len_cvt = (cvt->len_cvt / 8) * 2;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-
-/* Upmix stereo to a pseudo-5.1 stream */
 static void SDLCALL
-SDL_ConvertStereoTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_Convert71To21(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
-    int i;
-    float lf, rf, ce;
-    const float *src = (const float *) (cvt->buf + cvt->len_cvt);
-    float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
-
-    LOG_DEBUG_CONVERT("stereo", "5.1");
-    SDL_assert(format == AUDIO_F32SYS);
-
-    for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
-        dst -= 6;
-        src -= 2;
-        lf = src[0];
-        rf = src[1];
-        ce = (lf + rf) * 0.5f;
-        /* Constant 0.571f is approx 4/7 not to saturate */
-        dst[0] = 0.571f * (lf + (lf - 0.5f * ce));  /* FL */
-        dst[1] = 0.571f * (rf + (rf - 0.5f * ce));  /* FR */
-        dst[2] = ce;  /* FC */
-        dst[3] = 0;   /* LFE (only meant for special LFE effects) */
-        dst[4] = lf;  /* BL */
-        dst[5] = rf;  /* BR */
-    }
-
-    cvt->len_cvt *= 3;
-    if (cvt->filters[++cvt->filter_index]) {
-        cvt->filters[cvt->filter_index] (cvt, format);
-    }
-}
-
-
-/* Upmix quad to a pseudo-5.1 stream */
-static void SDLCALL
-SDL_ConvertQuadTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
-{
-    int i;
-    float lf, rf, lb, rb, ce;
-    const float *src = (const float *) (cvt->buf + cvt->len_cvt);
-    float *dst = (float *) (cvt->buf + cvt->len_cvt * 3 / 2);
-
-    LOG_DEBUG_CONVERT("quad", "5.1");
-    SDL_assert(format == AUDIO_F32SYS);
-    SDL_assert(cvt->len_cvt % (sizeof(float) * 4) == 0);
-
-    for (i = cvt->len_cvt / (sizeof(float) * 4); i; --i) {
-        dst -= 6;
-        src -= 4;
-        lf = src[0];
-        rf = src[1];
-        lb = src[2];
-        rb = src[3];
-        ce = (lf + rf) * 0.5f;
-        /* Constant 0.571f is approx 4/7 not to saturate */
-        dst[0] = 0.571f * (lf + (lf - 0.5f * ce)); /* FL */
-        dst[1] = 0.571f * (rf + (rf - 0.5f * ce)); /* FR */
-        dst[2] = ce;  /* FC */
-        dst[3] = 0;   /* LFE (only meant for special LFE effects) */
-        dst[4] = lb;  /* BL */
-        dst[5] = rb;  /* BR */
-    }
-
-    cvt->len_cvt = cvt->len_cvt * 3 / 2;
-    if (cvt->filters[++cvt->filter_index]) {
-        cvt->filters[cvt->filter_index] (cvt, format);
-    }
-}
-
-
-/* Upmix stereo to a pseudo-4.0 stream (by duplication) */
-static void SDLCALL
-SDL_ConvertStereoToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
-{
-    const float *src = (const float *) (cvt->buf + cvt->len_cvt);
-    float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
-    float lf, rf;
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
     int i;
 
-    LOG_DEBUG_CONVERT("stereo", "quad");
+    LOG_DEBUG_CONVERT("7.1", "2.1");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
-        dst -= 4;
-        src -= 2;
-        lf = src[0];
-        rf = src[1];
-        dst[0] = lf;  /* FL */
-        dst[1] = rf;  /* FR */
-        dst[2] = lf;  /* BL */
-        dst[3] = rf;  /* BR */
+    /* !!! FIXME: we can probably SIMD this. */
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bl = src[4];
+        const float br = src[5];
+        const float sl = src[6];
+        const float sr = src[7];
+
+        /* !!! FIXME: FNA/XNA mixes a little of the back right into the left (and back left into the right) and a little of the LFE...but this can't possibly be right, right...? */
+        *(dst++) = (fl * 0.211866662f) + (fc * 0.150266662f) + (bl * 0.181066677f) + (br * 0.111066669f) + (sl * 0.194133341f) + (sr * 0.085866667f);
+        *(dst++) = (fr * 0.211866662f) + (fc * 0.150266662f) + (br * 0.181066677f) + (bl * 0.111066669f) + (sr * 0.194133341f) + (sl * 0.085866667f);
+        *(dst++) = lfe;
     }
 
-    cvt->len_cvt *= 2;
+    cvt->len_cvt = (cvt->len_cvt / 8) * 3;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
-
-/* Upmix 5.1 to 7.1 */
 static void SDLCALL
-SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+SDL_Convert71ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
-    float lf, rf, lb, rb, ls, rs;
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
     int i;
-    const float *src = (const float *) (cvt->buf + cvt->len_cvt);
-    float *dst = (float *) (cvt->buf + cvt->len_cvt * 4 / 3);
 
-    LOG_DEBUG_CONVERT("5.1", "7.1");
+    LOG_DEBUG_CONVERT("7.1", "quad");
     SDL_assert(format == AUDIO_F32SYS);
-    SDL_assert(cvt->len_cvt % (sizeof(float) * 6) == 0);
 
-    for (i = cvt->len_cvt / (sizeof(float) * 6); i; --i) {
-        dst -= 8;
-        src -= 6;
-        lf = src[0];
-        rf = src[1];
-        lb = src[4];
-        rb = src[5];
-        ls = (lf + lb) * 0.5f;
-        rs = (rf + rb) * 0.5f;
-        lf += lf - ls;
-        rf += rf - rs;
-        lb += lb - ls;
-        rb += rb - rs;
-        dst[3] = src[3];  /* LFE */
-        dst[2] = src[2];  /* FC */
-        dst[7] = rs; /* SR */
-        dst[6] = ls; /* SL */
-        dst[5] = 0.5f * rb;  /* BR */
-        dst[4] = 0.5f * lb;  /* BL */
-        dst[1] = 0.5f * rf;  /* FR */
-        dst[0] = 0.5f * lf;  /* FL */
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float bl = src[4];
+        const float br = src[5];
+        const float sl = src[6];
+        const float sr = src[7];
+        const float extra = 0.034482758f / 3.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+        const float extra2 = 0.034482758f / 2.0f;  /* this was the LFE distribution, we'll just split it between the other channels for now. */
+        *(dst++) = (fl * (0.466344833f+extra)) + (fc * (0.329241365f+extra)) + (sl * (0.169931039f+extra));
+        *(dst++) = (fr * (0.466344833f+extra)) + (fc * (0.329241365f+extra)) + (sr * (0.169931039f+extra));
+        *(dst++) = (bl * (0.466344833f+extra2)) + (sl * (0.433517247f+extra2));
+        *(dst++) = (br * (0.466344833f+extra2)) + (sr * (0.433517247f+extra2));
     }
 
-    cvt->len_cvt = cvt->len_cvt * 4 / 3;
-
+    cvt->len_cvt = (cvt->len_cvt / 8) * 4;
     if (cvt->filters[++cvt->filter_index]) {
         cvt->filters[cvt->filter_index] (cvt, format);
     }
 }
 
+static void SDLCALL
+SDL_Convert71To41(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("7.1", "4.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bl = src[4];
+        const float br = src[5];
+        const float sl = src[6];
+        const float sr = src[7];
+        *(dst++) = (fl * 0.483000010f) + (fc * 0.340999991f) + (sl * 0.175999999f);
+        *(dst++) = (fr * 0.483000010f) + (fc * 0.340999991f) + (sr * 0.175999999f);
+        *(dst++) = lfe;
+        *(dst++) = (bl * 0.483000010f) + (sl * 0.449000001f);
+        *(dst++) = (br * 0.483000010f) + (sr * 0.449000001f);
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 8) * 5;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert71To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("7.1", "5.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bl = src[4];
+        const float br = src[5];
+        const float sl = src[6];
+        const float sr = src[7];
+        /* !!! FIXME: XNA/FNA quiets the front speakers a bunch, but leaves the back speakers at about the same volume. I'm not sure that's right. */
+        *(dst++) = (fl * 0.518000007f) + (sl * 0.188999996f);
+        *(dst++) = (fr * 0.518000007f) + (sr * 0.188999996f);
+        *(dst++) = (fc * 0.518000007f);  /* !!! FIXME: XNA/FNA silence the FC speaker to ~51%, but I'm not sure this is right. */
+        *(dst++) = lfe;
+        *(dst++) = (bl * 0.518000007f) + (sl * 0.188999996f);
+        *(dst++) = (br * 0.518000007f) + (sr * 0.188999996f);
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 8) * 6;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static void SDLCALL
+SDL_Convert71To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    LOG_DEBUG_CONVERT("7.1", "6.1");
+    SDL_assert(format == AUDIO_F32SYS);
+
+    for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8) {
+        const float fl = src[0];
+        const float fr = src[1];
+        const float fc = src[2];
+        const float lfe = src[3];
+        const float bl = src[4];
+        const float br = src[5];
+        const float sl = src[6];
+        const float sr = src[7];
+        /* !!! FIXME: XNA/FNA quiets the front speakers a bunch, but leaves the back speakers at about the same volume. I'm not sure that's right. */
+        *(dst++) = (fl * 0.541000009f);
+        *(dst++) = (fr * 0.541000009f);
+        *(dst++) = (fc * 0.541000009f);  /* !!! FIXME: XNA/FNA silence the FC speaker to ~61%, but I'm not sure this is right. */
+        *(dst++) = lfe;
+        *(dst++) = (bl * 0.287999988f) + (br * 0.287999988f);
+        *(dst++) = (bl * 0.458999991f) + (sl * 0.541000009f);
+        *(dst++) = (br * 0.458999991f) + (sr * 0.541000009f);
+    }
+
+    cvt->len_cvt = (cvt->len_cvt / 8) * 6;
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+static const SDL_AudioFilter channel_converters[8][8] = {   /* from][to] */
+    { NULL, SDL_ConvertMonoToStereo, SDL_ConvertMonoTo21, SDL_ConvertMonoToQuad, SDL_ConvertMonoTo41, SDL_ConvertMonoTo51, SDL_ConvertMonoTo61, SDL_ConvertMonoTo71 },
+    { SDL_ConvertStereoToMono, NULL, SDL_ConvertStereoTo21, SDL_ConvertStereoToQuad, SDL_ConvertStereoTo41, SDL_ConvertStereoTo51, SDL_ConvertStereoTo61, SDL_ConvertStereoTo71 },
+    { SDL_Convert21ToMono, SDL_Convert21ToStereo, NULL, SDL_Convert21ToQuad, SDL_Convert21To41, SDL_Convert21To51, SDL_Convert21To61, SDL_Convert21To71 },
+    { SDL_ConvertQuadToMono, SDL_ConvertQuadToStereo, SDL_ConvertQuadTo21, NULL, SDL_ConvertQuadTo41, SDL_ConvertQuadTo51, SDL_ConvertQuadTo61, SDL_ConvertQuadTo71 },
+    { SDL_Convert41ToMono, SDL_Convert41ToStereo, SDL_Convert41To21, SDL_Convert41ToQuad, NULL, SDL_Convert41To51, SDL_Convert41To61, SDL_Convert41To71 },
+    { SDL_Convert51ToMono, SDL_Convert51ToStereo, SDL_Convert51To21, SDL_Convert51ToQuad, SDL_Convert51To41, NULL, SDL_Convert51To61, SDL_Convert51To71 },
+    { SDL_Convert61ToMono, SDL_Convert61ToStereo, SDL_Convert61To21, SDL_Convert61ToQuad, SDL_Convert61To41, SDL_Convert61To51, NULL, SDL_Convert61To71 },
+    { SDL_Convert71ToMono, SDL_Convert71ToStereo, SDL_Convert71To21, SDL_Convert71ToQuad, SDL_Convert71To41, SDL_Convert71To51, SDL_Convert71To61, NULL }
+};
+
+
+
 /* SDL's resampler uses a "bandlimited interpolation" algorithm:
      https://ccrma.stanford.edu/~jos/resample/ */
 
@@ -1093,20 +1866,7 @@ SDL_SupportedAudioFormat(const SDL_AudioFormat fmt)
 static SDL_bool
 SDL_SupportedChannelCount(const int channels)
 {
-    switch (channels) {
-        case 1:  /* mono */
-        case 2:  /* stereo */
-        case 4:  /* quad */
-        case 6:  /* 5.1 */
-        case 7:  /* 6.1 */
-        case 8:  /* 7.1 */
-          return SDL_TRUE;  /* supported. */
-
-        default:
-            break;
-    }
-
-    return SDL_FALSE;  /* unsupported. */
+    return ((channels >= 1) && (channels <= 8)) ? SDL_TRUE : SDL_FALSE;
 }
 
 
@@ -1120,6 +1880,8 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
 {
+    SDL_AudioFilter channel_converter = NULL;
+
     /* Sanity check target pointer */
     if (cvt == NULL) {
         return SDL_InvalidParamError("cvt");
@@ -1168,14 +1930,14 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
     cvt->len_ratio = 1.0;
     cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
 
-    /* Make sure we've chosen audio conversion functions (MMX, scalar, etc.) */
+    /* Make sure we've chosen audio conversion functions (SIMD, scalar, etc.) */
     SDL_ChooseAudioConverters();
 
     /* Type conversion goes like this now:
         - byteswap to CPU native format first if necessary.
         - convert to native Float32 if necessary.
         - resample and change channel count if necessary.
-        - convert back to native format.
+        - convert to final data format.
         - byteswap back to foreign format if necessary.
 
        The expectation is we can process data faster in float32
@@ -1209,177 +1971,51 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
         return -1;              /* shouldn't happen, but just in case... */
     }
 
+
     /* Channel conversion */
-    if (src_channels < dst_channels) {
-        /* Upmixing */
 
-        /* 6.1 -> 7.1 */
-        if (src_channels == 7) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert61To71) < 0) {
-                return -1;
-            }
-            cvt->len_mult = (cvt->len_mult * 8 + 6) / 7;
-            src_channels = 8;
-            cvt->len_ratio = cvt->len_ratio * 8 / 7;
+    /* SDL_SupportedChannelCount should have caught these asserts, or we added a new format and forgot to update the table. */
+    SDL_assert(src_channels <= SDL_arraysize(channel_converters));
+    SDL_assert(dst_channels <= SDL_arraysize(channel_converters[0]));
+
+    channel_converter = channel_converters[src_channels-1][dst_channels-1];
+    if ((channel_converter == NULL) != (src_channels == dst_channels)) {
+        /* All combinations of supported channel counts should have been handled by now, but let's be defensive */
+        return SDL_SetError("Invalid channel combination");
+    } else if (channel_converter != NULL) {
+        if (SDL_AddAudioCVTFilter(cvt, channel_converter) < 0) {
+            return -1;
         }
-        /* Mono -> Stereo [-> ...] */
-        if ((src_channels == 1) && (dst_channels > 1)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertMonoToStereo) < 0) {
-                return -1;
-            }
-            cvt->len_mult *= 2;
-            src_channels = 2;
-            cvt->len_ratio *= 2;
-        }
-        /* [Mono ->] Stereo -> 5.1 [-> 7.1] */
-        if ((src_channels == 2) && (dst_channels >= 6)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoTo51) < 0) {
-                return -1;
-            }
-            src_channels = 6;
-            cvt->len_mult *= 3;
-            cvt->len_ratio *= 3;
-        }
-        /* Quad -> 5.1 [-> 7.1] */
-        if ((src_channels == 4) && (dst_channels >= 6)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadTo51) < 0) {
-                return -1;
-            }
-            src_channels = 6;
-            cvt->len_mult = (cvt->len_mult * 3 + 1) / 2;
-            cvt->len_ratio *= 1.5;
-        }
-        /* 5.1 -> 6.1 */
-        if (src_channels == 6 && dst_channels == 7) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51To61) < 0) {
-                return -1;
-            }
-            src_channels = 7;
-            cvt->len_mult = (cvt->len_mult * 7 + 5) / 6;
-            cvt->len_ratio = cvt->len_ratio * 7 / 6;
-        }
-        /* [[Mono ->] Stereo ->] 5.1 -> 7.1 */
-        if ((src_channels == 6) && (dst_channels == 8)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51To71) < 0) {
-                return -1;
-            }
-            src_channels = 8;
-            cvt->len_mult = (cvt->len_mult * 4 + 2) / 3;
-            /* Should be numerically exact with every valid input to this
-               function */
-            cvt->len_ratio = cvt->len_ratio * 4 / 3;
-        }
-        /* [Mono ->] Stereo -> Quad */
-        if ((src_channels == 2) && (dst_channels == 4)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoToQuad) < 0) {
-                return -1;
-            }
-            src_channels = 4;
-            cvt->len_mult *= 2;
-            cvt->len_ratio *= 2;
-        }
-    } else if (src_channels > dst_channels) {
-        /* Downmixing */
-        /* 7.1 -> 6.1 */
-        if (src_channels == 8 && dst_channels == 7) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To61) < 0) {
-                return -1;
-            }
-            src_channels = 7;
-            cvt->len_ratio *= 7.0f / 8.0f;
-        }
-        /* 6.1 -> 5.1 [->...] */
-        if (src_channels == 7 && dst_channels != 7) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert61To51) < 0) {
-                return -1;
-            }
-            src_channels = 6;
-            cvt->len_ratio *= 6.0f / 7.0f;
-        }
-        /* 7.1 -> 5.1 [-> Stereo [-> Mono]] */
-        /* 7.1 -> 5.1 [-> Quad] */
-        if ((src_channels == 8) && (dst_channels <= 6)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To51) < 0) {
-                return -1;
-            }
-            src_channels = 6;
-            cvt->len_ratio *= 0.75;
-        }
-        /* [7.1 ->] 5.1 -> Stereo [-> Mono] */
-        if ((src_channels == 6) && (dst_channels <= 2)) {
+
+        /* swap in some SIMD versions for a few of these. */
+        if (channel_converter == SDL_Convert51ToStereo) {
             SDL_AudioFilter filter = NULL;
-
+#if 0 /* !!! FIXME: these have not been updated for the new formulas */
             #if HAVE_AVX_INTRINSICS
-            if (SDL_HasAVX()) {
-                filter = SDL_Convert51ToStereo_AVX;
-            }
+            if (!filter && SDL_HasAVX()) { filter = SDL_Convert51ToStereo_AVX; }
             #endif
-
             #if HAVE_SSE_INTRINSICS
-            if (!filter && SDL_HasSSE()) {
-                filter = SDL_Convert51ToStereo_SSE;
-            }
+            if (!filter && SDL_HasSSE()) { filter = SDL_Convert51ToStereo_SSE; }
             #endif
-
             #if HAVE_NEON_INTRINSICS
-            if (!filter && SDL_HasNEON()) {
-                filter = SDL_Convert51ToStereo_NEON;
-            }
+            if (!filter && SDL_HasNEON()) { filter = SDL_Convert51ToStereo_NEON; }
             #endif
-
-            if (!filter) {
-                filter = SDL_Convert51ToStereo;
-            }
-
-            if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
-                return -1;
-            }
-            src_channels = 2;
-            cvt->len_ratio /= 3;
-        }
-        /* 5.1 -> Quad */
-        if ((src_channels == 6) && (dst_channels == 4)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToQuad) < 0) {
-                return -1;
-            }
-            src_channels = 4;
-            cvt->len_ratio = cvt->len_ratio * 2 / 3;
-        }
-        /* Quad -> Stereo [-> Mono] */
-        if ((src_channels == 4) && (dst_channels <= 2)) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadToStereo) < 0) {
-                return -1;
-            }
-            src_channels = 2;
-            cvt->len_ratio /= 2;
-        }
-        /* [... ->] Stereo -> Mono */
-        if ((src_channels == 2) && (dst_channels == 1)) {
+#endif
+            if (filter) { channel_converter = filter; }
+        } else if (channel_converter == SDL_ConvertStereoToMono) {
             SDL_AudioFilter filter = NULL;
-
             #if HAVE_SSE3_INTRINSICS
-            if (SDL_HasSSE3()) {
-                filter = SDL_ConvertStereoToMono_SSE3;
-            }
+            if (!filter && SDL_HasSSE3()) { filter = SDL_ConvertStereoToMono_SSE3; }
             #endif
-
-            if (!filter) {
-                filter = SDL_ConvertStereoToMono;
-            }
-
-            if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
-                return -1;
-            }
-
-            src_channels = 1;
-            cvt->len_ratio /= 2;
+            if (filter) { channel_converter = filter; }
         }
-    }
 
-    if (src_channels != dst_channels) {
-        /* All combinations of supported channel counts should have been
-           handled by now, but let's be defensive */
-      return SDL_SetError("Invalid channel combination");
+        if (src_channels < dst_channels) {
+            cvt->len_mult = ((cvt->len_mult * dst_channels) + (src_channels-1)) / src_channels;
+        }
+
+        cvt->len_ratio = (cvt->len_ratio * dst_channels) / src_channels;
+        src_channels = dst_channels;
     }
 
     /* Do rate conversion, if necessary. Updates (cvt). */