src/audio/SDL_audiocvt.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 17 Oct 2006 09:15:21 +0000
changeset 2049 5f6550e5184f
parent 2042 3908e1f808e1
child 2078 f932ac47a331
permissions -rw-r--r--
Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
     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 /* 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 /* Effectively mix right and left channels into a single channel */
    30 static void SDLCALL
    31 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    32 {
    33     int i;
    34     Sint32 sample;
    35 
    36 #ifdef DEBUG_CONVERT
    37     fprintf(stderr, "Converting to mono\n");
    38 #endif
    39     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
    40     case AUDIO_U8:
    41         {
    42             Uint8 *src, *dst;
    43 
    44             src = cvt->buf;
    45             dst = cvt->buf;
    46             for (i = cvt->len_cvt / 2; i; --i) {
    47                 sample = src[0] + src[1];
    48                 *dst = (Uint8) (sample / 2);
    49                 src += 2;
    50                 dst += 1;
    51             }
    52         }
    53         break;
    54 
    55     case AUDIO_S8:
    56         {
    57             Sint8 *src, *dst;
    58 
    59             src = (Sint8 *) cvt->buf;
    60             dst = (Sint8 *) cvt->buf;
    61             for (i = cvt->len_cvt / 2; i; --i) {
    62                 sample = src[0] + src[1];
    63                 *dst = (Sint8) (sample / 2);
    64                 src += 2;
    65                 dst += 1;
    66             }
    67         }
    68         break;
    69 
    70     case AUDIO_U16:
    71         {
    72             Uint8 *src, *dst;
    73 
    74             src = cvt->buf;
    75             dst = cvt->buf;
    76             if (SDL_AUDIO_ISBIGENDIAN(format)) {
    77                 for (i = cvt->len_cvt / 4; i; --i) {
    78                     sample = (Uint16) ((src[0] << 8) | src[1]) +
    79                         (Uint16) ((src[2] << 8) | src[3]);
    80                     sample /= 2;
    81                     dst[1] = (sample & 0xFF);
    82                     sample >>= 8;
    83                     dst[0] = (sample & 0xFF);
    84                     src += 4;
    85                     dst += 2;
    86                 }
    87             } else {
    88                 for (i = cvt->len_cvt / 4; i; --i) {
    89                     sample = (Uint16) ((src[1] << 8) | src[0]) +
    90                         (Uint16) ((src[3] << 8) | src[2]);
    91                     sample /= 2;
    92                     dst[0] = (sample & 0xFF);
    93                     sample >>= 8;
    94                     dst[1] = (sample & 0xFF);
    95                     src += 4;
    96                     dst += 2;
    97                 }
    98             }
    99         }
   100         break;
   101 
   102     case AUDIO_S16:
   103         {
   104             Uint8 *src, *dst;
   105 
   106             src = cvt->buf;
   107             dst = cvt->buf;
   108             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   109                 for (i = cvt->len_cvt / 4; i; --i) {
   110                     sample = (Sint16) ((src[0] << 8) | src[1]) +
   111                         (Sint16) ((src[2] << 8) | src[3]);
   112                     sample /= 2;
   113                     dst[1] = (sample & 0xFF);
   114                     sample >>= 8;
   115                     dst[0] = (sample & 0xFF);
   116                     src += 4;
   117                     dst += 2;
   118                 }
   119             } else {
   120                 for (i = cvt->len_cvt / 4; i; --i) {
   121                     sample = (Sint16) ((src[1] << 8) | src[0]) +
   122                         (Sint16) ((src[3] << 8) | src[2]);
   123                     sample /= 2;
   124                     dst[0] = (sample & 0xFF);
   125                     sample >>= 8;
   126                     dst[1] = (sample & 0xFF);
   127                     src += 4;
   128                     dst += 2;
   129                 }
   130             }
   131         }
   132         break;
   133 
   134     case AUDIO_S32:
   135         {
   136             const Uint32 *src = (const Uint32 *) cvt->buf;
   137             Uint32 *dst = (Uint32 *) cvt->buf;
   138             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   139                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   140                     const Sint64 added =
   141                         (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
   142                          ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
   143                     *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added >> 1)));
   144                 }
   145             } else {
   146                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   147                     const Sint64 added =
   148                         (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
   149                          ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
   150                     *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added >> 1)));
   151                 }
   152             }
   153         }
   154         break;
   155 
   156     case AUDIO_F32:
   157         {
   158             const float *src = (const float *) cvt->buf;
   159             float *dst = (float *) cvt->buf;
   160             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   161                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   162                     const float src1 = SDL_SwapFloatBE(src[0]);
   163                     const float src2 = SDL_SwapFloatBE(src[1]);
   164                     const double added = ((double) src1) + ((double) src2);
   165                     const float halved = (float) (added * 0.5);
   166                     *(dst++) = SDL_SwapFloatBE(halved);
   167                 }
   168             } else {
   169                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   170                     const float src1 = SDL_SwapFloatLE(src[0]);
   171                     const float src2 = SDL_SwapFloatLE(src[1]);
   172                     const double added = ((double) src1) + ((double) src2);
   173                     const float halved = (float) (added * 0.5);
   174                     *(dst++) = SDL_SwapFloatLE(halved);
   175                 }
   176             }
   177         }
   178         break;
   179     }
   180 
   181     cvt->len_cvt /= 2;
   182     if (cvt->filters[++cvt->filter_index]) {
   183         cvt->filters[cvt->filter_index] (cvt, format);
   184     }
   185 }
   186 
   187 
   188 /* Discard top 4 channels */
   189 static void SDLCALL
   190 SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   191 {
   192     int i;
   193 
   194 #ifdef DEBUG_CONVERT
   195     fprintf(stderr, "Converting down from 6 channels to stereo\n");
   196 #endif
   197 
   198 #define strip_chans_6_to_2(type) \
   199     { \
   200         const type *src = (const type *) cvt->buf; \
   201         type *dst = (type *) cvt->buf; \
   202         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   203             dst[0] = src[0]; \
   204             dst[1] = src[1]; \
   205             src += 6; \
   206             dst += 2; \
   207         } \
   208     }
   209 
   210     /* this function only cares about typesize, and data as a block of bits. */
   211     switch (SDL_AUDIO_BITSIZE(format)) {
   212     case 8:
   213         strip_chans_6_to_2(Uint8);
   214         break;
   215     case 16:
   216         strip_chans_6_to_2(Uint16);
   217         break;
   218     case 32:
   219         strip_chans_6_to_2(Uint32);
   220         break;
   221     }
   222 
   223 #undef strip_chans_6_to_2
   224 
   225     cvt->len_cvt /= 3;
   226     if (cvt->filters[++cvt->filter_index]) {
   227         cvt->filters[cvt->filter_index] (cvt, format);
   228     }
   229 }
   230 
   231 
   232 /* Discard top 2 channels of 6 */
   233 static void SDLCALL
   234 SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   235 {
   236     int i;
   237 
   238 #ifdef DEBUG_CONVERT
   239     fprintf(stderr, "Converting 6 down to quad\n");
   240 #endif
   241 
   242 #define strip_chans_6_to_4(type) \
   243     { \
   244         const type *src = (const type *) cvt->buf; \
   245         type *dst = (type *) cvt->buf; \
   246         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   247             dst[0] = src[0]; \
   248             dst[1] = src[1]; \
   249             dst[2] = src[2]; \
   250             dst[3] = src[3]; \
   251             src += 6; \
   252             dst += 4; \
   253         } \
   254     }
   255 
   256     /* this function only cares about typesize, and data as a block of bits. */
   257     switch (SDL_AUDIO_BITSIZE(format)) {
   258     case 8:
   259         strip_chans_6_to_4(Uint8);
   260         break;
   261     case 16:
   262         strip_chans_6_to_4(Uint16);
   263         break;
   264     case 32:
   265         strip_chans_6_to_4(Uint32);
   266         break;
   267     }
   268 
   269 #undef strip_chans_6_to_4
   270 
   271     cvt->len_cvt /= 6;
   272     cvt->len_cvt *= 4;
   273     if (cvt->filters[++cvt->filter_index]) {
   274         cvt->filters[cvt->filter_index] (cvt, format);
   275     }
   276 }
   277 
   278 /* Duplicate a mono channel to both stereo channels */
   279 static void SDLCALL
   280 SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   281 {
   282     int i;
   283 
   284 #ifdef DEBUG_CONVERT
   285     fprintf(stderr, "Converting to stereo\n");
   286 #endif
   287 
   288 #define dup_chans_1_to_2(type) \
   289     { \
   290         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   291         type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
   292         for (i = cvt->len_cvt / 2; i; --i, --src) { \
   293             const type val = *src; \
   294             dst -= 2; \
   295             dst[0] = dst[1] = val; \
   296         } \
   297     }
   298 
   299     /* this function only cares about typesize, and data as a block of bits. */
   300     switch (SDL_AUDIO_BITSIZE(format)) {
   301     case 8:
   302         dup_chans_1_to_2(Uint8);
   303         break;
   304     case 16:
   305         dup_chans_1_to_2(Uint16);
   306         break;
   307     case 32:
   308         dup_chans_1_to_2(Uint32);
   309         break;
   310     }
   311 
   312 #undef dup_chans_1_to_2
   313 
   314     cvt->len_cvt *= 2;
   315     if (cvt->filters[++cvt->filter_index]) {
   316         cvt->filters[cvt->filter_index] (cvt, format);
   317     }
   318 }
   319 
   320 
   321 /* Duplicate a stereo channel to a pseudo-5.1 stream */
   322 static void SDLCALL
   323 SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   324 {
   325     int i;
   326 
   327 #ifdef DEBUG_CONVERT
   328     fprintf(stderr, "Converting stereo to surround\n");
   329 #endif
   330 
   331     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   332     case AUDIO_U8:
   333         {
   334             Uint8 *src, *dst, lf, rf, ce;
   335 
   336             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   337             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
   338             for (i = cvt->len_cvt; i; --i) {
   339                 dst -= 6;
   340                 src -= 2;
   341                 lf = src[0];
   342                 rf = src[1];
   343                 ce = (lf / 2) + (rf / 2);
   344                 dst[0] = lf;
   345                 dst[1] = rf;
   346                 dst[2] = lf - ce;
   347                 dst[3] = rf - ce;
   348                 dst[4] = ce;
   349                 dst[5] = ce;
   350             }
   351         }
   352         break;
   353 
   354     case AUDIO_S8:
   355         {
   356             Sint8 *src, *dst, lf, rf, ce;
   357 
   358             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   359             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
   360             for (i = cvt->len_cvt; i; --i) {
   361                 dst -= 6;
   362                 src -= 2;
   363                 lf = src[0];
   364                 rf = src[1];
   365                 ce = (lf / 2) + (rf / 2);
   366                 dst[0] = lf;
   367                 dst[1] = rf;
   368                 dst[2] = lf - ce;
   369                 dst[3] = rf - ce;
   370                 dst[4] = ce;
   371                 dst[5] = ce;
   372             }
   373         }
   374         break;
   375 
   376     case AUDIO_U16:
   377         {
   378             Uint8 *src, *dst;
   379             Uint16 lf, rf, ce, lr, rr;
   380 
   381             src = cvt->buf + cvt->len_cvt;
   382             dst = cvt->buf + cvt->len_cvt * 3;
   383 
   384             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   385                 for (i = cvt->len_cvt / 4; i; --i) {
   386                     dst -= 12;
   387                     src -= 4;
   388                     lf = (Uint16) ((src[0] << 8) | src[1]);
   389                     rf = (Uint16) ((src[2] << 8) | src[3]);
   390                     ce = (lf / 2) + (rf / 2);
   391                     rr = lf - ce;
   392                     lr = rf - ce;
   393                     dst[1] = (lf & 0xFF);
   394                     dst[0] = ((lf >> 8) & 0xFF);
   395                     dst[3] = (rf & 0xFF);
   396                     dst[2] = ((rf >> 8) & 0xFF);
   397 
   398                     dst[1 + 4] = (lr & 0xFF);
   399                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   400                     dst[3 + 4] = (rr & 0xFF);
   401                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   402 
   403                     dst[1 + 8] = (ce & 0xFF);
   404                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   405                     dst[3 + 8] = (ce & 0xFF);
   406                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   407                 }
   408             } else {
   409                 for (i = cvt->len_cvt / 4; i; --i) {
   410                     dst -= 12;
   411                     src -= 4;
   412                     lf = (Uint16) ((src[1] << 8) | src[0]);
   413                     rf = (Uint16) ((src[3] << 8) | src[2]);
   414                     ce = (lf / 2) + (rf / 2);
   415                     rr = lf - ce;
   416                     lr = rf - ce;
   417                     dst[0] = (lf & 0xFF);
   418                     dst[1] = ((lf >> 8) & 0xFF);
   419                     dst[2] = (rf & 0xFF);
   420                     dst[3] = ((rf >> 8) & 0xFF);
   421 
   422                     dst[0 + 4] = (lr & 0xFF);
   423                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   424                     dst[2 + 4] = (rr & 0xFF);
   425                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   426 
   427                     dst[0 + 8] = (ce & 0xFF);
   428                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   429                     dst[2 + 8] = (ce & 0xFF);
   430                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   431                 }
   432             }
   433         }
   434         break;
   435 
   436     case AUDIO_S16:
   437         {
   438             Uint8 *src, *dst;
   439             Sint16 lf, rf, ce, lr, rr;
   440 
   441             src = cvt->buf + cvt->len_cvt;
   442             dst = cvt->buf + cvt->len_cvt * 3;
   443 
   444             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   445                 for (i = cvt->len_cvt / 4; i; --i) {
   446                     dst -= 12;
   447                     src -= 4;
   448                     lf = (Sint16) ((src[0] << 8) | src[1]);
   449                     rf = (Sint16) ((src[2] << 8) | src[3]);
   450                     ce = (lf / 2) + (rf / 2);
   451                     rr = lf - ce;
   452                     lr = rf - ce;
   453                     dst[1] = (lf & 0xFF);
   454                     dst[0] = ((lf >> 8) & 0xFF);
   455                     dst[3] = (rf & 0xFF);
   456                     dst[2] = ((rf >> 8) & 0xFF);
   457 
   458                     dst[1 + 4] = (lr & 0xFF);
   459                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   460                     dst[3 + 4] = (rr & 0xFF);
   461                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   462 
   463                     dst[1 + 8] = (ce & 0xFF);
   464                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   465                     dst[3 + 8] = (ce & 0xFF);
   466                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   467                 }
   468             } else {
   469                 for (i = cvt->len_cvt / 4; i; --i) {
   470                     dst -= 12;
   471                     src -= 4;
   472                     lf = (Sint16) ((src[1] << 8) | src[0]);
   473                     rf = (Sint16) ((src[3] << 8) | src[2]);
   474                     ce = (lf / 2) + (rf / 2);
   475                     rr = lf - ce;
   476                     lr = rf - ce;
   477                     dst[0] = (lf & 0xFF);
   478                     dst[1] = ((lf >> 8) & 0xFF);
   479                     dst[2] = (rf & 0xFF);
   480                     dst[3] = ((rf >> 8) & 0xFF);
   481 
   482                     dst[0 + 4] = (lr & 0xFF);
   483                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   484                     dst[2 + 4] = (rr & 0xFF);
   485                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   486 
   487                     dst[0 + 8] = (ce & 0xFF);
   488                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   489                     dst[2 + 8] = (ce & 0xFF);
   490                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   491                 }
   492             }
   493         }
   494         break;
   495 
   496     case AUDIO_S32:
   497         {
   498             Sint32 lf, rf, ce;
   499             const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
   500             Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
   501 
   502             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   503                 for (i = cvt->len_cvt / 8; i; --i) {
   504                     dst -= 6;
   505                     src -= 2;
   506                     lf = (Sint32) SDL_SwapBE32(src[0]);
   507                     rf = (Sint32) SDL_SwapBE32(src[1]);
   508                     ce = (lf / 2) + (rf / 2);
   509                     dst[0] = SDL_SwapBE32((Uint32) lf);
   510                     dst[1] = SDL_SwapBE32((Uint32) rf);
   511                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   512                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   513                     dst[4] = SDL_SwapBE32((Uint32) ce);
   514                     dst[5] = SDL_SwapBE32((Uint32) ce);
   515                 }
   516             } else {
   517                 for (i = cvt->len_cvt / 8; i; --i) {
   518                     dst -= 6;
   519                     src -= 2;
   520                     lf = (Sint32) SDL_SwapLE32(src[0]);
   521                     rf = (Sint32) SDL_SwapLE32(src[1]);
   522                     ce = (lf / 2) + (rf / 2);
   523                     dst[0] = src[0];
   524                     dst[1] = src[1];
   525                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   526                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   527                     dst[4] = SDL_SwapLE32((Uint32) ce);
   528                     dst[5] = SDL_SwapLE32((Uint32) ce);
   529                 }
   530             }
   531         }
   532         break;
   533 
   534     case AUDIO_F32:
   535         {
   536             float lf, rf, ce;
   537             const float *src = (const float *) cvt->buf + cvt->len_cvt;
   538             float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
   539 
   540             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   541                 for (i = cvt->len_cvt / 8; i; --i) {
   542                     dst -= 6;
   543                     src -= 2;
   544                     lf = SDL_SwapFloatBE(src[0]);
   545                     rf = SDL_SwapFloatBE(src[1]);
   546                     ce = (lf * 0.5f) + (rf * 0.5f);
   547                     dst[0] = src[0];
   548                     dst[1] = src[1];
   549                     dst[2] = SDL_SwapFloatBE(lf - ce);
   550                     dst[3] = SDL_SwapFloatBE(rf - ce);
   551                     dst[4] = dst[5] = SDL_SwapFloatBE(ce);
   552                 }
   553             } else {
   554                 for (i = cvt->len_cvt / 8; i; --i) {
   555                     dst -= 6;
   556                     src -= 2;
   557                     lf = SDL_SwapFloatLE(src[0]);
   558                     rf = SDL_SwapFloatLE(src[1]);
   559                     ce = (lf * 0.5f) + (rf * 0.5f);
   560                     dst[0] = src[0];
   561                     dst[1] = src[1];
   562                     dst[2] = SDL_SwapFloatLE(lf - ce);
   563                     dst[3] = SDL_SwapFloatLE(rf - ce);
   564                     dst[4] = dst[5] = SDL_SwapFloatLE(ce);
   565                 }
   566             }
   567         }
   568         break;
   569 
   570     }
   571     cvt->len_cvt *= 3;
   572     if (cvt->filters[++cvt->filter_index]) {
   573         cvt->filters[cvt->filter_index] (cvt, format);
   574     }
   575 }
   576 
   577 
   578 /* Duplicate a stereo channel to a pseudo-4.0 stream */
   579 static void SDLCALL
   580 SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   581 {
   582     int i;
   583 
   584 #ifdef DEBUG_CONVERT
   585     fprintf(stderr, "Converting stereo to quad\n");
   586 #endif
   587 
   588     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   589     case AUDIO_U8:
   590         {
   591             Uint8 *src, *dst, lf, rf, ce;
   592 
   593             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   594             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
   595             for (i = cvt->len_cvt; i; --i) {
   596                 dst -= 4;
   597                 src -= 2;
   598                 lf = src[0];
   599                 rf = src[1];
   600                 ce = (lf / 2) + (rf / 2);
   601                 dst[0] = lf;
   602                 dst[1] = rf;
   603                 dst[2] = lf - ce;
   604                 dst[3] = rf - ce;
   605             }
   606         }
   607         break;
   608 
   609     case AUDIO_S8:
   610         {
   611             Sint8 *src, *dst, lf, rf, ce;
   612 
   613             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   614             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
   615             for (i = cvt->len_cvt; i; --i) {
   616                 dst -= 4;
   617                 src -= 2;
   618                 lf = src[0];
   619                 rf = src[1];
   620                 ce = (lf / 2) + (rf / 2);
   621                 dst[0] = lf;
   622                 dst[1] = rf;
   623                 dst[2] = lf - ce;
   624                 dst[3] = rf - ce;
   625             }
   626         }
   627         break;
   628 
   629     case AUDIO_U16:
   630         {
   631             Uint8 *src, *dst;
   632             Uint16 lf, rf, ce, lr, rr;
   633 
   634             src = cvt->buf + cvt->len_cvt;
   635             dst = cvt->buf + cvt->len_cvt * 2;
   636 
   637             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   638                 for (i = cvt->len_cvt / 4; i; --i) {
   639                     dst -= 8;
   640                     src -= 4;
   641                     lf = (Uint16) ((src[0] << 8) | src[1]);
   642                     rf = (Uint16) ((src[2] << 8) | src[3]);
   643                     ce = (lf / 2) + (rf / 2);
   644                     rr = lf - ce;
   645                     lr = rf - ce;
   646                     dst[1] = (lf & 0xFF);
   647                     dst[0] = ((lf >> 8) & 0xFF);
   648                     dst[3] = (rf & 0xFF);
   649                     dst[2] = ((rf >> 8) & 0xFF);
   650 
   651                     dst[1 + 4] = (lr & 0xFF);
   652                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   653                     dst[3 + 4] = (rr & 0xFF);
   654                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   655                 }
   656             } else {
   657                 for (i = cvt->len_cvt / 4; i; --i) {
   658                     dst -= 8;
   659                     src -= 4;
   660                     lf = (Uint16) ((src[1] << 8) | src[0]);
   661                     rf = (Uint16) ((src[3] << 8) | src[2]);
   662                     ce = (lf / 2) + (rf / 2);
   663                     rr = lf - ce;
   664                     lr = rf - ce;
   665                     dst[0] = (lf & 0xFF);
   666                     dst[1] = ((lf >> 8) & 0xFF);
   667                     dst[2] = (rf & 0xFF);
   668                     dst[3] = ((rf >> 8) & 0xFF);
   669 
   670                     dst[0 + 4] = (lr & 0xFF);
   671                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   672                     dst[2 + 4] = (rr & 0xFF);
   673                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   674                 }
   675             }
   676         }
   677         break;
   678 
   679     case AUDIO_S16:
   680         {
   681             Uint8 *src, *dst;
   682             Sint16 lf, rf, ce, lr, rr;
   683 
   684             src = cvt->buf + cvt->len_cvt;
   685             dst = cvt->buf + cvt->len_cvt * 2;
   686 
   687             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   688                 for (i = cvt->len_cvt / 4; i; --i) {
   689                     dst -= 8;
   690                     src -= 4;
   691                     lf = (Sint16) ((src[0] << 8) | src[1]);
   692                     rf = (Sint16) ((src[2] << 8) | src[3]);
   693                     ce = (lf / 2) + (rf / 2);
   694                     rr = lf - ce;
   695                     lr = rf - ce;
   696                     dst[1] = (lf & 0xFF);
   697                     dst[0] = ((lf >> 8) & 0xFF);
   698                     dst[3] = (rf & 0xFF);
   699                     dst[2] = ((rf >> 8) & 0xFF);
   700 
   701                     dst[1 + 4] = (lr & 0xFF);
   702                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   703                     dst[3 + 4] = (rr & 0xFF);
   704                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   705                 }
   706             } else {
   707                 for (i = cvt->len_cvt / 4; i; --i) {
   708                     dst -= 8;
   709                     src -= 4;
   710                     lf = (Sint16) ((src[1] << 8) | src[0]);
   711                     rf = (Sint16) ((src[3] << 8) | src[2]);
   712                     ce = (lf / 2) + (rf / 2);
   713                     rr = lf - ce;
   714                     lr = rf - ce;
   715                     dst[0] = (lf & 0xFF);
   716                     dst[1] = ((lf >> 8) & 0xFF);
   717                     dst[2] = (rf & 0xFF);
   718                     dst[3] = ((rf >> 8) & 0xFF);
   719 
   720                     dst[0 + 4] = (lr & 0xFF);
   721                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   722                     dst[2 + 4] = (rr & 0xFF);
   723                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   724                 }
   725             }
   726         }
   727         break;
   728 
   729     case AUDIO_S32:
   730         {
   731             const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
   732             Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
   733             Sint32 lf, rf, ce;
   734 
   735             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   736                 for (i = cvt->len_cvt / 8; i; --i) {
   737                     dst -= 4;
   738                     src -= 2;
   739                     lf = (Sint32) SDL_SwapBE32(src[0]);
   740                     rf = (Sint32) SDL_SwapBE32(src[1]);
   741                     ce = (lf / 2) + (rf / 2);
   742                     dst[0] = src[0];
   743                     dst[1] = src[1];
   744                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   745                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   746                 }
   747             } else {
   748                 for (i = cvt->len_cvt / 8; i; --i) {
   749                     dst -= 4;
   750                     src -= 2;
   751                     lf = (Sint32) SDL_SwapLE32(src[0]);
   752                     rf = (Sint32) SDL_SwapLE32(src[1]);
   753                     ce = (lf / 2) + (rf / 2);
   754                     dst[0] = src[0];
   755                     dst[1] = src[1];
   756                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   757                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   758                 }
   759             }
   760         }
   761         break;
   762     }
   763     cvt->len_cvt *= 2;
   764     if (cvt->filters[++cvt->filter_index]) {
   765         cvt->filters[cvt->filter_index] (cvt, format);
   766     }
   767 }
   768 
   769 /* Convert rate up by multiple of 2 */
   770 static void SDLCALL
   771 SDL_RateMUL2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   772 {
   773     int i;
   774 
   775 #ifdef DEBUG_CONVERT
   776     fprintf(stderr, "Converting audio rate * 2 (mono)\n");
   777 #endif
   778 
   779 #define mul2_mono(type) { \
   780         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   781         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   782         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
   783             src--; \
   784             dst[-1] = dst[-2] = src[0]; \
   785             dst -= 2; \
   786         } \
   787     }
   788 
   789     switch (SDL_AUDIO_BITSIZE(format)) {
   790     case 8:
   791         mul2_mono(Uint8);
   792         break;
   793     case 16:
   794         mul2_mono(Uint16);
   795         break;
   796     case 32:
   797         mul2_mono(Uint32);
   798         break;
   799     }
   800 
   801 #undef mul2_mono
   802 
   803     cvt->len_cvt *= 2;
   804     if (cvt->filters[++cvt->filter_index]) {
   805         cvt->filters[cvt->filter_index] (cvt, format);
   806     }
   807 }
   808 
   809 
   810 /* Convert rate up by multiple of 2, for stereo */
   811 static void SDLCALL
   812 SDL_RateMUL2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   813 {
   814     int i;
   815 
   816 #ifdef DEBUG_CONVERT
   817     fprintf(stderr, "Converting audio rate * 2 (stereo)\n");
   818 #endif
   819 
   820 #define mul2_stereo(type) { \
   821         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   822         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   823         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   824             const type r = src[-1]; \
   825             const type l = src[-2]; \
   826             src -= 2; \
   827             dst[-1] = r; \
   828             dst[-2] = l; \
   829             dst[-3] = r; \
   830             dst[-4] = l; \
   831             dst -= 4; \
   832         } \
   833     }
   834 
   835     switch (SDL_AUDIO_BITSIZE(format)) {
   836     case 8:
   837         mul2_stereo(Uint8);
   838         break;
   839     case 16:
   840         mul2_stereo(Uint16);
   841         break;
   842     case 32:
   843         mul2_stereo(Uint32);
   844         break;
   845     }
   846 
   847 #undef mul2_stereo
   848 
   849     cvt->len_cvt *= 2;
   850     if (cvt->filters[++cvt->filter_index]) {
   851         cvt->filters[cvt->filter_index] (cvt, format);
   852     }
   853 }
   854 
   855 /* Convert rate up by multiple of 2, for quad */
   856 static void SDLCALL
   857 SDL_RateMUL2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   858 {
   859     int i;
   860 
   861 #ifdef DEBUG_CONVERT
   862     fprintf(stderr, "Converting audio rate * 2 (quad)\n");
   863 #endif
   864 
   865 #define mul2_quad(type) { \
   866         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   867         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   868         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
   869             const type c1 = src[-1]; \
   870             const type c2 = src[-2]; \
   871             const type c3 = src[-3]; \
   872             const type c4 = src[-4]; \
   873             src -= 4; \
   874             dst[-1] = c1; \
   875             dst[-2] = c2; \
   876             dst[-3] = c3; \
   877             dst[-4] = c4; \
   878             dst[-5] = c1; \
   879             dst[-6] = c2; \
   880             dst[-7] = c3; \
   881             dst[-8] = c4; \
   882             dst -= 8; \
   883         } \
   884     }
   885 
   886     switch (SDL_AUDIO_BITSIZE(format)) {
   887     case 8:
   888         mul2_quad(Uint8);
   889         break;
   890     case 16:
   891         mul2_quad(Uint16);
   892         break;
   893     case 32:
   894         mul2_quad(Uint32);
   895         break;
   896     }
   897 
   898 #undef mul2_quad
   899 
   900     cvt->len_cvt *= 2;
   901     if (cvt->filters[++cvt->filter_index]) {
   902         cvt->filters[cvt->filter_index] (cvt, format);
   903     }
   904 }
   905 
   906 
   907 /* Convert rate up by multiple of 2, for 5.1 */
   908 static void SDLCALL
   909 SDL_RateMUL2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   910 {
   911     int i;
   912 
   913 #ifdef DEBUG_CONVERT
   914     fprintf(stderr, "Converting audio rate * 2 (six channels)\n");
   915 #endif
   916 
   917 #define mul2_chansix(type) { \
   918         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   919         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   920         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   921             const type c1 = src[-1]; \
   922             const type c2 = src[-2]; \
   923             const type c3 = src[-3]; \
   924             const type c4 = src[-4]; \
   925             const type c5 = src[-5]; \
   926             const type c6 = src[-6]; \
   927             src -= 6; \
   928             dst[-1] = c1; \
   929             dst[-2] = c2; \
   930             dst[-3] = c3; \
   931             dst[-4] = c4; \
   932             dst[-5] = c5; \
   933             dst[-6] = c6; \
   934             dst[-7] = c1; \
   935             dst[-8] = c2; \
   936             dst[-9] = c3; \
   937             dst[-10] = c4; \
   938             dst[-11] = c5; \
   939             dst[-12] = c6; \
   940             dst -= 12; \
   941         } \
   942     }
   943 
   944     switch (SDL_AUDIO_BITSIZE(format)) {
   945     case 8:
   946         mul2_chansix(Uint8);
   947         break;
   948     case 16:
   949         mul2_chansix(Uint16);
   950         break;
   951     case 32:
   952         mul2_chansix(Uint32);
   953         break;
   954     }
   955 
   956 #undef mul2_chansix
   957 
   958     cvt->len_cvt *= 2;
   959     if (cvt->filters[++cvt->filter_index]) {
   960         cvt->filters[cvt->filter_index] (cvt, format);
   961     }
   962 }
   963 
   964 /* Convert rate down by multiple of 2 */
   965 static void SDLCALL
   966 SDL_RateDIV2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   967 {
   968     int i;
   969 
   970 #ifdef DEBUG_CONVERT
   971     fprintf(stderr, "Converting audio rate / 2 (mono)\n");
   972 #endif
   973 
   974 #define div2_mono(type) { \
   975         const type *src = (const type *) cvt->buf; \
   976         type *dst = (type *) cvt->buf; \
   977         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   978             dst[0] = src[0]; \
   979             src += 2; \
   980             dst++; \
   981         } \
   982     }
   983 
   984     switch (SDL_AUDIO_BITSIZE(format)) {
   985     case 8:
   986         div2_mono(Uint8);
   987         break;
   988     case 16:
   989         div2_mono(Uint16);
   990         break;
   991     case 32:
   992         div2_mono(Uint32);
   993         break;
   994     }
   995 
   996 #undef div2_mono
   997 
   998     cvt->len_cvt /= 2;
   999     if (cvt->filters[++cvt->filter_index]) {
  1000         cvt->filters[cvt->filter_index] (cvt, format);
  1001     }
  1002 }
  1003 
  1004 
  1005 /* Convert rate down by multiple of 2, for stereo */
  1006 static void SDLCALL
  1007 SDL_RateDIV2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1008 {
  1009     int i;
  1010 
  1011 #ifdef DEBUG_CONVERT
  1012     fprintf(stderr, "Converting audio rate / 2 (stereo)\n");
  1013 #endif
  1014 
  1015 #define div2_stereo(type) { \
  1016         const type *src = (const type *) cvt->buf; \
  1017         type *dst = (type *) cvt->buf; \
  1018         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
  1019             dst[0] = src[0]; \
  1020             dst[1] = src[1]; \
  1021             src += 4; \
  1022             dst += 2; \
  1023         } \
  1024     }
  1025 
  1026     switch (SDL_AUDIO_BITSIZE(format)) {
  1027     case 8:
  1028         div2_stereo(Uint8);
  1029         break;
  1030     case 16:
  1031         div2_stereo(Uint16);
  1032         break;
  1033     case 32:
  1034         div2_stereo(Uint32);
  1035         break;
  1036     }
  1037 
  1038 #undef div2_stereo
  1039 
  1040     cvt->len_cvt /= 2;
  1041     if (cvt->filters[++cvt->filter_index]) {
  1042         cvt->filters[cvt->filter_index] (cvt, format);
  1043     }
  1044 }
  1045 
  1046 
  1047 /* Convert rate down by multiple of 2, for quad */
  1048 static void SDLCALL
  1049 SDL_RateDIV2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1050 {
  1051     int i;
  1052 
  1053 #ifdef DEBUG_CONVERT
  1054     fprintf(stderr, "Converting audio rate / 2 (quad)\n");
  1055 #endif
  1056 
  1057 #define div2_quad(type) { \
  1058         const type *src = (const type *) cvt->buf; \
  1059         type *dst = (type *) cvt->buf; \
  1060         for (i = cvt->len_cvt / (sizeof (type) * 8); i; --i) { \
  1061             dst[0] = src[0]; \
  1062             dst[1] = src[1]; \
  1063             dst[2] = src[2]; \
  1064             dst[3] = src[3]; \
  1065             src += 8; \
  1066             dst += 4; \
  1067         } \
  1068     }
  1069 
  1070     switch (SDL_AUDIO_BITSIZE(format)) {
  1071     case 8:
  1072         div2_quad(Uint8);
  1073         break;
  1074     case 16:
  1075         div2_quad(Uint16);
  1076         break;
  1077     case 32:
  1078         div2_quad(Uint32);
  1079         break;
  1080     }
  1081 
  1082 #undef div2_quad
  1083 
  1084     cvt->len_cvt /= 2;
  1085     if (cvt->filters[++cvt->filter_index]) {
  1086         cvt->filters[cvt->filter_index] (cvt, format);
  1087     }
  1088 }
  1089 
  1090 /* Convert rate down by multiple of 2, for 5.1 */
  1091 static void SDLCALL
  1092 SDL_RateDIV2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1093 {
  1094     int i;
  1095 
  1096 #ifdef DEBUG_CONVERT
  1097     fprintf(stderr, "Converting audio rate / 2 (six channels)\n");
  1098 #endif
  1099 
  1100 #define div2_chansix(type) { \
  1101         const type *src = (const type *) cvt->buf; \
  1102         type *dst = (type *) cvt->buf; \
  1103         for (i = cvt->len_cvt / (sizeof (type) * 12); i; --i) { \
  1104             dst[0] = src[0]; \
  1105             dst[1] = src[1]; \
  1106             dst[2] = src[2]; \
  1107             dst[3] = src[3]; \
  1108             dst[4] = src[4]; \
  1109             dst[5] = src[5]; \
  1110             src += 12; \
  1111             dst += 6; \
  1112         } \
  1113     }
  1114 
  1115     switch (SDL_AUDIO_BITSIZE(format)) {
  1116     case 8:
  1117         div2_chansix(Uint8);
  1118         break;
  1119     case 16:
  1120         div2_chansix(Uint16);
  1121         break;
  1122     case 32:
  1123         div2_chansix(Uint32);
  1124         break;
  1125     }
  1126 
  1127 #undef div_chansix
  1128 
  1129     cvt->len_cvt /= 2;
  1130     if (cvt->filters[++cvt->filter_index]) {
  1131         cvt->filters[cvt->filter_index] (cvt, format);
  1132     }
  1133 }
  1134 
  1135 /* Very slow rate conversion routine */
  1136 static void SDLCALL
  1137 SDL_RateSLOW(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1138 {
  1139     double ipos;
  1140     int i, clen;
  1141 
  1142 #ifdef DEBUG_CONVERT
  1143     fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
  1144 #endif
  1145     clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
  1146     if (cvt->rate_incr > 1.0) {
  1147         switch (SDL_AUDIO_BITSIZE(format)) {
  1148         case 8:
  1149             {
  1150                 Uint8 *output;
  1151 
  1152                 output = cvt->buf;
  1153                 ipos = 0.0;
  1154                 for (i = clen; i; --i) {
  1155                     *output = cvt->buf[(int) ipos];
  1156                     ipos += cvt->rate_incr;
  1157                     output += 1;
  1158                 }
  1159             }
  1160             break;
  1161 
  1162         case 16:
  1163             {
  1164                 Uint16 *output;
  1165 
  1166                 clen &= ~1;
  1167                 output = (Uint16 *) cvt->buf;
  1168                 ipos = 0.0;
  1169                 for (i = clen / 2; i; --i) {
  1170                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1171                     ipos += cvt->rate_incr;
  1172                     output += 1;
  1173                 }
  1174             }
  1175             break;
  1176 
  1177         case 32:
  1178             {
  1179                 /* !!! FIXME: need 32-bit converter here! */
  1180                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1181             }
  1182         }
  1183     } else {
  1184         switch (SDL_AUDIO_BITSIZE(format)) {
  1185         case 8:
  1186             {
  1187                 Uint8 *output;
  1188 
  1189                 output = cvt->buf + clen;
  1190                 ipos = (double) cvt->len_cvt;
  1191                 for (i = clen; i; --i) {
  1192                     ipos -= cvt->rate_incr;
  1193                     output -= 1;
  1194                     *output = cvt->buf[(int) ipos];
  1195                 }
  1196             }
  1197             break;
  1198 
  1199         case 16:
  1200             {
  1201                 Uint16 *output;
  1202 
  1203                 clen &= ~1;
  1204                 output = (Uint16 *) (cvt->buf + clen);
  1205                 ipos = (double) cvt->len_cvt / 2;
  1206                 for (i = clen / 2; i; --i) {
  1207                     ipos -= cvt->rate_incr;
  1208                     output -= 1;
  1209                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1210                 }
  1211             }
  1212             break;
  1213 
  1214         case 32:
  1215             {
  1216                 /* !!! FIXME: need 32-bit converter here! */
  1217                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1218             }
  1219         }
  1220     }
  1221 
  1222     cvt->len_cvt = clen;
  1223     if (cvt->filters[++cvt->filter_index]) {
  1224         cvt->filters[cvt->filter_index] (cvt, format);
  1225     }
  1226 }
  1227 
  1228 int
  1229 SDL_ConvertAudio(SDL_AudioCVT * cvt)
  1230 {
  1231     /* Make sure there's data to convert */
  1232     if (cvt->buf == NULL) {
  1233         SDL_SetError("No buffer allocated for conversion");
  1234         return (-1);
  1235     }
  1236     /* Return okay if no conversion is necessary */
  1237     cvt->len_cvt = cvt->len;
  1238     if (cvt->filters[0] == NULL) {
  1239         return (0);
  1240     }
  1241 
  1242     /* Set up the conversion and go! */
  1243     cvt->filter_index = 0;
  1244     cvt->filters[0] (cvt, cvt->src_format);
  1245     return (0);
  1246 }
  1247 
  1248 
  1249 static SDL_AudioFilter
  1250 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1251 {
  1252     /*
  1253      * Fill in any future conversions that are specialized to a
  1254      *  processor, platform, compiler, or library here.
  1255      */
  1256 
  1257     return NULL;                /* no specialized converter code available. */
  1258 }
  1259 
  1260 
  1261 /*
  1262  * Find a converter between two data types. We try to select a hand-tuned
  1263  *  asm/vectorized/optimized function first, and then fallback to an
  1264  *  autogenerated function that is customized to convert between two
  1265  *  specific data types.
  1266  */
  1267 static int
  1268 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
  1269                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1270 {
  1271     if (src_fmt != dst_fmt) {
  1272         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
  1273         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
  1274         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
  1275 
  1276         /* No hand-tuned converter? Try the autogenerated ones. */
  1277         if (filter == NULL) {
  1278             int i;
  1279             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
  1280                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
  1281                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
  1282                     filter = filt->filter;
  1283                     break;
  1284                 }
  1285             }
  1286 
  1287             if (filter == NULL) {
  1288                 return -1;      /* Still no matching converter?! */
  1289             }
  1290         }
  1291 
  1292         /* Update (cvt) with filter details... */
  1293         cvt->filters[cvt->filter_index++] = filter;
  1294         if (src_bitsize < dst_bitsize) {
  1295             const int mult = (dst_bitsize / src_bitsize);
  1296             cvt->len_mult *= mult;
  1297             cvt->len_ratio *= mult;
  1298         } else if (src_bitsize > dst_bitsize) {
  1299             cvt->len_ratio /= (src_bitsize / dst_bitsize);
  1300         }
  1301 
  1302         return 1;               /* added a converter. */
  1303     }
  1304 
  1305     return 0;                   /* no conversion necessary. */
  1306 }
  1307 
  1308 
  1309 
  1310 /* Creates a set of audio filters to convert from one format to another.
  1311    Returns -1 if the format conversion is not supported, 0 if there's
  1312    no conversion needed, or 1 if the audio filter is set up.
  1313 */
  1314 
  1315 int
  1316 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
  1317                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1318                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1319 {
  1320     /* there are no unsigned types over 16 bits, so catch this upfront. */
  1321     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1322         return -1;
  1323     }
  1324     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1325         return -1;
  1326     }
  1327 #ifdef DEBUG_CONVERT
  1328     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1329            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1330 #endif
  1331 
  1332     /* Start off with no conversion necessary */
  1333 
  1334     cvt->src_format = src_fmt;
  1335     cvt->dst_format = dst_fmt;
  1336     cvt->needed = 0;
  1337     cvt->filter_index = 0;
  1338     cvt->filters[0] = NULL;
  1339     cvt->len_mult = 1;
  1340     cvt->len_ratio = 1.0;
  1341 
  1342     /* Convert data types, if necessary. Updates (cvt). */
  1343     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1344         return -1;              /* shouldn't happen, but just in case... */
  1345 
  1346     /* Channel conversion */
  1347     if (src_channels != dst_channels) {
  1348         if ((src_channels == 1) && (dst_channels > 1)) {
  1349             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1350             cvt->len_mult *= 2;
  1351             src_channels = 2;
  1352             cvt->len_ratio *= 2;
  1353         }
  1354         if ((src_channels == 2) && (dst_channels == 6)) {
  1355             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1356             src_channels = 6;
  1357             cvt->len_mult *= 3;
  1358             cvt->len_ratio *= 3;
  1359         }
  1360         if ((src_channels == 2) && (dst_channels == 4)) {
  1361             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1362             src_channels = 4;
  1363             cvt->len_mult *= 2;
  1364             cvt->len_ratio *= 2;
  1365         }
  1366         while ((src_channels * 2) <= dst_channels) {
  1367             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1368             cvt->len_mult *= 2;
  1369             src_channels *= 2;
  1370             cvt->len_ratio *= 2;
  1371         }
  1372         if ((src_channels == 6) && (dst_channels <= 2)) {
  1373             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1374             src_channels = 2;
  1375             cvt->len_ratio /= 3;
  1376         }
  1377         if ((src_channels == 6) && (dst_channels == 4)) {
  1378             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1379             src_channels = 4;
  1380             cvt->len_ratio /= 2;
  1381         }
  1382         /* This assumes that 4 channel audio is in the format:
  1383            Left {front/back} + Right {front/back}
  1384            so converting to L/R stereo works properly.
  1385          */
  1386         while (((src_channels % 2) == 0) &&
  1387                ((src_channels / 2) >= dst_channels)) {
  1388             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1389             src_channels /= 2;
  1390             cvt->len_ratio /= 2;
  1391         }
  1392         if (src_channels != dst_channels) {
  1393             /* Uh oh.. */ ;
  1394         }
  1395     }
  1396 
  1397     /* Do rate conversion */
  1398     cvt->rate_incr = 0.0;
  1399     if ((src_rate / 100) != (dst_rate / 100)) {
  1400         Uint32 hi_rate, lo_rate;
  1401         int len_mult;
  1402         double len_ratio;
  1403         SDL_AudioFilter rate_cvt = NULL;
  1404 
  1405         if (src_rate > dst_rate) {
  1406             hi_rate = src_rate;
  1407             lo_rate = dst_rate;
  1408             switch (src_channels) {
  1409             case 1:
  1410                 rate_cvt = SDL_RateDIV2;
  1411                 break;
  1412             case 2:
  1413                 rate_cvt = SDL_RateDIV2_c2;
  1414                 break;
  1415             case 4:
  1416                 rate_cvt = SDL_RateDIV2_c4;
  1417                 break;
  1418             case 6:
  1419                 rate_cvt = SDL_RateDIV2_c6;
  1420                 break;
  1421             default:
  1422                 return -1;
  1423             }
  1424             len_mult = 1;
  1425             len_ratio = 0.5;
  1426         } else {
  1427             hi_rate = dst_rate;
  1428             lo_rate = src_rate;
  1429             switch (src_channels) {
  1430             case 1:
  1431                 rate_cvt = SDL_RateMUL2;
  1432                 break;
  1433             case 2:
  1434                 rate_cvt = SDL_RateMUL2_c2;
  1435                 break;
  1436             case 4:
  1437                 rate_cvt = SDL_RateMUL2_c4;
  1438                 break;
  1439             case 6:
  1440                 rate_cvt = SDL_RateMUL2_c6;
  1441                 break;
  1442             default:
  1443                 return -1;
  1444             }
  1445             len_mult = 2;
  1446             len_ratio = 2.0;
  1447         }
  1448         /* If hi_rate = lo_rate*2^x then conversion is easy */
  1449         while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1450             cvt->filters[cvt->filter_index++] = rate_cvt;
  1451             cvt->len_mult *= len_mult;
  1452             lo_rate *= 2;
  1453             cvt->len_ratio *= len_ratio;
  1454         }
  1455         /* We may need a slow conversion here to finish up */
  1456         if ((lo_rate / 100) != (hi_rate / 100)) {
  1457 #if 1
  1458             /* The problem with this is that if the input buffer is
  1459                say 1K, and the conversion rate is say 1.1, then the
  1460                output buffer is 1.1K, which may not be an acceptable
  1461                buffer size for the audio driver (not a power of 2)
  1462              */
  1463             /* For now, punt and hope the rate distortion isn't great.
  1464              */
  1465 #else
  1466             if (src_rate < dst_rate) {
  1467                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1468                 cvt->len_mult *= 2;
  1469                 cvt->len_ratio /= cvt->rate_incr;
  1470             } else {
  1471                 cvt->rate_incr = (double) hi_rate / lo_rate;
  1472                 cvt->len_ratio *= cvt->rate_incr;
  1473             }
  1474             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1475 #endif
  1476         }
  1477     }
  1478 
  1479     /* Set up the filter information */
  1480     if (cvt->filter_index != 0) {
  1481         cvt->needed = 1;
  1482         cvt->src_format = src_fmt;
  1483         cvt->dst_format = dst_fmt;
  1484         cvt->len = 0;
  1485         cvt->buf = NULL;
  1486         cvt->filters[cvt->filter_index] = NULL;
  1487     }
  1488     return (cvt->needed);
  1489 }
  1490 
  1491 /* vi: set ts=4 sw=4 expandtab: */