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