diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c
index 0a999730c..b59a1e12b 100644
--- a/src/audio/SDL_audiocvt.c
+++ b/src/audio/SDL_audiocvt.c
@@ -36,7 +36,7 @@
 #endif
 
 #if HAVE_SSE3_INTRINSICS
-/* Effectively mix right and left channels into a single channel */
+/* Convert from stereo to mono. Average left and right. */
 static void SDLCALL
 SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -71,7 +71,7 @@ SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 }
 #endif
 
-/* Effectively mix right and left channels into a single channel */
+/* Convert from stereo to mono. Average left and right. */
 static void SDLCALL
 SDL_ConvertStereoToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -93,7 +93,7 @@ SDL_ConvertStereoToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 }
 
 
-/* Convert from 5.1 to stereo. Average left and right, discard subwoofer. */
+/* Convert from 5.1 to stereo. Average left and right, distribute center, discard LFE. */
 static void SDLCALL
 SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -104,11 +104,11 @@ SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     LOG_DEBUG_CONVERT("5.1", "stereo");
     SDL_assert(format == AUDIO_F32SYS);
 
-    /* this assumes FL+FR+FC+subwoof+BL+BR layout. */
+    /* 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 double front_center = (double) src[2];
-        dst[0] = (float) ((src[0] + front_center + src[4]) / 3.0);  /* left */
-        dst[1] = (float) ((src[1] + front_center + src[5]) / 3.0);  /* right */
+        const float front_center_distributed = src[2] * 0.5f;
+        dst[0] = (src[0] + front_center_distributed + src[4]) / 2.5f;  /* left */
+        dst[1] = (src[1] + front_center_distributed + src[5]) / 2.5f;  /* right */
     }
 
     cvt->len_cvt /= 3;
@@ -118,7 +118,60 @@ SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 }
 
 
-/* Convert from 5.1 to quad */
+/* Convert from quad to stereo. Average left and right. */
+static void SDLCALL
+SDL_ConvertQuadToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float *dst = (float *) cvt->buf;
+    const float *src = dst;
+    int i;
+
+    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 */
+    }
+
+    cvt->len_cvt /= 3;
+    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;
+
+    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) / 1.5f;  /* FL */
+        dst[1] = (src[1] + surround_right_distributed) / 1.5f;  /* FR */
+        dst[2] = src[2] / 1.5f; /* CC */
+        dst[3] = src[3] / 1.5f; /* LFE */
+        dst[4] = (src[4] + surround_left_distributed) / 1.5f;  /* BL */
+        dst[5] = (src[5] + surround_right_distributed) / 1.5f;  /* BR */
+    }
+
+    cvt->len_cvt /= 8;
+    cvt->len_cvt *= 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)
 {
@@ -129,14 +182,14 @@ SDL_Convert51ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     LOG_DEBUG_CONVERT("5.1", "quad");
     SDL_assert(format == AUDIO_F32SYS);
 
-    /* assumes quad is FL+FR+BL+BR layout and 5.1 is FL+FR+FC+subwoof+BL+BR */
+    /* 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) {
-        /* FIXME: this is a good candidate for SIMD. */
-        const double front_center = (double) src[2];
-        dst[0] = (float) ((src[0] + front_center) * 0.5);  /* FL */
-        dst[1] = (float) ((src[1] + front_center) * 0.5);  /* FR */
-        dst[2] = (float) ((src[4] + front_center) * 0.5);  /* BL */
-        dst[3] = (float) ((src[5] + front_center) * 0.5);  /* BR */
+        const float front_center_distributed = src[2] * 0.5f;
+        dst[0] = (src[0] + front_center_distributed) / 1.5f;  /* FL */
+        dst[1] = (src[1] + front_center_distributed) / 1.5f;  /* FR */
+        dst[2] = src[4] / 1.5f;  /* BL */
+        dst[3] = src[5] / 1.5f;  /* BR */
     }
 
     cvt->len_cvt /= 6;
@@ -147,7 +200,7 @@ SDL_Convert51ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 }
 
 
-/* Duplicate a mono channel to both stereo channels */
+/* Upmix mono to stereo (by duplication) */
 static void SDLCALL
 SDL_ConvertMonoToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -171,7 +224,7 @@ SDL_ConvertMonoToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 }
 
 
-/* Duplicate a stereo channel to a pseudo-5.1 stream */
+/* Upmix stereo to a pseudo-5.1 stream */
 static void SDLCALL
 SDL_ConvertStereoTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 {
@@ -183,16 +236,17 @@ SDL_ConvertStereoTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     LOG_DEBUG_CONVERT("stereo", "5.1");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / 8; i; --i) {
+    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;
+        /* !!! FIXME: FL and FR may clip */
         dst[0] = lf + (lf - ce);  /* FL */
         dst[1] = rf + (rf - ce);  /* FR */
         dst[2] = ce;  /* FC */
-        dst[3] = ce;  /* !!! FIXME: wrong! This is the subwoofer. */
+        dst[3] = 0;   /* LFE (only meant for special LFE effects) */
         dst[4] = lf;  /* BL */
         dst[5] = rf;  /* BR */
     }
