/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
*/

/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c */

static void SDLCALL SDL_ConvertMonoToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 2))) - 2;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "stereo");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 2) {
        const float srcFC = src[0];
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 2;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertMonoTo21(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 3))) - 3;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "2.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 3) {
        const float srcFC = src[0];
        dst[2] /* LFE */ = 0.0f;
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 3;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertMonoToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 4))) - 4;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "quad");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 4) {
        const float srcFC = src[0];
        dst[3] /* BR */ = 0.0f;
        dst[2] /* BL */ = 0.0f;
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 4;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertMonoTo41(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 5))) - 5;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "4.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 5) {
        const float srcFC = src[0];
        dst[4] /* BR */ = 0.0f;
        dst[3] /* BL */ = 0.0f;
        dst[2] /* LFE */ = 0.0f;
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 5;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertMonoTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 6))) - 6;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "5.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 6) {
        const float srcFC = src[0];
        dst[5] /* BR */ = 0.0f;
        dst[4] /* BL */ = 0.0f;
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 6;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertMonoTo61(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 7))) - 7;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "6.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 7) {
        const float srcFC = src[0];
        dst[6] /* SR */ = 0.0f;
        dst[5] /* SL */ = 0.0f;
        dst[4] /* BC */ = 0.0f;
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 7;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertMonoTo71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 1) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 1;
    int i;

    LOG_DEBUG_CONVERT("mono", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 1); i; i--, src -= 1, dst -= 8) {
        const float srcFC = src[0];
        dst[7] /* SR */ = 0.0f;
        dst[6] /* SL */ = 0.0f;
        dst[5] /* BR */ = 0.0f;
        dst[4] /* BL */ = 0.0f;
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = srcFC;
        dst[0] /* FL */ = srcFC;
    }

    cvt->len_cvt = cvt->len_cvt * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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 / (sizeof(float) * 2); i; i--, src += 2, dst += 1) {
        dst[0] /* FC */ = (src[0] * 0.500000000f) + (src[1] * 0.500000000f);
    }

    cvt->len_cvt = cvt->len_cvt / 2;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertStereoTo21(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 2) * 3))) - 3;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 2;
    int i;

    LOG_DEBUG_CONVERT("stereo", "2.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 2); i; i--, src -= 2, dst -= 3) {
        dst[2] /* LFE */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 2) * 3;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertStereoToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 2) * 4))) - 4;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 2;
    int i;

    LOG_DEBUG_CONVERT("stereo", "quad");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 2); i; i--, src -= 2, dst -= 4) {
        dst[3] /* BR */ = 0.0f;
        dst[2] /* BL */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 2) * 4;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertStereoTo41(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 2) * 5))) - 5;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 2;
    int i;

    LOG_DEBUG_CONVERT("stereo", "4.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 2); i; i--, src -= 2, dst -= 5) {
        dst[4] /* BR */ = 0.0f;
        dst[3] /* BL */ = 0.0f;
        dst[2] /* LFE */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 2) * 5;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertStereoTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 2) * 6))) - 6;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 2;
    int i;

    LOG_DEBUG_CONVERT("stereo", "5.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 2); i; i--, src -= 2, dst -= 6) {
        dst[5] /* BR */ = 0.0f;
        dst[4] /* BL */ = 0.0f;
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 2) * 6;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertStereoTo61(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 2) * 7))) - 7;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 2;
    int i;

    LOG_DEBUG_CONVERT("stereo", "6.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 2); i; i--, src -= 2, dst -= 7) {
        dst[6] /* SR */ = 0.0f;
        dst[5] /* SL */ = 0.0f;
        dst[4] /* BC */ = 0.0f;
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 2) * 7;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertStereoTo71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 2) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 2;
    int i;

    LOG_DEBUG_CONVERT("stereo", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 2); i; i--, src -= 2, dst -= 8) {
        dst[7] /* SR */ = 0.0f;
        dst[6] /* SL */ = 0.0f;
        dst[5] /* BR */ = 0.0f;
        dst[4] /* BL */ = 0.0f;
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 2) * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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) * 3); i; i--, src += 3, dst += 1) {
        dst[0] /* FC */ = (src[0] * 0.333333343f) + (src[1] * 0.333333343f) + (src[2] * 0.333333343f);
    }

    cvt->len_cvt = cvt->len_cvt / 3;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert21ToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    LOG_DEBUG_CONVERT("2.1", "stereo");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 3); i; i--, src += 3, dst += 2) {
        const float srcLFE = src[2];
        dst[0] /* FL */ = (src[0] * 0.800000012f) + (srcLFE * 0.200000003f);
        dst[1] /* FR */ = (src[1] * 0.800000012f) + (srcLFE * 0.200000003f);
    }

    cvt->len_cvt = (cvt->len_cvt / 3) * 2;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert21ToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 3) * 4))) - 4;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 3;
    int i;

    LOG_DEBUG_CONVERT("2.1", "quad");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 3); i; i--, src -= 3, dst -= 4) {
        const float srcLFE = src[2];
        dst[3] /* BR */ = (srcLFE * 0.111111112f);
        dst[2] /* BL */ = (srcLFE * 0.111111112f);
        dst[1] /* FR */ = (srcLFE * 0.111111112f) + (src[1] * 0.888888896f);
        dst[0] /* FL */ = (srcLFE * 0.111111112f) + (src[0] * 0.888888896f);
    }

    cvt->len_cvt = (cvt->len_cvt / 3) * 4;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert21To41(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 3) * 5))) - 5;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 3;
    int i;

    LOG_DEBUG_CONVERT("2.1", "4.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 3); i; i--, src -= 3, dst -= 5) {
        dst[4] /* BR */ = 0.0f;
        dst[3] /* BL */ = 0.0f;
        dst[2] /* LFE */ = src[2];
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 3) * 5;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert21To51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 3) * 6))) - 6;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 3;
    int i;

    LOG_DEBUG_CONVERT("2.1", "5.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 3); i; i--, src -= 3, dst -= 6) {
        dst[5] /* BR */ = 0.0f;
        dst[4] /* BL */ = 0.0f;
        dst[3] /* LFE */ = src[2];
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 3) * 6;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert21To61(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 3) * 7))) - 7;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 3;
    int i;

    LOG_DEBUG_CONVERT("2.1", "6.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 3); i; i--, src -= 3, dst -= 7) {
        dst[6] /* SR */ = 0.0f;
        dst[5] /* SL */ = 0.0f;
        dst[4] /* BC */ = 0.0f;
        dst[3] /* LFE */ = src[2];
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 3) * 7;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert21To71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 3) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 3;
    int i;

    LOG_DEBUG_CONVERT("2.1", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 3); i; i--, src -= 3, dst -= 8) {
        dst[7] /* SR */ = 0.0f;
        dst[6] /* SL */ = 0.0f;
        dst[5] /* BR */ = 0.0f;
        dst[4] /* BL */ = 0.0f;
        dst[3] /* LFE */ = src[2];
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 3) * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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);

    for (i = cvt->len_cvt / (sizeof(float) * 4); i; i--, src += 4, dst += 1) {
        dst[0] /* FC */ = (src[0] * 0.250000000f) + (src[1] * 0.250000000f) + (src[2] * 0.250000000f) + (src[3] * 0.250000000f);
    }

    cvt->len_cvt = cvt->len_cvt / 4;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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) {
        const float srcBL = src[2];
        const float srcBR = src[3];
        dst[0] /* FL */ = (src[0] * 0.421000004f) + (srcBL * 0.358999997f) + (srcBR * 0.219999999f);
        dst[1] /* FR */ = (src[1] * 0.421000004f) + (srcBL * 0.219999999f) + (srcBR * 0.358999997f);
    }

    cvt->len_cvt = (cvt->len_cvt / 4) * 2;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertQuadTo21(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    LOG_DEBUG_CONVERT("quad", "2.1");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 4); i; i--, src += 4, dst += 3) {
        const float srcBL = src[2];
        const float srcBR = src[3];
        dst[0] /* FL */ = (src[0] * 0.421000004f) + (srcBL * 0.358999997f) + (srcBR * 0.219999999f);
        dst[1] /* FR */ = (src[1] * 0.421000004f) + (srcBL * 0.219999999f) + (srcBR * 0.358999997f);
        dst[2] /* LFE */ = 0.0f;
    }

    cvt->len_cvt = (cvt->len_cvt / 4) * 3;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_ConvertQuadTo41(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 4) * 5))) - 5;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 4;
    int i;

    LOG_DEBUG_CONVERT("quad", "4.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 4); i; i--, src -= 4, dst -= 5) {
        dst[4] /* BR */ = src[3];
        dst[3] /* BL */ = src[2];
        dst[2] /* LFE */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = 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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 4) * 6))) - 6;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 4;
    int i;

    LOG_DEBUG_CONVERT("quad", "5.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 4); i; i--, src -= 4, dst -= 6) {
        dst[5] /* BR */ = src[3];
        dst[4] /* BL */ = src[2];
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = 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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 4) * 7))) - 7;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 4;
    int i;

    LOG_DEBUG_CONVERT("quad", "6.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 4); i; i--, src -= 4, dst -= 7) {
        const float srcBL = src[2];
        const float srcBR = src[3];
        dst[6] /* SR */ = (srcBR * 0.796000004f);
        dst[5] /* SL */ = (srcBL * 0.796000004f);
        dst[4] /* BC */ = (srcBR * 0.500000000f) + (srcBL * 0.500000000f);
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = (src[1] * 0.939999998f);
        dst[0] /* FL */ = (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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 4) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 4;
    int i;

    LOG_DEBUG_CONVERT("quad", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 4); i; i--, src -= 4, dst -= 8) {
        dst[7] /* SR */ = 0.0f;
        dst[6] /* SL */ = 0.0f;
        dst[5] /* BR */ = src[3];
        dst[4] /* BL */ = src[2];
        dst[3] /* LFE */ = 0.0f;
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 4) * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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("4.1", "mono");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 5); i; i--, src += 5, dst += 1) {
        dst[0] /* FC */ = (src[0] * 0.200000003f) + (src[1] * 0.200000003f) + (src[2] * 0.200000003f) + (src[3] * 0.200000003f) + (src[4] * 0.200000003f);
    }

    cvt->len_cvt = 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, dst += 2) {
        const float srcLFE = src[2];
        const float srcBL = src[3];
        const float srcBR = src[4];
        dst[0] /* FL */ = (src[0] * 0.374222219f) + (srcLFE * 0.111111112f) + (srcBL * 0.319111109f) + (srcBR * 0.195555553f);
        dst[1] /* FR */ = (src[1] * 0.374222219f) + (srcLFE * 0.111111112f) + (srcBL * 0.195555553f) + (srcBR * 0.319111109f);
    }

    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, dst += 3) {
        const float srcBL = src[3];
        const float srcBR = src[4];
        dst[0] /* FL */ = (src[0] * 0.421000004f) + (srcBL * 0.358999997f) + (srcBR * 0.219999999f);
        dst[1] /* FR */ = (src[1] * 0.421000004f) + (srcBL * 0.219999999f) + (srcBR * 0.358999997f);
        dst[2] /* LFE */ = src[2];
    }

    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, dst += 4) {
        const float srcLFE = src[2];
        dst[0] /* FL */ = (src[0] * 0.941176474f) + (srcLFE * 0.058823530f);
        dst[1] /* FR */ = (src[1] * 0.941176474f) + (srcLFE * 0.058823530f);
        dst[2] /* BL */ = (srcLFE * 0.058823530f) + (src[3] * 0.941176474f);
        dst[3] /* BR */ = (srcLFE * 0.058823530f) + (src[4] * 0.941176474f);
    }

    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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 5) * 6))) - 6;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 5;
    int i;

    LOG_DEBUG_CONVERT("4.1", "5.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 5); i; i--, src -= 5, dst -= 6) {
        dst[5] /* BR */ = src[4];
        dst[4] /* BL */ = src[3];
        dst[3] /* LFE */ = src[2];
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = 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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 5) * 7))) - 7;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 5;
    int i;

    LOG_DEBUG_CONVERT("4.1", "6.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 5); i; i--, src -= 5, dst -= 7) {
        const float srcBL = src[3];
        const float srcBR = src[4];
        dst[6] /* SR */ = (srcBR * 0.796000004f);
        dst[5] /* SL */ = (srcBL * 0.796000004f);
        dst[4] /* BC */ = (srcBR * 0.500000000f) + (srcBL * 0.500000000f);
        dst[3] /* LFE */ = src[2];
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = (src[1] * 0.939999998f);
        dst[0] /* FL */ = (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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 5) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 5;
    int i;

    LOG_DEBUG_CONVERT("4.1", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 5); i; i--, src -= 5, dst -= 8) {
        dst[7] /* SR */ = 0.0f;
        dst[6] /* SL */ = 0.0f;
        dst[5] /* BR */ = src[4];
        dst[4] /* BL */ = src[3];
        dst[3] /* LFE */ = src[2];
        dst[2] /* FC */ = 0.0f;
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 5) * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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 += 1) {
        dst[0] /* FC */ = (src[0] * 0.166666672f) + (src[1] * 0.166666672f) + (src[2] * 0.166666672f) + (src[3] * 0.166666672f) + (src[4] * 0.166666672f) + (src[5] * 0.166666672f);
    }

    cvt->len_cvt = 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, dst += 2) {
        const float srcFC = src[2];
        const float srcLFE = src[3];
        const float srcBL = src[4];
        const float srcBR = src[5];
        dst[0] /* FL */ = (src[0] * 0.294545442f) + (srcFC * 0.208181813f) + (srcLFE * 0.090909094f) + (srcBL * 0.251818180f) + (srcBR * 0.154545456f);
        dst[1] /* FR */ = (src[1] * 0.294545442f) + (srcFC * 0.208181813f) + (srcLFE * 0.090909094f) + (srcBL * 0.154545456f) + (srcBR * 0.251818180f);
    }

    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, dst += 3) {
        const float srcFC = src[2];
        const float srcBL = src[4];
        const float srcBR = src[5];
        dst[0] /* FL */ = (src[0] * 0.324000001f) + (srcFC * 0.229000002f) + (srcBL * 0.277000010f) + (srcBR * 0.170000002f);
        dst[1] /* FR */ = (src[1] * 0.324000001f) + (srcFC * 0.229000002f) + (srcBL * 0.170000002f) + (srcBR * 0.277000010f);
        dst[2] /* LFE */ = src[3];
    }

    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, dst += 4) {
        const float srcFC = src[2];
        const float srcLFE = src[3];
        dst[0] /* FL */ = (src[0] * 0.558095276f) + (srcFC * 0.394285709f) + (srcLFE * 0.047619049f);
        dst[1] /* FR */ = (src[1] * 0.558095276f) + (srcFC * 0.394285709f) + (srcLFE * 0.047619049f);
        dst[2] /* BL */ = (srcLFE * 0.047619049f) + (src[4] * 0.558095276f);
        dst[3] /* BR */ = (srcLFE * 0.047619049f) + (src[5] * 0.558095276f);
    }

    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, dst += 5) {
        const float srcFC = src[2];
        dst[0] /* FL */ = (src[0] * 0.586000025f) + (srcFC * 0.414000005f);
        dst[1] /* FR */ = (src[1] * 0.586000025f) + (srcFC * 0.414000005f);
        dst[2] /* LFE */ = src[3];
        dst[3] /* BL */ = (src[4] * 0.586000025f);
        dst[4] /* BR */ = (src[5] * 0.586000025f);
    }

    cvt->len_cvt = (cvt->len_cvt / 6) * 5;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert51To61(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 6) * 7))) - 7;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 6;
    int i;

    LOG_DEBUG_CONVERT("5.1", "6.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 6); i; i--, src -= 6, dst -= 7) {
        const float srcBL = src[4];
        const float srcBR = src[5];
        dst[6] /* SR */ = (srcBR * 0.796000004f);
        dst[5] /* SL */ = (srcBL * 0.796000004f);
        dst[4] /* BC */ = (srcBR * 0.500000000f) + (srcBL * 0.500000000f);
        dst[3] /* LFE */ = src[3];
        dst[2] /* FC */ = (src[2] * 0.939999998f);
        dst[1] /* FR */ = (src[1] * 0.939999998f);
        dst[0] /* FL */ = (src[0] * 0.939999998f);
    }

    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)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 6) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 6;
    int i;

    LOG_DEBUG_CONVERT("5.1", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 6); i; i--, src -= 6, dst -= 8) {
        dst[7] /* SR */ = 0.0f;
        dst[6] /* SL */ = 0.0f;
        dst[5] /* BR */ = src[5];
        dst[4] /* BL */ = src[4];
        dst[3] /* LFE */ = src[3];
        dst[2] /* FC */ = src[2];
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 6) * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

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 += 1) {
        dst[0] /* FC */ = (src[0] * 0.143142849f) + (src[1] * 0.143142849f) + (src[2] * 0.143142849f) + (src[3] * 0.142857149f) + (src[4] * 0.143142849f) + (src[5] * 0.143142849f) + (src[6] * 0.143142849f);
    }

    cvt->len_cvt = 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, dst += 2) {
        const float srcFC = src[2];
        const float srcLFE = src[3];
        const float srcBC = src[4];
        const float srcSL = src[5];
        const float srcSR = src[6];
        dst[0] /* FL */ = (src[0] * 0.247384623f) + (srcFC * 0.174461529f) + (srcLFE * 0.076923080f) + (srcBC * 0.174461529f) + (srcSL * 0.226153851f) + (srcSR * 0.100615382f);
        dst[1] /* FR */ = (src[1] * 0.247384623f) + (srcFC * 0.174461529f) + (srcLFE * 0.076923080f) + (srcBC * 0.174461529f) + (srcSL * 0.100615382f) + (srcSR * 0.226153851f);
    }

    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, dst += 3) {
        const float srcFC = src[2];
        const float srcBC = src[4];
        const float srcSL = src[5];
        const float srcSR = src[6];
        dst[0] /* FL */ = (src[0] * 0.268000007f) + (srcFC * 0.188999996f) + (srcBC * 0.188999996f) + (srcSL * 0.245000005f) + (srcSR * 0.108999997f);
        dst[1] /* FR */ = (src[1] * 0.268000007f) + (srcFC * 0.188999996f) + (srcBC * 0.188999996f) + (srcSL * 0.108999997f) + (srcSR * 0.245000005f);
        dst[2] /* LFE */ = src[3];
    }

    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, dst += 4) {
        const float srcFC = src[2];
        const float srcLFE = src[3];
        const float srcBC = src[4];
        const float srcSL = src[5];
        const float srcSR = src[6];
        dst[0] /* FL */ = (src[0] * 0.463679999f) + (srcFC * 0.327360004f) + (srcLFE * 0.040000003f) + (srcSL * 0.168960005f);
        dst[1] /* FR */ = (src[1] * 0.463679999f) + (srcFC * 0.327360004f) + (srcLFE * 0.040000003f) + (srcSR * 0.168960005f);
        dst[2] /* BL */ = (srcLFE * 0.040000003f) + (srcBC * 0.327360004f) + (srcSL * 0.431039989f);
        dst[3] /* BR */ = (srcLFE * 0.040000003f) + (srcBC * 0.327360004f) + (srcSR * 0.431039989f);
    }

    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, dst += 5) {
        const float srcFC = src[2];
        const float srcBC = src[4];
        const float srcSL = src[5];
        const float srcSR = src[6];
        dst[0] /* FL */ = (src[0] * 0.483000010f) + (srcFC * 0.340999991f) + (srcSL * 0.175999999f);
        dst[1] /* FR */ = (src[1] * 0.483000010f) + (srcFC * 0.340999991f) + (srcSR * 0.175999999f);
        dst[2] /* LFE */ = src[3];
        dst[3] /* BL */ = (srcBC * 0.340999991f) + (srcSL * 0.449000001f);
        dst[4] /* BR */ = (srcBC * 0.340999991f) + (srcSR * 0.449000001f);
    }

    cvt->len_cvt = (cvt->len_cvt / 7) * 5;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert61To51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    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) {
        const float srcBC = src[4];
        const float srcSL = src[5];
        const float srcSR = src[6];
        dst[0] /* FL */ = (src[0] * 0.611000001f) + (srcSL * 0.223000005f);
        dst[1] /* FR */ = (src[1] * 0.611000001f) + (srcSR * 0.223000005f);
        dst[2] /* FC */ = (src[2] * 0.611000001f);
        dst[3] /* LFE */ = src[3];
        dst[4] /* BL */ = (srcBC * 0.432000011f) + (srcSL * 0.568000019f);
        dst[5] /* BR */ = (srcBC * 0.432000011f) + (srcSR * 0.568000019f);
    }

    cvt->len_cvt = (cvt->len_cvt / 7) * 6;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert61To71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = ((float *)(cvt->buf + ((cvt->len_cvt / 7) * 8))) - 8;
    const float *src = ((const float *)(cvt->buf + cvt->len_cvt)) - 7;
    int i;

    LOG_DEBUG_CONVERT("6.1", "7.1");
    SDL_assert(format == AUDIO_F32SYS);

    /* convert backwards, since output is growing in-place. */
    for (i = cvt->len_cvt / (sizeof(float) * 7); i; i--, src -= 7, dst -= 8) {
        const float srcBC = src[4];
        dst[7] /* SR */ = src[6];
        dst[6] /* SL */ = src[5];
        dst[5] /* BR */ = (srcBC * 0.707000017f);
        dst[4] /* BL */ = (srcBC * 0.707000017f);
        dst[3] /* LFE */ = src[3];
        dst[2] /* FC */ = src[2];
        dst[1] /* FR */ = src[1];
        dst[0] /* FL */ = src[0];
    }

    cvt->len_cvt = (cvt->len_cvt / 7) * 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert71ToMono(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    LOG_DEBUG_CONVERT("7.1", "mono");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 8); i; i--, src += 8, dst += 1) {
        dst[0] /* FC */ = (src[0] * 0.125125006f) + (src[1] * 0.125125006f) + (src[2] * 0.125125006f) + (src[3] * 0.125000000f) + (src[4] * 0.125125006f) + (src[5] * 0.125125006f) + (src[6] * 0.125125006f) + (src[7] * 0.125125006f);
    }

    cvt->len_cvt = cvt->len_cvt / 8;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert71ToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    LOG_DEBUG_CONVERT("7.1", "stereo");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 8); i; i--, src += 8, dst += 2) {
        const float srcFC = src[2];
        const float srcLFE = src[3];
        const float srcBL = src[4];
        const float srcBR = src[5];
        const float srcSL = src[6];
        const float srcSR = src[7];
        dst[0] /* FL */ = (src[0] * 0.211866662f) + (srcFC * 0.150266662f) + (srcLFE * 0.066666670f) + (srcBL * 0.181066677f) + (srcBR * 0.111066669f) + (srcSL * 0.194133341f) + (srcSR * 0.085866667f);
        dst[1] /* FR */ = (src[1] * 0.211866662f) + (srcFC * 0.150266662f) + (srcLFE * 0.066666670f) + (srcBL * 0.111066669f) + (srcBR * 0.181066677f) + (srcSL * 0.085866667f) + (srcSR * 0.194133341f);
    }

    cvt->len_cvt = (cvt->len_cvt / 8) * 2;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert71To21(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    LOG_DEBUG_CONVERT("7.1", "2.1");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 8); i; i--, src += 8, dst += 3) {
        const float srcFC = src[2];
        const float srcBL = src[4];
        const float srcBR = src[5];
        const float srcSL = src[6];
        const float srcSR = src[7];
        dst[0] /* FL */ = (src[0] * 0.226999998f) + (srcFC * 0.160999998f) + (srcBL * 0.194000006f) + (srcBR * 0.119000003f) + (srcSL * 0.208000004f) + (srcSR * 0.092000000f);
        dst[1] /* FR */ = (src[1] * 0.226999998f) + (srcFC * 0.160999998f) + (srcBL * 0.119000003f) + (srcBR * 0.194000006f) + (srcSL * 0.092000000f) + (srcSR * 0.208000004f);
        dst[2] /* LFE */ = src[3];
    }

    cvt->len_cvt = (cvt->len_cvt / 8) * 3;
    if (cvt->filters[++cvt->filter_index]) {
        cvt->filters[cvt->filter_index](cvt, format);
    }
}

