src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 25 Aug 2008 15:08:59 +0000
changeset 2716 f8f68f47285a
parent 2130 3ee59c43d784
child 2728 2768bd7281e0
permissions -rw-r--r--
Final merge of Google Summer of Code 2008 work...

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