@@ -204,7 +258,44 @@ SDL_ConvertStereoTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
 }
 
 
-/* Duplicate a stereo channel to a pseudo-4.0 stream */
+/* 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;
+        /* !!! FIXME: FL and FR may clip */
+        dst[0] = lf + (lf - ce);  /* FL */
+        dst[1] = rf + (rf - 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)
 {
@@ -216,7 +307,7 @@ SDL_ConvertStereoToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     LOG_DEBUG_CONVERT("stereo", "quad");
     SDL_assert(format == AUDIO_F32SYS);
 
-    for (i = cvt->len_cvt / 8; i; --i) {
+    for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
         dst -= 4;
         src -= 2;
         lf = src[0];
@@ -233,6 +324,52 @@ SDL_ConvertStereoToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     }
 }
 
+
+/* Upmix 5.1 to 7.1 */
+static void SDLCALL
+SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
+{
+    float lf, rf, lb, rb, ls, rs;
+    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");
+    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;
+        /* !!! FIXME: these four may clip */
+        lf += lf - ls;
+        rf += rf - ls;
+        lb += lb - ls;
+        rb += rb - ls;
+        dst[3] = src[3];  /* LFE */
+        dst[2] = src[2];  /* FC */
+        dst[7] = rs; /* SR */
+        dst[6] = ls; /* SL */
+        dst[5] = rb;  /* BR */
+        dst[4] = lb;  /* BL */
+        dst[1] = rf;  /* FR */
+        dst[0] = lf;  /* FL */
+    }
+
+    cvt->len_cvt = cvt->len_cvt * 4 / 3;
+
+    if (cvt->filters[++cvt->filter_index]) {
+        cvt->filters[cvt->filter_index] (cvt, format);
+    }
+}
+
+
 static int
 SDL_ResampleAudioSimple(const int chans, const double rate_incr,
                         float *last_sample, const float *inbuf,
@@ -732,9 +869,9 @@ SDL_SupportedChannelCount(const int channels)
         case 2:  /* stereo */
         case 4:  /* quad */
         case 6:  /* 5.1 */
-            return SDL_TRUE;  /* supported. */
+        case 8:  /* 7.1 */
+          return SDL_TRUE;  /* supported. */
 
-        case 8:  /* !!! FIXME: 7.1 */
         default:
             break;
     }
@@ -857,7 +994,9 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
     }
 
     /* Channel conversion */
-    if (src_channels != dst_channels) {
+    if (src_channels < dst_channels) {
+        /* Upmixing */
+        /* Mono -> Stereo [-> ...] */
         if ((src_channels == 1) && (dst_channels > 1)) {
             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertMonoToStereo) < 0) {
                 return -1;
@@ -866,7 +1005,8 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
             src_channels = 2;
             cvt->len_ratio *= 2;
         }
-        if ((src_channels == 2) && (dst_channels == 6)) {
+        /* [Mono ->] Stereo -> 5.1 [-> 7.1] */
+        if ((src_channels == 2) && (dst_channels >= 6)) {
             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoTo51) < 0) {
                 return -1;
             }
@@ -874,6 +1014,27 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
             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;
+        }
+        /* [[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;
@@ -882,14 +1043,18 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
             cvt->len_mult *= 2;
             cvt->len_ratio *= 2;
         }
-        while ((src_channels * 2) <= dst_channels) {
-            if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertMonoToStereo) < 0) {
+    } else if (src_channels > dst_channels) {
+        /* Downmixing */
+        /* 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;
             }
-            cvt->len_mult *= 2;
-            src_channels *= 2;
-            cvt->len_ratio *= 2;
+            src_channels = 6;
+            cvt->len_ratio *= 0.75;
         }
+        /* [7.1 ->] 5.1 -> Stereo [-> Mono] */
         if ((src_channels == 6) && (dst_channels <= 2)) {
             if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToStereo) < 0) {
                 return -1;
@@ -897,19 +1062,24 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
             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;
         }
-        /* This assumes that 4 channel audio is in the format:
-           Left {front/back} + Right {front/back}
-           so converting to L/R stereo works properly.
-         */
-        while (((src_channels % 2) == 0) &&
-               ((src_channels / 2) >= dst_channels)) {
+        /* [... ->] Stereo -> Mono */
+        if ((src_channels == 2) && (dst_channels == 1)) {
             SDL_AudioFilter filter = NULL;
 
             #if HAVE_SSE3_INTRINSICS
@@ -926,14 +1096,17 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
                 return -1;
             }
 
-            src_channels /= 2;
+            src_channels = 1;
             cvt->len_ratio /= 2;
         }
-        if (src_channels != dst_channels) {
-            /* Uh oh.. */ ;
-        }
     }
 
+    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");
+    }
+    
     /* Do rate conversion, if necessary. Updates (cvt). */
     if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) < 0) {
         return -1;              /* shouldn't happen, but just in case... */