static void SDLCALL SDL_Convert71ToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
    float *dst = (float *)cvt->buf;
    const float *src = dst;
    int i;

    LOG_DEBUG_CONVERT("7.1", "quad");
    SDL_assert(format == AUDIO_F32SYS);

    for (i = cvt->len_cvt / (sizeof(float) * 8); i; i--, src += 8, dst += 4) {
        const float srcFC = src[2];
        const float srcLFE = src[3];
        const float srcSL = src[6];
        const float srcSR = src[7];
        dst[0] /* FL */ = (src[0] * 0.466344833f) + (srcFC * 0.329241365f) + (srcLFE * 0.034482758f) + (srcSL * 0.169931039f);
        dst[1] /* FR */ = (src[1] * 0.466344833f) + (srcFC * 0.329241365f) + (srcLFE * 0.034482758f) + (srcSR * 0.169931039f);
        dst[2] /* BL */ = (srcLFE * 0.034482758f) + (src[4] * 0.466344833f) + (srcSL * 0.433517247f);
        dst[3] /* BR */ = (srcLFE * 0.034482758f) + (src[5] * 0.466344833f) + (srcSR * 0.433517247f);
    }

    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, dst += 5) {
        const float srcFC = src[2];
        const float srcSL = src[6];
        const float srcSR = src[7];
        dst[0] /* FL */ = (src[0] * 0.483000010f) + (srcFC * 0.340999991f) + (srcSL * 0.175999999f);
        dst[1] /* FR */ = (src[1] * 0.483000010f) + (srcFC * 0.340999991f) + (srcSR * 0.175999999f);
        dst[2] /* LFE */ = src[3];
        dst[3] /* BL */ = (src[4] * 0.483000010f) + (srcSL * 0.449000001f);
        dst[4] /* BR */ = (src[5] * 0.483000010f) + (srcSR * 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, dst += 6) {
        const float srcSL = src[6];
        const float srcSR = src[7];
        dst[0] /* FL */ = (src[0] * 0.518000007f) + (srcSL * 0.188999996f);
        dst[1] /* FR */ = (src[1] * 0.518000007f) + (srcSR * 0.188999996f);
        dst[2] /* FC */ = (src[2] * 0.518000007f);
        dst[3] /* LFE */ = src[3];
        dst[4] /* BL */ = (src[4] * 0.518000007f) + (srcSL * 0.481999993f);
        dst[5] /* BR */ = (src[5] * 0.518000007f) + (srcSR * 0.481999993f);
    }

    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, dst += 7) {
        const float srcBL = src[4];
        const float srcBR = src[5];
        dst[0] /* FL */ = (src[0] * 0.541000009f);
        dst[1] /* FR */ = (src[1] * 0.541000009f);
        dst[2] /* FC */ = (src[2] * 0.541000009f);
        dst[3] /* LFE */ = src[3];
        dst[4] /* BC */ = (srcBL * 0.287999988f) + (srcBR * 0.287999988f);
        dst[5] /* SL */ = (srcBL * 0.458999991f) + (src[6] * 0.541000009f);
        dst[6] /* SR */ = (srcBR * 0.458999991f) + (src[7] * 0.541000009f);
    }

    cvt->len_cvt = (cvt->len_cvt / 8) * 7;
    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 }
};

/* vi: set ts=4 sw=4 expandtab: */
