src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 26 Aug 2008 07:34:49 +0000
changeset 2728 2768bd7281e0
parent 2716 f8f68f47285a
child 2738 79c1bd651f04
permissions -rw-r--r--
Fixed Visual Studio compilation problems
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #define _USE_MATH_DEFINES
    25 #include <math.h>
    26 
    27 /* Functions for audio drivers to perform runtime conversion of audio format */
    28 
    29 #include "SDL_audio.h"
    30 #include "SDL_audio_c.h"
    31 
    32 //#define DEBUG_CONVERT
    33 
    34 /* These are fractional multiplication routines. That is, their inputs
    35    are two numbers in the range [-1, 1) and the result falls in that
    36    same range. The output is the same size as the inputs, i.e.
    37    32-bit x 32-bit = 32-bit.
    38  */
    39 
    40 /* We hope here that the right shift includes sign extension */
    41 #ifdef SDL_HAS_64BIT_Type
    42 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    43 #else
    44 /* If we don't have the 64-bit type, do something more complicated. See http://www.8052.com/mul16.phtml or http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html */
    45 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    46 #endif
    47 #define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
    48 #define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
    49 /* This macro just makes the floating point filtering code not have to be a special case. */
    50 #define SDL_FloatMpy(a, b) (a * b)
    51 
    52 /* These macros take floating point numbers in the range [-1.0f, 1.0f) and
    53    represent them as fixed-point numbers in that same range. There's no
    54    checking that the floating point argument is inside the appropriate range.
    55  */
    56 
    57 #define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
    58 #define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
    59 #define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
    60 #define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
    61 #define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
    62 #define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
    63 
    64 /* Effectively mix right and left channels into a single channel */
    65 static void SDLCALL
    66 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    67 {
    68     int i;
    69     Sint32 sample;
    70 
    71 #ifdef DEBUG_CONVERT
    72     fprintf(stderr, "Converting to mono\n");
    73 #endif
    74     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
    75     case AUDIO_U8:
    76         {
    77             Uint8 *src, *dst;
    78 
    79             src = cvt->buf;
    80             dst = cvt->buf;
    81             for (i = cvt->len_cvt / 2; i; --i) {
    82                 sample = src[0] + src[1];
    83                 *dst = (Uint8) (sample / 2);
    84                 src += 2;
    85                 dst += 1;
    86             }
    87         }
    88         break;
    89 
    90     case AUDIO_S8:
    91         {
    92             Sint8 *src, *dst;
    93 
    94             src = (Sint8 *) cvt->buf;
    95             dst = (Sint8 *) cvt->buf;
    96             for (i = cvt->len_cvt / 2; i; --i) {
    97                 sample = src[0] + src[1];
    98                 *dst = (Sint8) (sample / 2);
    99                 src += 2;
   100                 dst += 1;
   101             }
   102         }
   103         break;
   104 
   105     case AUDIO_U16:
   106         {
   107             Uint8 *src, *dst;
   108 
   109             src = cvt->buf;
   110             dst = cvt->buf;
   111             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   112                 for (i = cvt->len_cvt / 4; i; --i) {
   113                     sample = (Uint16) ((src[0] << 8) | src[1]) +
   114                         (Uint16) ((src[2] << 8) | src[3]);
   115                     sample /= 2;
   116                     dst[1] = (sample & 0xFF);
   117                     sample >>= 8;
   118                     dst[0] = (sample & 0xFF);
   119                     src += 4;
   120                     dst += 2;
   121                 }
   122             } else {
   123                 for (i = cvt->len_cvt / 4; i; --i) {
   124                     sample = (Uint16) ((src[1] << 8) | src[0]) +
   125                         (Uint16) ((src[3] << 8) | src[2]);
   126                     sample /= 2;
   127                     dst[0] = (sample & 0xFF);
   128                     sample >>= 8;
   129                     dst[1] = (sample & 0xFF);
   130                     src += 4;
   131                     dst += 2;
   132                 }
   133             }
   134         }
   135         break;
   136 
   137     case AUDIO_S16:
   138         {
   139             Uint8 *src, *dst;
   140 
   141             src = cvt->buf;
   142             dst = cvt->buf;
   143             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   144                 for (i = cvt->len_cvt / 4; i; --i) {
   145                     sample = (Sint16) ((src[0] << 8) | src[1]) +
   146                         (Sint16) ((src[2] << 8) | src[3]);
   147                     sample /= 2;
   148                     dst[1] = (sample & 0xFF);
   149                     sample >>= 8;
   150                     dst[0] = (sample & 0xFF);
   151                     src += 4;
   152                     dst += 2;
   153                 }
   154             } else {
   155                 for (i = cvt->len_cvt / 4; i; --i) {
   156                     sample = (Sint16) ((src[1] << 8) | src[0]) +
   157                         (Sint16) ((src[3] << 8) | src[2]);
   158                     sample /= 2;
   159                     dst[0] = (sample & 0xFF);
   160                     sample >>= 8;
   161                     dst[1] = (sample & 0xFF);
   162                     src += 4;
   163                     dst += 2;
   164                 }
   165             }
   166         }
   167         break;
   168 
   169     case AUDIO_S32:
   170         {
   171             const Uint32 *src = (const Uint32 *) cvt->buf;
   172             Uint32 *dst = (Uint32 *) cvt->buf;
   173             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   174                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   175                     const Sint64 added =
   176                         (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
   177                          ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
   178                     *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
   179                 }
   180             } else {
   181                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   182                     const Sint64 added =
   183                         (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
   184                          ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
   185                     *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
   186                 }
   187             }
   188         }
   189         break;
   190 
   191     case AUDIO_F32:
   192         {
   193             const float *src = (const float *) cvt->buf;
   194             float *dst = (float *) cvt->buf;
   195             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   196                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   197                     const float src1 = SDL_SwapFloatBE(src[0]);
   198                     const float src2 = SDL_SwapFloatBE(src[1]);
   199                     const double added = ((double) src1) + ((double) src2);
   200                     const float halved = (float) (added * 0.5);
   201                     *(dst++) = SDL_SwapFloatBE(halved);
   202                 }
   203             } else {
   204                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   205                     const float src1 = SDL_SwapFloatLE(src[0]);
   206                     const float src2 = SDL_SwapFloatLE(src[1]);
   207                     const double added = ((double) src1) + ((double) src2);
   208                     const float halved = (float) (added * 0.5);
   209                     *(dst++) = SDL_SwapFloatLE(halved);
   210                 }
   211             }
   212         }
   213         break;
   214     }
   215 
   216     cvt->len_cvt /= 2;
   217     if (cvt->filters[++cvt->filter_index]) {
   218         cvt->filters[cvt->filter_index] (cvt, format);
   219     }
   220 }
   221 
   222 
   223 /* Discard top 4 channels */
   224 static void SDLCALL
   225 SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   226 {
   227     int i;
   228 
   229 #ifdef DEBUG_CONVERT
   230     fprintf(stderr, "Converting down from 6 channels to stereo\n");
   231 #endif
   232 
   233 #define strip_chans_6_to_2(type) \
   234     { \
   235         const type *src = (const type *) cvt->buf; \
   236         type *dst = (type *) cvt->buf; \
   237         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   238             dst[0] = src[0]; \
   239             dst[1] = src[1]; \
   240             src += 6; \
   241             dst += 2; \
   242         } \
   243     }
   244 
   245     /* this function only cares about typesize, and data as a block of bits. */
   246     switch (SDL_AUDIO_BITSIZE(format)) {
   247     case 8:
   248         strip_chans_6_to_2(Uint8);
   249         break;
   250     case 16:
   251         strip_chans_6_to_2(Uint16);
   252         break;
   253     case 32:
   254         strip_chans_6_to_2(Uint32);
   255         break;
   256     }
   257 
   258 #undef strip_chans_6_to_2
   259 
   260     cvt->len_cvt /= 3;
   261     if (cvt->filters[++cvt->filter_index]) {
   262         cvt->filters[cvt->filter_index] (cvt, format);
   263     }
   264 }
   265 
   266 
   267 /* Discard top 2 channels of 6 */
   268 static void SDLCALL
   269 SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   270 {
   271     int i;
   272 
   273 #ifdef DEBUG_CONVERT
   274     fprintf(stderr, "Converting 6 down to quad\n");
   275 #endif
   276 
   277 #define strip_chans_6_to_4(type) \
   278     { \
   279         const type *src = (const type *) cvt->buf; \
   280         type *dst = (type *) cvt->buf; \
   281         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   282             dst[0] = src[0]; \
   283             dst[1] = src[1]; \
   284             dst[2] = src[2]; \
   285             dst[3] = src[3]; \
   286             src += 6; \
   287             dst += 4; \
   288         } \
   289     }
   290 
   291     /* this function only cares about typesize, and data as a block of bits. */
   292     switch (SDL_AUDIO_BITSIZE(format)) {
   293     case 8:
   294         strip_chans_6_to_4(Uint8);
   295         break;
   296     case 16:
   297         strip_chans_6_to_4(Uint16);
   298         break;
   299     case 32:
   300         strip_chans_6_to_4(Uint32);
   301         break;
   302     }
   303 
   304 #undef strip_chans_6_to_4
   305 
   306     cvt->len_cvt /= 6;
   307     cvt->len_cvt *= 4;
   308     if (cvt->filters[++cvt->filter_index]) {
   309         cvt->filters[cvt->filter_index] (cvt, format);
   310     }
   311 }
   312 
   313 /* Duplicate a mono channel to both stereo channels */
   314 static void SDLCALL
   315 SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   316 {
   317     int i;
   318 
   319 #ifdef DEBUG_CONVERT
   320     fprintf(stderr, "Converting to stereo\n");
   321 #endif
   322 
   323 #define dup_chans_1_to_2(type) \
   324     { \
   325         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   326         type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
   327         for (i = cvt->len_cvt / 2; i; --i, --src) { \
   328             const type val = *src; \
   329             dst -= 2; \
   330             dst[0] = dst[1] = val; \
   331         } \
   332     }
   333 
   334     /* this function only cares about typesize, and data as a block of bits. */
   335     switch (SDL_AUDIO_BITSIZE(format)) {
   336     case 8:
   337         dup_chans_1_to_2(Uint8);
   338         break;
   339     case 16:
   340         dup_chans_1_to_2(Uint16);
   341         break;
   342     case 32:
   343         dup_chans_1_to_2(Uint32);
   344         break;
   345     }
   346 
   347 #undef dup_chans_1_to_2
   348 
   349     cvt->len_cvt *= 2;
   350     if (cvt->filters[++cvt->filter_index]) {
   351         cvt->filters[cvt->filter_index] (cvt, format);
   352     }
   353 }
   354 
   355 
   356 /* Duplicate a stereo channel to a pseudo-5.1 stream */
   357 static void SDLCALL
   358 SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   359 {
   360     int i;
   361 
   362 #ifdef DEBUG_CONVERT
   363     fprintf(stderr, "Converting stereo to surround\n");
   364 #endif
   365 
   366     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   367     case AUDIO_U8:
   368         {
   369             Uint8 *src, *dst, lf, rf, ce;
   370 
   371             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   372             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
   373             for (i = cvt->len_cvt; i; --i) {
   374                 dst -= 6;
   375                 src -= 2;
   376                 lf = src[0];
   377                 rf = src[1];
   378                 ce = (lf / 2) + (rf / 2);
   379                 dst[0] = lf;
   380                 dst[1] = rf;
   381                 dst[2] = lf - ce;
   382                 dst[3] = rf - ce;
   383                 dst[4] = ce;
   384                 dst[5] = ce;
   385             }
   386         }
   387         break;
   388 
   389     case AUDIO_S8:
   390         {
   391             Sint8 *src, *dst, lf, rf, ce;
   392 
   393             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   394             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
   395             for (i = cvt->len_cvt; i; --i) {
   396                 dst -= 6;
   397                 src -= 2;
   398                 lf = src[0];
   399                 rf = src[1];
   400                 ce = (lf / 2) + (rf / 2);
   401                 dst[0] = lf;
   402                 dst[1] = rf;
   403                 dst[2] = lf - ce;
   404                 dst[3] = rf - ce;
   405                 dst[4] = ce;
   406                 dst[5] = ce;
   407             }
   408         }
   409         break;
   410 
   411     case AUDIO_U16:
   412         {
   413             Uint8 *src, *dst;
   414             Uint16 lf, rf, ce, lr, rr;
   415 
   416             src = cvt->buf + cvt->len_cvt;
   417             dst = cvt->buf + cvt->len_cvt * 3;
   418 
   419             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   420                 for (i = cvt->len_cvt / 4; i; --i) {
   421                     dst -= 12;
   422                     src -= 4;
   423                     lf = (Uint16) ((src[0] << 8) | src[1]);
   424                     rf = (Uint16) ((src[2] << 8) | src[3]);
   425                     ce = (lf / 2) + (rf / 2);
   426                     rr = lf - ce;
   427                     lr = rf - ce;
   428                     dst[1] = (lf & 0xFF);
   429                     dst[0] = ((lf >> 8) & 0xFF);
   430                     dst[3] = (rf & 0xFF);
   431                     dst[2] = ((rf >> 8) & 0xFF);
   432 
   433                     dst[1 + 4] = (lr & 0xFF);
   434                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   435                     dst[3 + 4] = (rr & 0xFF);
   436                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   437 
   438                     dst[1 + 8] = (ce & 0xFF);
   439                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   440                     dst[3 + 8] = (ce & 0xFF);
   441                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   442                 }
   443             } else {
   444                 for (i = cvt->len_cvt / 4; i; --i) {
   445                     dst -= 12;
   446                     src -= 4;
   447                     lf = (Uint16) ((src[1] << 8) | src[0]);
   448                     rf = (Uint16) ((src[3] << 8) | src[2]);
   449                     ce = (lf / 2) + (rf / 2);
   450                     rr = lf - ce;
   451                     lr = rf - ce;
   452                     dst[0] = (lf & 0xFF);
   453                     dst[1] = ((lf >> 8) & 0xFF);
   454                     dst[2] = (rf & 0xFF);
   455                     dst[3] = ((rf >> 8) & 0xFF);
   456 
   457                     dst[0 + 4] = (lr & 0xFF);
   458                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   459                     dst[2 + 4] = (rr & 0xFF);
   460                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   461 
   462                     dst[0 + 8] = (ce & 0xFF);
   463                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   464                     dst[2 + 8] = (ce & 0xFF);
   465                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   466                 }
   467             }
   468         }
   469         break;
   470 
   471     case AUDIO_S16:
   472         {
   473             Uint8 *src, *dst;
   474             Sint16 lf, rf, ce, lr, rr;
   475 
   476             src = cvt->buf + cvt->len_cvt;
   477             dst = cvt->buf + cvt->len_cvt * 3;
   478 
   479             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   480                 for (i = cvt->len_cvt / 4; i; --i) {
   481                     dst -= 12;
   482                     src -= 4;
   483                     lf = (Sint16) ((src[0] << 8) | src[1]);
   484                     rf = (Sint16) ((src[2] << 8) | src[3]);
   485                     ce = (lf / 2) + (rf / 2);
   486                     rr = lf - ce;
   487                     lr = rf - ce;
   488                     dst[1] = (lf & 0xFF);
   489                     dst[0] = ((lf >> 8) & 0xFF);
   490                     dst[3] = (rf & 0xFF);
   491                     dst[2] = ((rf >> 8) & 0xFF);
   492 
   493                     dst[1 + 4] = (lr & 0xFF);
   494                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   495                     dst[3 + 4] = (rr & 0xFF);
   496                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   497 
   498                     dst[1 + 8] = (ce & 0xFF);
   499                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   500                     dst[3 + 8] = (ce & 0xFF);
   501                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   502                 }
   503             } else {
   504                 for (i = cvt->len_cvt / 4; i; --i) {
   505                     dst -= 12;
   506                     src -= 4;
   507                     lf = (Sint16) ((src[1] << 8) | src[0]);
   508                     rf = (Sint16) ((src[3] << 8) | src[2]);
   509                     ce = (lf / 2) + (rf / 2);
   510                     rr = lf - ce;
   511                     lr = rf - ce;
   512                     dst[0] = (lf & 0xFF);
   513                     dst[1] = ((lf >> 8) & 0xFF);
   514                     dst[2] = (rf & 0xFF);
   515                     dst[3] = ((rf >> 8) & 0xFF);
   516 
   517                     dst[0 + 4] = (lr & 0xFF);
   518                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   519                     dst[2 + 4] = (rr & 0xFF);
   520                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   521 
   522                     dst[0 + 8] = (ce & 0xFF);
   523                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   524                     dst[2 + 8] = (ce & 0xFF);
   525                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   526                 }
   527             }
   528         }
   529         break;
   530 
   531     case AUDIO_S32:
   532         {
   533             Sint32 lf, rf, ce;
   534             const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
   535             Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
   536 
   537             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   538                 for (i = cvt->len_cvt / 8; i; --i) {
   539                     dst -= 6;
   540                     src -= 2;
   541                     lf = (Sint32) SDL_SwapBE32(src[0]);
   542                     rf = (Sint32) SDL_SwapBE32(src[1]);
   543                     ce = (lf / 2) + (rf / 2);
   544                     dst[0] = SDL_SwapBE32((Uint32) lf);
   545                     dst[1] = SDL_SwapBE32((Uint32) rf);
   546                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   547                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   548                     dst[4] = SDL_SwapBE32((Uint32) ce);
   549                     dst[5] = SDL_SwapBE32((Uint32) ce);
   550                 }
   551             } else {
   552                 for (i = cvt->len_cvt / 8; i; --i) {
   553                     dst -= 6;
   554                     src -= 2;
   555                     lf = (Sint32) SDL_SwapLE32(src[0]);
   556                     rf = (Sint32) SDL_SwapLE32(src[1]);
   557                     ce = (lf / 2) + (rf / 2);
   558                     dst[0] = src[0];
   559                     dst[1] = src[1];
   560                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   561                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   562                     dst[4] = SDL_SwapLE32((Uint32) ce);
   563                     dst[5] = SDL_SwapLE32((Uint32) ce);
   564                 }
   565             }
   566         }
   567         break;
   568 
   569     case AUDIO_F32:
   570         {
   571             float lf, rf, ce;
   572             const float *src = (const float *) cvt->buf + cvt->len_cvt;
   573             float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
   574 
   575             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   576                 for (i = cvt->len_cvt / 8; i; --i) {
   577                     dst -= 6;
   578                     src -= 2;
   579                     lf = SDL_SwapFloatBE(src[0]);
   580                     rf = SDL_SwapFloatBE(src[1]);
   581                     ce = (lf * 0.5f) + (rf * 0.5f);
   582                     dst[0] = src[0];
   583                     dst[1] = src[1];
   584                     dst[2] = SDL_SwapFloatBE(lf - ce);
   585                     dst[3] = SDL_SwapFloatBE(rf - ce);
   586                     dst[4] = dst[5] = SDL_SwapFloatBE(ce);
   587                 }
   588             } else {
   589                 for (i = cvt->len_cvt / 8; i; --i) {
   590                     dst -= 6;
   591                     src -= 2;
   592                     lf = SDL_SwapFloatLE(src[0]);
   593                     rf = SDL_SwapFloatLE(src[1]);
   594                     ce = (lf * 0.5f) + (rf * 0.5f);
   595                     dst[0] = src[0];
   596                     dst[1] = src[1];
   597                     dst[2] = SDL_SwapFloatLE(lf - ce);
   598                     dst[3] = SDL_SwapFloatLE(rf - ce);
   599                     dst[4] = dst[5] = SDL_SwapFloatLE(ce);
   600                 }
   601             }
   602         }
   603         break;
   604 
   605     }
   606     cvt->len_cvt *= 3;
   607     if (cvt->filters[++cvt->filter_index]) {
   608         cvt->filters[cvt->filter_index] (cvt, format);
   609     }
   610 }
   611 
   612 
   613 /* Duplicate a stereo channel to a pseudo-4.0 stream */
   614 static void SDLCALL
   615 SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   616 {
   617     int i;
   618 
   619 #ifdef DEBUG_CONVERT
   620     fprintf(stderr, "Converting stereo to quad\n");
   621 #endif
   622 
   623     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   624     case AUDIO_U8:
   625         {
   626             Uint8 *src, *dst, lf, rf, ce;
   627 
   628             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   629             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
   630             for (i = cvt->len_cvt; i; --i) {
   631                 dst -= 4;
   632                 src -= 2;
   633                 lf = src[0];
   634                 rf = src[1];
   635                 ce = (lf / 2) + (rf / 2);
   636                 dst[0] = lf;
   637                 dst[1] = rf;
   638                 dst[2] = lf - ce;
   639                 dst[3] = rf - ce;
   640             }
   641         }
   642         break;
   643 
   644     case AUDIO_S8:
   645         {
   646             Sint8 *src, *dst, lf, rf, ce;
   647 
   648             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   649             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
   650             for (i = cvt->len_cvt; i; --i) {
   651                 dst -= 4;
   652                 src -= 2;
   653                 lf = src[0];
   654                 rf = src[1];
   655                 ce = (lf / 2) + (rf / 2);
   656                 dst[0] = lf;
   657                 dst[1] = rf;
   658                 dst[2] = lf - ce;
   659                 dst[3] = rf - ce;
   660             }
   661         }
   662         break;
   663 
   664     case AUDIO_U16:
   665         {
   666             Uint8 *src, *dst;
   667             Uint16 lf, rf, ce, lr, rr;
   668 
   669             src = cvt->buf + cvt->len_cvt;
   670             dst = cvt->buf + cvt->len_cvt * 2;
   671 
   672             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   673                 for (i = cvt->len_cvt / 4; i; --i) {
   674                     dst -= 8;
   675                     src -= 4;
   676                     lf = (Uint16) ((src[0] << 8) | src[1]);
   677                     rf = (Uint16) ((src[2] << 8) | src[3]);
   678                     ce = (lf / 2) + (rf / 2);
   679                     rr = lf - ce;
   680                     lr = rf - ce;
   681                     dst[1] = (lf & 0xFF);
   682                     dst[0] = ((lf >> 8) & 0xFF);
   683                     dst[3] = (rf & 0xFF);
   684                     dst[2] = ((rf >> 8) & 0xFF);
   685 
   686                     dst[1 + 4] = (lr & 0xFF);
   687                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   688                     dst[3 + 4] = (rr & 0xFF);
   689                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   690                 }
   691             } else {
   692                 for (i = cvt->len_cvt / 4; i; --i) {
   693                     dst -= 8;
   694                     src -= 4;
   695                     lf = (Uint16) ((src[1] << 8) | src[0]);
   696                     rf = (Uint16) ((src[3] << 8) | src[2]);
   697                     ce = (lf / 2) + (rf / 2);
   698                     rr = lf - ce;
   699                     lr = rf - ce;
   700                     dst[0] = (lf & 0xFF);
   701                     dst[1] = ((lf >> 8) & 0xFF);
   702                     dst[2] = (rf & 0xFF);
   703                     dst[3] = ((rf >> 8) & 0xFF);
   704 
   705                     dst[0 + 4] = (lr & 0xFF);
   706                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   707                     dst[2 + 4] = (rr & 0xFF);
   708                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   709                 }
   710             }
   711         }
   712         break;
   713 
   714     case AUDIO_S16:
   715         {
   716             Uint8 *src, *dst;
   717             Sint16 lf, rf, ce, lr, rr;
   718 
   719             src = cvt->buf + cvt->len_cvt;
   720             dst = cvt->buf + cvt->len_cvt * 2;
   721 
   722             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   723                 for (i = cvt->len_cvt / 4; i; --i) {
   724                     dst -= 8;
   725                     src -= 4;
   726                     lf = (Sint16) ((src[0] << 8) | src[1]);
   727                     rf = (Sint16) ((src[2] << 8) | src[3]);
   728                     ce = (lf / 2) + (rf / 2);
   729                     rr = lf - ce;
   730                     lr = rf - ce;
   731                     dst[1] = (lf & 0xFF);
   732                     dst[0] = ((lf >> 8) & 0xFF);
   733                     dst[3] = (rf & 0xFF);
   734                     dst[2] = ((rf >> 8) & 0xFF);
   735 
   736                     dst[1 + 4] = (lr & 0xFF);
   737                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   738                     dst[3 + 4] = (rr & 0xFF);
   739                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   740                 }
   741             } else {
   742                 for (i = cvt->len_cvt / 4; i; --i) {
   743                     dst -= 8;
   744                     src -= 4;
   745                     lf = (Sint16) ((src[1] << 8) | src[0]);
   746                     rf = (Sint16) ((src[3] << 8) | src[2]);
   747                     ce = (lf / 2) + (rf / 2);
   748                     rr = lf - ce;
   749                     lr = rf - ce;
   750                     dst[0] = (lf & 0xFF);
   751                     dst[1] = ((lf >> 8) & 0xFF);
   752                     dst[2] = (rf & 0xFF);
   753                     dst[3] = ((rf >> 8) & 0xFF);
   754 
   755                     dst[0 + 4] = (lr & 0xFF);
   756                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   757                     dst[2 + 4] = (rr & 0xFF);
   758                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   759                 }
   760             }
   761         }
   762         break;
   763 
   764     case AUDIO_S32:
   765         {
   766             const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
   767             Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
   768             Sint32 lf, rf, ce;
   769 
   770             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   771                 for (i = cvt->len_cvt / 8; i; --i) {
   772                     dst -= 4;
   773                     src -= 2;
   774                     lf = (Sint32) SDL_SwapBE32(src[0]);
   775                     rf = (Sint32) SDL_SwapBE32(src[1]);
   776                     ce = (lf / 2) + (rf / 2);
   777                     dst[0] = src[0];
   778                     dst[1] = src[1];
   779                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   780                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   781                 }
   782             } else {
   783                 for (i = cvt->len_cvt / 8; i; --i) {
   784                     dst -= 4;
   785                     src -= 2;
   786                     lf = (Sint32) SDL_SwapLE32(src[0]);
   787                     rf = (Sint32) SDL_SwapLE32(src[1]);
   788                     ce = (lf / 2) + (rf / 2);
   789                     dst[0] = src[0];
   790                     dst[1] = src[1];
   791                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   792                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   793                 }
   794             }
   795         }
   796         break;
   797     }
   798     cvt->len_cvt *= 2;
   799     if (cvt->filters[++cvt->filter_index]) {
   800         cvt->filters[cvt->filter_index] (cvt, format);
   801     }
   802 }
   803 
   804 /* Convert rate up by multiple of 2 */
   805 static void SDLCALL
   806 SDL_RateMUL2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   807 {
   808     int i;
   809 
   810 #ifdef DEBUG_CONVERT
   811     fprintf(stderr, "Converting audio rate * 2 (mono)\n");
   812 #endif
   813 
   814 #define mul2_mono(type) { \
   815         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   816         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   817         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
   818             src--; \
   819             dst[-1] = dst[-2] = src[0]; \
   820             dst -= 2; \
   821         } \
   822     }
   823 
   824     switch (SDL_AUDIO_BITSIZE(format)) {
   825     case 8:
   826         mul2_mono(Uint8);
   827         break;
   828     case 16:
   829         mul2_mono(Uint16);
   830         break;
   831     case 32:
   832         mul2_mono(Uint32);
   833         break;
   834     }
   835 
   836 #undef mul2_mono
   837 
   838     cvt->len_cvt *= 2;
   839     if (cvt->filters[++cvt->filter_index]) {
   840         cvt->filters[cvt->filter_index] (cvt, format);
   841     }
   842 }
   843 
   844 
   845 /* Convert rate up by multiple of 2, for stereo */
   846 static void SDLCALL
   847 SDL_RateMUL2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   848 {
   849     int i;
   850 
   851 #ifdef DEBUG_CONVERT
   852     fprintf(stderr, "Converting audio rate * 2 (stereo)\n");
   853 #endif
   854 
   855 #define mul2_stereo(type) { \
   856         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   857         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   858         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   859             const type r = src[-1]; \
   860             const type l = src[-2]; \
   861             src -= 2; \
   862             dst[-1] = r; \
   863             dst[-2] = l; \
   864             dst[-3] = r; \
   865             dst[-4] = l; \
   866             dst -= 4; \
   867         } \
   868     }
   869 
   870     switch (SDL_AUDIO_BITSIZE(format)) {
   871     case 8:
   872         mul2_stereo(Uint8);
   873         break;
   874     case 16:
   875         mul2_stereo(Uint16);
   876         break;
   877     case 32:
   878         mul2_stereo(Uint32);
   879         break;
   880     }
   881 
   882 #undef mul2_stereo
   883 
   884     cvt->len_cvt *= 2;
   885     if (cvt->filters[++cvt->filter_index]) {
   886         cvt->filters[cvt->filter_index] (cvt, format);
   887     }
   888 }
   889 
   890 /* Convert rate up by multiple of 2, for quad */
   891 static void SDLCALL
   892 SDL_RateMUL2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   893 {
   894     int i;
   895 
   896 #ifdef DEBUG_CONVERT
   897     fprintf(stderr, "Converting audio rate * 2 (quad)\n");
   898 #endif
   899 
   900 #define mul2_quad(type) { \
   901         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   902         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   903         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
   904             const type c1 = src[-1]; \
   905             const type c2 = src[-2]; \
   906             const type c3 = src[-3]; \
   907             const type c4 = src[-4]; \
   908             src -= 4; \
   909             dst[-1] = c1; \
   910             dst[-2] = c2; \
   911             dst[-3] = c3; \
   912             dst[-4] = c4; \
   913             dst[-5] = c1; \
   914             dst[-6] = c2; \
   915             dst[-7] = c3; \
   916             dst[-8] = c4; \
   917             dst -= 8; \
   918         } \
   919     }
   920 
   921     switch (SDL_AUDIO_BITSIZE(format)) {
   922     case 8:
   923         mul2_quad(Uint8);
   924         break;
   925     case 16:
   926         mul2_quad(Uint16);
   927         break;
   928     case 32:
   929         mul2_quad(Uint32);
   930         break;
   931     }
   932 
   933 #undef mul2_quad
   934 
   935     cvt->len_cvt *= 2;
   936     if (cvt->filters[++cvt->filter_index]) {
   937         cvt->filters[cvt->filter_index] (cvt, format);
   938     }
   939 }
   940 
   941 
   942 /* Convert rate up by multiple of 2, for 5.1 */
   943 static void SDLCALL
   944 SDL_RateMUL2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   945 {
   946     int i;
   947 
   948 #ifdef DEBUG_CONVERT
   949     fprintf(stderr, "Converting audio rate * 2 (six channels)\n");
   950 #endif
   951 
   952 #define mul2_chansix(type) { \
   953         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   954         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   955         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   956             const type c1 = src[-1]; \
   957             const type c2 = src[-2]; \
   958             const type c3 = src[-3]; \
   959             const type c4 = src[-4]; \
   960             const type c5 = src[-5]; \
   961             const type c6 = src[-6]; \
   962             src -= 6; \
   963             dst[-1] = c1; \
   964             dst[-2] = c2; \
   965             dst[-3] = c3; \
   966             dst[-4] = c4; \
   967             dst[-5] = c5; \
   968             dst[-6] = c6; \
   969             dst[-7] = c1; \
   970             dst[-8] = c2; \
   971             dst[-9] = c3; \
   972             dst[-10] = c4; \
   973             dst[-11] = c5; \
   974             dst[-12] = c6; \
   975             dst -= 12; \
   976         } \
   977     }
   978 
   979     switch (SDL_AUDIO_BITSIZE(format)) {
   980     case 8:
   981         mul2_chansix(Uint8);
   982         break;
   983     case 16:
   984         mul2_chansix(Uint16);
   985         break;
   986     case 32:
   987         mul2_chansix(Uint32);
   988         break;
   989     }
   990 
   991 #undef mul2_chansix
   992 
   993     cvt->len_cvt *= 2;
   994     if (cvt->filters[++cvt->filter_index]) {
   995         cvt->filters[cvt->filter_index] (cvt, format);
   996     }
   997 }
   998 
   999 /* Convert rate down by multiple of 2 */
  1000 static void SDLCALL
  1001 SDL_RateDIV2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1002 {
  1003     int i;
  1004 
  1005 #ifdef DEBUG_CONVERT
  1006     fprintf(stderr, "Converting audio rate / 2 (mono)\n");
  1007 #endif
  1008 
  1009 #define div2_mono(type) { \
  1010         const type *src = (const type *) cvt->buf; \
  1011         type *dst = (type *) cvt->buf; \
  1012         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
  1013             dst[0] = src[0]; \
  1014             src += 2; \
  1015             dst++; \
  1016         } \
  1017     }
  1018 
  1019     switch (SDL_AUDIO_BITSIZE(format)) {
  1020     case 8:
  1021         div2_mono(Uint8);
  1022         break;
  1023     case 16:
  1024         div2_mono(Uint16);
  1025         break;
  1026     case 32:
  1027         div2_mono(Uint32);
  1028         break;
  1029     }
  1030 
  1031 #undef div2_mono
  1032 
  1033     cvt->len_cvt /= 2;
  1034     if (cvt->filters[++cvt->filter_index]) {
  1035         cvt->filters[cvt->filter_index] (cvt, format);
  1036     }
  1037 }
  1038 
  1039 
  1040 /* Convert rate down by multiple of 2, for stereo */
  1041 static void SDLCALL
  1042 SDL_RateDIV2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1043 {
  1044     int i;
  1045 
  1046 #ifdef DEBUG_CONVERT
  1047     fprintf(stderr, "Converting audio rate / 2 (stereo)\n");
  1048 #endif
  1049 
  1050 #define div2_stereo(type) { \
  1051         const type *src = (const type *) cvt->buf; \
  1052         type *dst = (type *) cvt->buf; \
  1053         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
  1054             dst[0] = src[0]; \
  1055             dst[1] = src[1]; \
  1056             src += 4; \
  1057             dst += 2; \
  1058         } \
  1059     }
  1060 
  1061     switch (SDL_AUDIO_BITSIZE(format)) {
  1062     case 8:
  1063         div2_stereo(Uint8);
  1064         break;
  1065     case 16:
  1066         div2_stereo(Uint16);
  1067         break;
  1068     case 32:
  1069         div2_stereo(Uint32);
  1070         break;
  1071     }
  1072 
  1073 #undef div2_stereo
  1074 
  1075     cvt->len_cvt /= 2;
  1076     if (cvt->filters[++cvt->filter_index]) {
  1077         cvt->filters[cvt->filter_index] (cvt, format);
  1078     }
  1079 }
  1080 
  1081 
  1082 /* Convert rate down by multiple of 2, for quad */
  1083 static void SDLCALL
  1084 SDL_RateDIV2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1085 {
  1086     int i;
  1087 
  1088 #ifdef DEBUG_CONVERT
  1089     fprintf(stderr, "Converting audio rate / 2 (quad)\n");
  1090 #endif
  1091 
  1092 #define div2_quad(type) { \
  1093         const type *src = (const type *) cvt->buf; \
  1094         type *dst = (type *) cvt->buf; \
  1095         for (i = cvt->len_cvt / (sizeof (type) * 8); i; --i) { \
  1096             dst[0] = src[0]; \
  1097             dst[1] = src[1]; \
  1098             dst[2] = src[2]; \
  1099             dst[3] = src[3]; \
  1100             src += 8; \
  1101             dst += 4; \
  1102         } \
  1103     }
  1104 
  1105     switch (SDL_AUDIO_BITSIZE(format)) {
  1106     case 8:
  1107         div2_quad(Uint8);
  1108         break;
  1109     case 16:
  1110         div2_quad(Uint16);
  1111         break;
  1112     case 32:
  1113         div2_quad(Uint32);
  1114         break;
  1115     }
  1116 
  1117 #undef div2_quad
  1118 
  1119     cvt->len_cvt /= 2;
  1120     if (cvt->filters[++cvt->filter_index]) {
  1121         cvt->filters[cvt->filter_index] (cvt, format);
  1122     }
  1123 }
  1124 
  1125 /* Convert rate down by multiple of 2, for 5.1 */
  1126 static void SDLCALL
  1127 SDL_RateDIV2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1128 {
  1129     int i;
  1130 
  1131 #ifdef DEBUG_CONVERT
  1132     fprintf(stderr, "Converting audio rate / 2 (six channels)\n");
  1133 #endif
  1134 
  1135 #define div2_chansix(type) { \
  1136         const type *src = (const type *) cvt->buf; \
  1137         type *dst = (type *) cvt->buf; \
  1138         for (i = cvt->len_cvt / (sizeof (type) * 12); i; --i) { \
  1139             dst[0] = src[0]; \
  1140             dst[1] = src[1]; \
  1141             dst[2] = src[2]; \
  1142             dst[3] = src[3]; \
  1143             dst[4] = src[4]; \
  1144             dst[5] = src[5]; \
  1145             src += 12; \
  1146             dst += 6; \
  1147         } \
  1148     }
  1149 
  1150     switch (SDL_AUDIO_BITSIZE(format)) {
  1151     case 8:
  1152         div2_chansix(Uint8);
  1153         break;
  1154     case 16:
  1155         div2_chansix(Uint16);
  1156         break;
  1157     case 32:
  1158         div2_chansix(Uint32);
  1159         break;
  1160     }
  1161 
  1162 #undef div_chansix
  1163 
  1164     cvt->len_cvt /= 2;
  1165     if (cvt->filters[++cvt->filter_index]) {
  1166         cvt->filters[cvt->filter_index] (cvt, format);
  1167     }
  1168 }
  1169 
  1170 /* Very slow rate conversion routine */
  1171 static void SDLCALL
  1172 SDL_RateSLOW(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1173 {
  1174     double ipos;
  1175     int i, clen;
  1176 
  1177 #ifdef DEBUG_CONVERT
  1178     fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
  1179 #endif
  1180     clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
  1181     if (cvt->rate_incr > 1.0) {
  1182         switch (SDL_AUDIO_BITSIZE(format)) {
  1183         case 8:
  1184             {
  1185                 Uint8 *output;
  1186 
  1187                 output = cvt->buf;
  1188                 ipos = 0.0;
  1189                 for (i = clen; i; --i) {
  1190                     *output = cvt->buf[(int) ipos];
  1191                     ipos += cvt->rate_incr;
  1192                     output += 1;
  1193                 }
  1194             }
  1195             break;
  1196 
  1197         case 16:
  1198             {
  1199                 Uint16 *output;
  1200 
  1201                 clen &= ~1;
  1202                 output = (Uint16 *) cvt->buf;
  1203                 ipos = 0.0;
  1204                 for (i = clen / 2; i; --i) {
  1205                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1206                     ipos += cvt->rate_incr;
  1207                     output += 1;
  1208                 }
  1209             }
  1210             break;
  1211 
  1212         case 32:
  1213             {
  1214                 /* !!! FIXME: need 32-bit converter here! */
  1215 #ifdef DEBUG_CONVERT
  1216                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1217 #endif
  1218             }
  1219         }
  1220     } else {
  1221         switch (SDL_AUDIO_BITSIZE(format)) {
  1222         case 8:
  1223             {
  1224                 Uint8 *output;
  1225 
  1226                 output = cvt->buf + clen;
  1227                 ipos = (double) cvt->len_cvt;
  1228                 for (i = clen; i; --i) {
  1229                     ipos -= cvt->rate_incr;
  1230                     output -= 1;
  1231                     *output = cvt->buf[(int) ipos];
  1232                 }
  1233             }
  1234             break;
  1235 
  1236         case 16:
  1237             {
  1238                 Uint16 *output;
  1239 
  1240                 clen &= ~1;
  1241                 output = (Uint16 *) (cvt->buf + clen);
  1242                 ipos = (double) cvt->len_cvt / 2;
  1243                 for (i = clen / 2; i; --i) {
  1244                     ipos -= cvt->rate_incr;
  1245                     output -= 1;
  1246                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1247                 }
  1248             }
  1249             break;
  1250 
  1251         case 32:
  1252             {
  1253                 /* !!! FIXME: need 32-bit converter here! */
  1254 #ifdef DEBUG_CONVERT
  1255                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1256 #endif
  1257             }
  1258         }
  1259     }
  1260 
  1261     cvt->len_cvt = clen;
  1262     if (cvt->filters[++cvt->filter_index]) {
  1263         cvt->filters[cvt->filter_index] (cvt, format);
  1264     }
  1265 }
  1266 
  1267 int
  1268 SDL_ConvertAudio(SDL_AudioCVT * cvt)
  1269 {
  1270     /* Make sure there's data to convert */
  1271     if (cvt->buf == NULL) {
  1272         SDL_SetError("No buffer allocated for conversion");
  1273         return (-1);
  1274     }
  1275     /* Return okay if no conversion is necessary */
  1276     cvt->len_cvt = cvt->len;
  1277     if (cvt->filters[0] == NULL) {
  1278         return (0);
  1279     }
  1280 
  1281     /* Set up the conversion and go! */
  1282     cvt->filter_index = 0;
  1283     cvt->filters[0] (cvt, cvt->src_format);
  1284     return (0);
  1285 }
  1286 
  1287 
  1288 static SDL_AudioFilter
  1289 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1290 {
  1291     /*
  1292      * Fill in any future conversions that are specialized to a
  1293      *  processor, platform, compiler, or library here.
  1294      */
  1295 
  1296     return NULL;                /* no specialized converter code available. */
  1297 }
  1298 
  1299 
  1300 /*
  1301  * Find a converter between two data types. We try to select a hand-tuned
  1302  *  asm/vectorized/optimized function first, and then fallback to an
  1303  *  autogenerated function that is customized to convert between two
  1304  *  specific data types.
  1305  */
  1306 static int
  1307 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
  1308                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1309 {
  1310     if (src_fmt != dst_fmt) {
  1311         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
  1312         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
  1313         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
  1314 
  1315         /* No hand-tuned converter? Try the autogenerated ones. */
  1316         if (filter == NULL) {
  1317             int i;
  1318             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
  1319                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
  1320                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
  1321                     filter = filt->filter;
  1322                     break;
  1323                 }
  1324             }
  1325 
  1326             if (filter == NULL) {
  1327                 return -1;      /* Still no matching converter?! */
  1328             }
  1329         }
  1330 
  1331         /* Update (cvt) with filter details... */
  1332         cvt->filters[cvt->filter_index++] = filter;
  1333         if (src_bitsize < dst_bitsize) {
  1334             const int mult = (dst_bitsize / src_bitsize);
  1335             cvt->len_mult *= mult;
  1336             cvt->len_ratio *= mult;
  1337         } else if (src_bitsize > dst_bitsize) {
  1338             cvt->len_ratio /= (src_bitsize / dst_bitsize);
  1339         }
  1340 
  1341         return 1;               /* added a converter. */
  1342     }
  1343 
  1344     return 0;                   /* no conversion necessary. */
  1345 }
  1346 
  1347 /* Generate the necessary IIR lowpass coefficients for resampling.
  1348    Assume that the SDL_AudioCVT struct is already set up with
  1349    the correct values for len_mult and len_div, and use the
  1350    type of dst_format. Also assume the buffer is allocated.
  1351    Note the buffer needs to be 6 units long.
  1352    For now, use RBJ's cookbook coefficients. It might be more
  1353    optimal to create a Butterworth filter, but this is more difficult.
  1354 */
  1355 int
  1356 SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1357 {
  1358     float fc;                   /* cutoff frequency */
  1359     float coeff[6];             /* floating point iir coefficients b0, b1, b2, a0, a1, a2 */
  1360     float scale;
  1361     float w0, alpha, cosw0;
  1362     int i;
  1363 
  1364     /* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */
  1365     static const float Q = 5.0f;
  1366     static const float CUTOFF = 0.4f;
  1367 
  1368     fc = (cvt->len_mult >
  1369           cvt->len_div) ? CUTOFF / (float) cvt->len_mult : CUTOFF /
  1370         (float) cvt->len_div;
  1371 
  1372     w0 = 2.0f * M_PI * fc;
  1373     cosw0 = cosf(w0);
  1374     alpha = sinf(w0) / (2.0f * Q);
  1375 
  1376     /* Compute coefficients, normalizing by a0 */
  1377     scale = 1.0f / (1.0f + alpha);
  1378 
  1379     coeff[0] = (1.0f - cosw0) / 2.0f * scale;
  1380     coeff[1] = (1.0f - cosw0) * scale;
  1381     coeff[2] = coeff[0];
  1382 
  1383     coeff[3] = 1.0f;            /* a0 is normalized to 1 */
  1384     coeff[4] = -2.0f * cosw0 * scale;
  1385     coeff[5] = (1.0f - alpha) * scale;
  1386 
  1387     /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */
  1388 #define convert_fixed(type, fix) { \
  1389             type *cvt_coeff = (type *)cvt->coeff; \
  1390             for(i = 0; i < 6; ++i) { \
  1391                 cvt_coeff[i] = fix(coeff[i]); \
  1392             } \
  1393         }
  1394 
  1395     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1396         float *cvt_coeff = (float *) cvt->coeff;
  1397         for (i = 0; i < 6; ++i) {
  1398             cvt_coeff[i] = coeff[i];
  1399         }
  1400     } else {
  1401         switch (SDL_AUDIO_BITSIZE(format)) {
  1402         case 8:
  1403             convert_fixed(Uint8, SDL_Make_2_6);
  1404             break;
  1405         case 16:
  1406             convert_fixed(Uint16, SDL_Make_2_14);
  1407             break;
  1408         case 32:
  1409             convert_fixed(Uint32, SDL_Make_2_30);
  1410             break;
  1411         }
  1412     }
  1413 
  1414 #ifdef DEBUG_CONVERT
  1415 #define debug_iir(type) { \
  1416             type *cvt_coeff = (type *)cvt->coeff; \
  1417             for(i = 0; i < 6; ++i) { \
  1418                 printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \
  1419             } \
  1420         }
  1421     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1422         float *cvt_coeff = (float *) cvt->coeff;
  1423         for (i = 0; i < 6; ++i) {
  1424             printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]);
  1425         }
  1426     } else {
  1427         switch (SDL_AUDIO_BITSIZE(format)) {
  1428         case 8:
  1429             debug_iir(Uint8);
  1430             break;
  1431         case 16:
  1432             debug_iir(Uint16);
  1433             break;
  1434         case 32:
  1435             debug_iir(Uint32);
  1436             break;
  1437         }
  1438     }
  1439 #undef debug_iir
  1440 #endif
  1441 
  1442     /* Initialize the state buffer to all zeroes, and set initial position */
  1443     SDL_memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4);
  1444     cvt->state_pos = 0;
  1445 #undef convert_fixed
  1446 }
  1447 
  1448 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
  1449 /* This was implemented because it would be much faster than the fir filter, 
  1450    but it doesn't seem to have a steep enough cutoff so we'd need several
  1451    cascaded biquads, which probably isn't a great idea. Therefore, this
  1452    function can probably be discarded.
  1453 */
  1454 static void
  1455 SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1456 {
  1457     Uint32 i, n;
  1458 
  1459     /* TODO: Check that n is calculated right */
  1460     n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
  1461 
  1462     /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? The right shift temp = buf[n] >> 1 needs to depend on whether the type is signed or not for sign extension. */
  1463     /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
  1464 #define iir_fix(type, mult) {\
  1465             type *coeff = (type *)cvt->coeff; \
  1466             type *state = (type *)cvt->state_buf; \
  1467             type *buf = (type *)cvt->buf; \
  1468             type temp; \
  1469             for(i = 0; i < n; ++i) { \
  1470                     temp = buf[i] >> 1; \
  1471                     if(cvt->state_pos) { \
  1472                         buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
  1473                         state[1] = temp; \
  1474                         state[3] = buf[i]; \
  1475                         cvt->state_pos = 0; \
  1476                     } else { \
  1477                         buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[1]) + mult(coeff[2], state[0]) - mult(coeff[4], state[3]) - mult(coeff[5], state[2]); \
  1478                         state[0] = temp; \
  1479                         state[2] = buf[i]; \
  1480                         cvt->state_pos = 1; \
  1481                     } \
  1482                 } \
  1483         }
  1484 /* Need to test to see if the previous method or this one is faster */
  1485 /*#define iir_fix(type, mult) {\
  1486             type *coeff = (type *)cvt->coeff; \
  1487             type *state = (type *)cvt->state_buf; \
  1488             type *buf = (type *)cvt->buf; \
  1489             type temp; \
  1490             for(i = 0; i < n; ++i) { \
  1491                     temp = buf[i] >> 1; \
  1492                     buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
  1493                     state[1] = state[0]; \
  1494                     state[0] = temp; \
  1495                     state[3] = state[2]; \
  1496                     state[2] = buf[i]; \
  1497                 } \
  1498         }*/
  1499 
  1500     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1501         float *coeff = (float *) cvt->coeff;
  1502         float *state = (float *) cvt->state_buf;
  1503         float *buf = (float *) cvt->buf;
  1504         float temp;
  1505 
  1506         for (i = 0; i < n; ++i) {
  1507             /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
  1508             temp = buf[i];
  1509             if (cvt->state_pos) {
  1510                 buf[i] =
  1511                     coeff[0] * buf[n] + coeff[1] * state[0] +
  1512                     coeff[2] * state[1] - coeff[4] * state[2] -
  1513                     coeff[5] * state[3];
  1514                 state[1] = temp;
  1515                 state[3] = buf[i];
  1516                 cvt->state_pos = 0;
  1517             } else {
  1518                 buf[i] =
  1519                     coeff[0] * buf[n] + coeff[1] * state[1] +
  1520                     coeff[2] * state[0] - coeff[4] * state[3] -
  1521                     coeff[5] * state[2];
  1522                 state[0] = temp;
  1523                 state[2] = buf[i];
  1524                 cvt->state_pos = 1;
  1525             }
  1526         }
  1527     } else {
  1528         /* Treat everything as signed! */
  1529         switch (SDL_AUDIO_BITSIZE(format)) {
  1530         case 8:
  1531             iir_fix(Sint8, SDL_FixMpy8);
  1532             break;
  1533         case 16:
  1534             iir_fix(Sint16, SDL_FixMpy16);
  1535             break;
  1536         case 32:
  1537             iir_fix(Sint32, SDL_FixMpy32);
  1538             break;
  1539         }
  1540     }
  1541 #undef iir_fix
  1542 }
  1543 
  1544 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct.
  1545 */
  1546 static void
  1547 SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1548 {
  1549     int n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
  1550     int m = cvt->len_sinc;
  1551     int i, j;
  1552 
  1553     /* 
  1554        Note: We can make a big optimization here by taking advantage
  1555        of the fact that the signal is zero stuffed, so we can do
  1556        significantly fewer multiplications and additions. However, this
  1557        depends on the zero stuffing ratio, so it may not pay off. This would
  1558        basically be a polyphase filter.
  1559      */
  1560     /* One other way to do this fast is to look at the fir filter from a different angle:
  1561        After we zero stuff, we have input of all zeroes, except for every len_mult
  1562        sample. If we choose a sinc length equal to len_mult, then the fir filter becomes
  1563        much more simple: we're just taking a windowed sinc, shifting it to start at each
  1564        len_mult sample, and scaling it by the value of that sample. If we do this, then
  1565        we don't even need to worry about the sample histories, and the inner loop here is
  1566        unnecessary. This probably sacrifices some quality but could really speed things up as well.
  1567      */
  1568     /* We only calculate the values of samples which are 0 (mod len_div) because
  1569        those are the only ones used. All the other ones are discarded in the
  1570        third step of resampling. This is a huge speedup. As a warning, though,
  1571        if for some reason this is used elsewhere where there are no samples discarded,
  1572        the output will not be corrrect if len_div is not 1. To make this filter a
  1573        generic FIR filter, simply remove the if statement "if(i % cvt->len_div == 0)"
  1574        around the inner loop so that every sample is processed.
  1575      */
  1576     /* This is basically just a FIR filter. i.e. for input x_n and m coefficients,
  1577        y_n = x_n*sinc_0 + x_(n-1)*sinc_1 +  x_(n-2)*sinc_2 + ... + x_(n-m+1)*sinc_(m-1)
  1578      */
  1579 #define filter_sinc(type, mult) { \
  1580             type *sinc = (type *)cvt->coeff; \
  1581             type *state = (type *)cvt->state_buf; \
  1582             type *buf = (type *)cvt->buf; \
  1583             for(i = 0; i < n; ++i) { \
  1584                 state[cvt->state_pos] = buf[i]; \
  1585                 buf[i] = 0; \
  1586                 if( i % cvt->len_div == 0 ) { \
  1587                     for(j = 0; j < m;  ++j) { \
  1588                         buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \
  1589                     } \
  1590                 }\
  1591                 cvt->state_pos = (cvt->state_pos + 1) % m; \
  1592             } \
  1593         }
  1594 
  1595     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1596         filter_sinc(float, SDL_FloatMpy);
  1597     } else {
  1598         switch (SDL_AUDIO_BITSIZE(format)) {
  1599         case 8:
  1600             filter_sinc(Sint8, SDL_FixMpy8);
  1601             break;
  1602         case 16:
  1603             filter_sinc(Sint16, SDL_FixMpy16);
  1604             break;
  1605         case 32:
  1606             filter_sinc(Sint32, SDL_FixMpy32);
  1607             break;
  1608         }
  1609     }
  1610 
  1611 #undef filter_sinc
  1612 
  1613 }
  1614 
  1615 /* Generate the necessary windowed sinc filter for resampling.
  1616    Assume that the SDL_AudioCVT struct is already set up with
  1617    the correct values for len_mult and len_div, and use the
  1618    type of dst_format. Also assume the buffer is allocated.
  1619    Note the buffer needs to be m+1 units long.
  1620 */
  1621 int
  1622 SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format,
  1623                       unsigned int m)
  1624 {
  1625     float fScale;               /* scale factor for fixed point */
  1626     float *fSinc;               /* floating point sinc buffer, to be converted to fixed point */
  1627     float fc;                   /* cutoff frequency */
  1628     float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
  1629     float norm_sum, norm_fact;
  1630     unsigned int i;
  1631 
  1632     /* Check that the buffer is allocated */
  1633     if (cvt->coeff == NULL) {
  1634         return -1;
  1635     }
  1636 
  1637     /* Set the length */
  1638     cvt->len_sinc = m + 1;
  1639 
  1640     /* Allocate the floating point windowed sinc. */
  1641     fSinc = SDL_stack_alloc(float, (m + 1));
  1642     if (fSinc == NULL) {
  1643         return -1;
  1644     }
  1645 
  1646     /* Set up the filter parameters */
  1647     fc = (cvt->len_mult >
  1648           cvt->len_div) ? 0.5f / (float) cvt->len_mult : 0.5f /
  1649         (float) cvt->len_div;
  1650 #ifdef DEBUG_CONVERT
  1651     printf("Lowpass cutoff frequency = %f\n", fc);
  1652 #endif
  1653     two_pi_fc = 2.0f * M_PI * fc;
  1654     two_pi_over_m = 2.0f * M_PI / (float) m;
  1655     four_pi_over_m = 2.0f * two_pi_over_m;
  1656     m_over_two = (float) m / 2.0f;
  1657     norm_sum = 0.0f;
  1658 
  1659     for (i = 0; i <= m; ++i) {
  1660         if (i == m / 2) {
  1661             fSinc[i] = two_pi_fc;
  1662         } else {
  1663             fSinc[i] =
  1664                 sinf(two_pi_fc * ((float) i - m_over_two)) / ((float) i -
  1665                                                               m_over_two);
  1666             /* Apply blackman window */
  1667             fSinc[i] *=
  1668                 0.42f - 0.5f * cosf(two_pi_over_m * (float) i) +
  1669                 0.08f * cosf(four_pi_over_m * (float) i);
  1670         }
  1671         norm_sum += fabs(fSinc[i]);
  1672     }
  1673 
  1674     norm_fact = 1.0f / norm_sum;
  1675 
  1676 #define convert_fixed(type, fix) { \
  1677         type *dst = (type *)cvt->coeff; \
  1678         for( i = 0; i <= m; ++i ) { \
  1679             dst[i] = fix(fSinc[i] * norm_fact); \
  1680         } \
  1681     }
  1682 
  1683     /* If we're using floating point, we only need to normalize */
  1684     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1685         float *fDest = (float *) cvt->coeff;
  1686         for (i = 0; i <= m; ++i) {
  1687             fDest[i] = fSinc[i] * norm_fact;
  1688         }
  1689     } else {
  1690         switch (SDL_AUDIO_BITSIZE(format)) {
  1691         case 8:
  1692             convert_fixed(Uint8, SDL_Make_1_7);
  1693             break;
  1694         case 16:
  1695             convert_fixed(Uint16, SDL_Make_1_15);
  1696             break;
  1697         case 32:
  1698             convert_fixed(Uint32, SDL_Make_1_31);
  1699             break;
  1700         }
  1701     }
  1702 
  1703     /* Initialize the state buffer to all zeroes, and set initial position */
  1704     SDL_memset(cvt->state_buf, 0,
  1705                cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
  1706     cvt->state_pos = 0;
  1707 
  1708     /* Clean up */
  1709 #undef convert_fixed
  1710     SDL_stack_free(fSinc);
  1711 }
  1712 
  1713 /* This is used to reduce the resampling ratio */
  1714 static __inline__ int
  1715 SDL_GCD(int a, int b)
  1716 {
  1717     int temp;
  1718     while (b != 0) {
  1719         temp = a % b;
  1720         a = b;
  1721         b = temp;
  1722     }
  1723     return a;
  1724 }
  1725 
  1726 /* Perform proper resampling. This is pretty slow but it's the best-sounding method. */
  1727 static void SDLCALL
  1728 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1729 {
  1730     int i, j;
  1731 
  1732 #ifdef DEBUG_CONVERT
  1733     printf("Converting audio rate via proper resampling (mono)\n");
  1734 #endif
  1735 
  1736 #define zerostuff_mono(type) { \
  1737         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
  1738         type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \
  1739         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
  1740             src--; \
  1741             dst[-1] = src[0]; \
  1742             for( j = -cvt->len_mult; j < -1; ++j ) { \
  1743                 dst[j] = 0; \
  1744             } \
  1745             dst -= cvt->len_mult; \
  1746         } \
  1747     }
  1748 
  1749 #define discard_mono(type) { \
  1750         const type *src = (const type *) (cvt->buf); \
  1751         type *dst = (type *) (cvt->buf); \
  1752         for (i = 0; i < (cvt->len_cvt / sizeof(type)) / cvt->len_div; ++i) { \
  1753             dst[0] = src[0]; \
  1754             src += cvt->len_div; \
  1755             ++dst; \
  1756         } \
  1757     }
  1758 
  1759     /* Step 1: Zero stuff the conversion buffer. This upsamples by a factor of len_mult,
  1760        creating aliasing at frequencies above the original nyquist frequency.
  1761      */
  1762 #ifdef DEBUG_CONVERT
  1763     printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
  1764 #endif
  1765     switch (SDL_AUDIO_BITSIZE(format)) {
  1766     case 8:
  1767         zerostuff_mono(Uint8);
  1768         break;
  1769     case 16:
  1770         zerostuff_mono(Uint16);
  1771         break;
  1772     case 32:
  1773         zerostuff_mono(Uint32);
  1774         break;
  1775     }
  1776 
  1777     cvt->len_cvt *= cvt->len_mult;
  1778 
  1779     /* Step 2: Use a windowed sinc FIR filter (lowpass filter) to remove the alias
  1780        frequencies. This is the slow part.
  1781      */
  1782     SDL_FilterFIR(cvt, format);
  1783 
  1784     /* Step 3: Now downsample by discarding samples. */
  1785 
  1786 #ifdef DEBUG_CONVERT
  1787     printf("Discarding samples by a factor of %u\n", cvt->len_div);
  1788 #endif
  1789     switch (SDL_AUDIO_BITSIZE(format)) {
  1790     case 8:
  1791         discard_mono(Uint8);
  1792         break;
  1793     case 16:
  1794         discard_mono(Uint16);
  1795         break;
  1796     case 32:
  1797         discard_mono(Uint32);
  1798         break;
  1799     }
  1800 
  1801 #undef zerostuff_mono
  1802 #undef discard_mono
  1803 
  1804     cvt->len_cvt /= cvt->len_div;
  1805 
  1806     if (cvt->filters[++cvt->filter_index]) {
  1807         cvt->filters[cvt->filter_index] (cvt, format);
  1808     }
  1809 }
  1810 
  1811 
  1812 /* Creates a set of audio filters to convert from one format to another.
  1813    Returns -1 if the format conversion is not supported, 0 if there's
  1814    no conversion needed, or 1 if the audio filter is set up.
  1815 */
  1816 
  1817 int
  1818 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
  1819                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1820                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1821 {
  1822     /* there are no unsigned types over 16 bits, so catch this upfront. */
  1823     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1824         return -1;
  1825     }
  1826     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1827         return -1;
  1828     }
  1829 #ifdef DEBUG_CONVERT
  1830     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1831            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1832 #endif
  1833 
  1834     /* Start off with no conversion necessary */
  1835 
  1836     cvt->src_format = src_fmt;
  1837     cvt->dst_format = dst_fmt;
  1838     cvt->needed = 0;
  1839     cvt->filter_index = 0;
  1840     cvt->filters[0] = NULL;
  1841     cvt->len_mult = 1;
  1842     cvt->len_ratio = 1.0;
  1843 
  1844     /* Convert data types, if necessary. Updates (cvt). */
  1845     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1846         return -1;              /* shouldn't happen, but just in case... */
  1847 
  1848     /* Channel conversion */
  1849     if (src_channels != dst_channels) {
  1850         if ((src_channels == 1) && (dst_channels > 1)) {
  1851             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1852             cvt->len_mult *= 2;
  1853             src_channels = 2;
  1854             cvt->len_ratio *= 2;
  1855         }
  1856         if ((src_channels == 2) && (dst_channels == 6)) {
  1857             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1858             src_channels = 6;
  1859             cvt->len_mult *= 3;
  1860             cvt->len_ratio *= 3;
  1861         }
  1862         if ((src_channels == 2) && (dst_channels == 4)) {
  1863             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1864             src_channels = 4;
  1865             cvt->len_mult *= 2;
  1866             cvt->len_ratio *= 2;
  1867         }
  1868         while ((src_channels * 2) <= dst_channels) {
  1869             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1870             cvt->len_mult *= 2;
  1871             src_channels *= 2;
  1872             cvt->len_ratio *= 2;
  1873         }
  1874         if ((src_channels == 6) && (dst_channels <= 2)) {
  1875             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1876             src_channels = 2;
  1877             cvt->len_ratio /= 3;
  1878         }
  1879         if ((src_channels == 6) && (dst_channels == 4)) {
  1880             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1881             src_channels = 4;
  1882             cvt->len_ratio /= 2;
  1883         }
  1884         /* This assumes that 4 channel audio is in the format:
  1885            Left {front/back} + Right {front/back}
  1886            so converting to L/R stereo works properly.
  1887          */
  1888         while (((src_channels % 2) == 0) &&
  1889                ((src_channels / 2) >= dst_channels)) {
  1890             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1891             src_channels /= 2;
  1892             cvt->len_ratio /= 2;
  1893         }
  1894         if (src_channels != dst_channels) {
  1895             /* Uh oh.. */ ;
  1896         }
  1897     }
  1898 
  1899     /* Do rate conversion */
  1900     if (src_rate != dst_rate) {
  1901         int rate_gcd;
  1902         rate_gcd = SDL_GCD(src_rate, dst_rate);
  1903         cvt->len_mult = dst_rate / rate_gcd;
  1904         cvt->len_div = src_rate / rate_gcd;
  1905         cvt->len_ratio = (double) cvt->len_mult / (double) cvt->len_div;
  1906         cvt->filters[cvt->filter_index++] = SDL_Resample;
  1907         SDL_BuildWindowedSinc(cvt, dst_fmt, 768);
  1908     }
  1909 
  1910 /*
  1911     cvt->rate_incr = 0.0;
  1912     if ((src_rate / 100) != (dst_rate / 100)) {
  1913         Uint32 hi_rate, lo_rate;
  1914         int len_mult;
  1915         double len_ratio;
  1916         SDL_AudioFilter rate_cvt = NULL;
  1917 
  1918         if (src_rate > dst_rate) {
  1919             hi_rate = src_rate;
  1920             lo_rate = dst_rate;
  1921             switch (src_channels) {
  1922             case 1:
  1923                 rate_cvt = SDL_RateDIV2;
  1924                 break;
  1925             case 2:
  1926                 rate_cvt = SDL_RateDIV2_c2;
  1927                 break;
  1928             case 4:
  1929                 rate_cvt = SDL_RateDIV2_c4;
  1930                 break;
  1931             case 6:
  1932                 rate_cvt = SDL_RateDIV2_c6;
  1933                 break;
  1934             default:
  1935                 return -1;
  1936             }
  1937             len_mult = 1;
  1938             len_ratio = 0.5;
  1939         } else {
  1940             hi_rate = dst_rate;
  1941             lo_rate = src_rate;
  1942             switch (src_channels) {
  1943             case 1:
  1944                 rate_cvt = SDL_RateMUL2;
  1945                 break;
  1946             case 2:
  1947                 rate_cvt = SDL_RateMUL2_c2;
  1948                 break;
  1949             case 4:
  1950                 rate_cvt = SDL_RateMUL2_c4;
  1951                 break;
  1952             case 6:
  1953                 rate_cvt = SDL_RateMUL2_c6;
  1954                 break;
  1955             default:
  1956                 return -1;
  1957             }
  1958             len_mult = 2;
  1959             len_ratio = 2.0;
  1960         }*/
  1961     /* If hi_rate = lo_rate*2^x then conversion is easy */
  1962     /*   while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1963        cvt->filters[cvt->filter_index++] = rate_cvt;
  1964        cvt->len_mult *= len_mult;
  1965        lo_rate *= 2;
  1966        cvt->len_ratio *= len_ratio;
  1967        } */
  1968     /* We may need a slow conversion here to finish up */
  1969     /*    if ((lo_rate / 100) != (hi_rate / 100)) {
  1970        #if 1 */
  1971     /* The problem with this is that if the input buffer is
  1972        say 1K, and the conversion rate is say 1.1, then the
  1973        output buffer is 1.1K, which may not be an acceptable
  1974        buffer size for the audio driver (not a power of 2)
  1975      */
  1976     /* For now, punt and hope the rate distortion isn't great.
  1977      */
  1978 /*#else
  1979             if (src_rate < dst_rate) {
  1980                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1981                 cvt->len_mult *= 2;
  1982                 cvt->len_ratio /= cvt->rate_incr;
  1983             } else {
  1984                 cvt->rate_incr = (double) hi_rate / lo_rate;
  1985                 cvt->len_ratio *= cvt->rate_incr;
  1986             }
  1987             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1988 #endif
  1989         }
  1990     }*/
  1991 
  1992     /* Set up the filter information */
  1993     if (cvt->filter_index != 0) {
  1994         cvt->needed = 1;
  1995         cvt->src_format = src_fmt;
  1996         cvt->dst_format = dst_fmt;
  1997         cvt->len = 0;
  1998         cvt->buf = NULL;
  1999         cvt->filters[cvt->filter_index] = NULL;
  2000     }
  2001     return (cvt->needed);
  2002 }
  2003 
  2004 #undef SDL_FixMpy8
  2005 #undef SDL_FixMpy16
  2006 #undef SDL_FixMpy32
  2007 #undef SDL_FloatMpy
  2008 #undef SDL_Make_1_7
  2009 #undef SDL_Make_1_15
  2010 #undef SDL_Make_1_31
  2011 #undef SDL_Make_2_6
  2012 #undef SDL_Make_2_14
  2013 #undef SDL_Make_2_30
  2014 
  2015 /* vi: set ts=4 sw=4 expandtab: */