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