src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 19 Jun 2007 05:53:56 +0000
changeset 2130 3ee59c43d784
parent 2078 f932ac47a331
child 2655 b8e736c8a5a8
child 2716 f8f68f47285a
permissions -rw-r--r--
Fixes for compiling with Visual C++ 8.0 Express Edition
     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 / 2)));
   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 / 2)));
   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 #ifdef DEBUG_CONVERT
  1181                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1182 #endif
  1183             }
  1184         }
  1185     } else {
  1186         switch (SDL_AUDIO_BITSIZE(format)) {
  1187         case 8:
  1188             {
  1189                 Uint8 *output;
  1190 
  1191                 output = cvt->buf + clen;
  1192                 ipos = (double) cvt->len_cvt;
  1193                 for (i = clen; i; --i) {
  1194                     ipos -= cvt->rate_incr;
  1195                     output -= 1;
  1196                     *output = cvt->buf[(int) ipos];
  1197                 }
  1198             }
  1199             break;
  1200 
  1201         case 16:
  1202             {
  1203                 Uint16 *output;
  1204 
  1205                 clen &= ~1;
  1206                 output = (Uint16 *) (cvt->buf + clen);
  1207                 ipos = (double) cvt->len_cvt / 2;
  1208                 for (i = clen / 2; i; --i) {
  1209                     ipos -= cvt->rate_incr;
  1210                     output -= 1;
  1211                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1212                 }
  1213             }
  1214             break;
  1215 
  1216         case 32:
  1217             {
  1218                 /* !!! FIXME: need 32-bit converter here! */
  1219 #ifdef DEBUG_CONVERT
  1220                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1221 #endif
  1222             }
  1223         }
  1224     }
  1225 
  1226     cvt->len_cvt = clen;
  1227     if (cvt->filters[++cvt->filter_index]) {
  1228         cvt->filters[cvt->filter_index] (cvt, format);
  1229     }
  1230 }
  1231 
  1232 int
  1233 SDL_ConvertAudio(SDL_AudioCVT * cvt)
  1234 {
  1235     /* Make sure there's data to convert */
  1236     if (cvt->buf == NULL) {
  1237         SDL_SetError("No buffer allocated for conversion");
  1238         return (-1);
  1239     }
  1240     /* Return okay if no conversion is necessary */
  1241     cvt->len_cvt = cvt->len;
  1242     if (cvt->filters[0] == NULL) {
  1243         return (0);
  1244     }
  1245 
  1246     /* Set up the conversion and go! */
  1247     cvt->filter_index = 0;
  1248     cvt->filters[0] (cvt, cvt->src_format);
  1249     return (0);
  1250 }
  1251 
  1252 
  1253 static SDL_AudioFilter
  1254 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1255 {
  1256     /*
  1257      * Fill in any future conversions that are specialized to a
  1258      *  processor, platform, compiler, or library here.
  1259      */
  1260 
  1261     return NULL;                /* no specialized converter code available. */
  1262 }
  1263 
  1264 
  1265 /*
  1266  * Find a converter between two data types. We try to select a hand-tuned
  1267  *  asm/vectorized/optimized function first, and then fallback to an
  1268  *  autogenerated function that is customized to convert between two
  1269  *  specific data types.
  1270  */
  1271 static int
  1272 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
  1273                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1274 {
  1275     if (src_fmt != dst_fmt) {
  1276         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
  1277         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
  1278         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
  1279 
  1280         /* No hand-tuned converter? Try the autogenerated ones. */
  1281         if (filter == NULL) {
  1282             int i;
  1283             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
  1284                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
  1285                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
  1286                     filter = filt->filter;
  1287                     break;
  1288                 }
  1289             }
  1290 
  1291             if (filter == NULL) {
  1292                 return -1;      /* Still no matching converter?! */
  1293             }
  1294         }
  1295 
  1296         /* Update (cvt) with filter details... */
  1297         cvt->filters[cvt->filter_index++] = filter;
  1298         if (src_bitsize < dst_bitsize) {
  1299             const int mult = (dst_bitsize / src_bitsize);
  1300             cvt->len_mult *= mult;
  1301             cvt->len_ratio *= mult;
  1302         } else if (src_bitsize > dst_bitsize) {
  1303             cvt->len_ratio /= (src_bitsize / dst_bitsize);
  1304         }
  1305 
  1306         return 1;               /* added a converter. */
  1307     }
  1308 
  1309     return 0;                   /* no conversion necessary. */
  1310 }
  1311 
  1312 
  1313 
  1314 /* Creates a set of audio filters to convert from one format to another.
  1315    Returns -1 if the format conversion is not supported, 0 if there's
  1316    no conversion needed, or 1 if the audio filter is set up.
  1317 */
  1318 
  1319 int
  1320 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
  1321                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1322                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1323 {
  1324     /* there are no unsigned types over 16 bits, so catch this upfront. */
  1325     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1326         return -1;
  1327     }
  1328     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1329         return -1;
  1330     }
  1331 #ifdef DEBUG_CONVERT
  1332     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1333            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1334 #endif
  1335 
  1336     /* Start off with no conversion necessary */
  1337 
  1338     cvt->src_format = src_fmt;
  1339     cvt->dst_format = dst_fmt;
  1340     cvt->needed = 0;
  1341     cvt->filter_index = 0;
  1342     cvt->filters[0] = NULL;
  1343     cvt->len_mult = 1;
  1344     cvt->len_ratio = 1.0;
  1345 
  1346     /* Convert data types, if necessary. Updates (cvt). */
  1347     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1348         return -1;              /* shouldn't happen, but just in case... */
  1349 
  1350     /* Channel conversion */
  1351     if (src_channels != dst_channels) {
  1352         if ((src_channels == 1) && (dst_channels > 1)) {
  1353             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1354             cvt->len_mult *= 2;
  1355             src_channels = 2;
  1356             cvt->len_ratio *= 2;
  1357         }
  1358         if ((src_channels == 2) && (dst_channels == 6)) {
  1359             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1360             src_channels = 6;
  1361             cvt->len_mult *= 3;
  1362             cvt->len_ratio *= 3;
  1363         }
  1364         if ((src_channels == 2) && (dst_channels == 4)) {
  1365             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1366             src_channels = 4;
  1367             cvt->len_mult *= 2;
  1368             cvt->len_ratio *= 2;
  1369         }
  1370         while ((src_channels * 2) <= dst_channels) {
  1371             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1372             cvt->len_mult *= 2;
  1373             src_channels *= 2;
  1374             cvt->len_ratio *= 2;
  1375         }
  1376         if ((src_channels == 6) && (dst_channels <= 2)) {
  1377             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1378             src_channels = 2;
  1379             cvt->len_ratio /= 3;
  1380         }
  1381         if ((src_channels == 6) && (dst_channels == 4)) {
  1382             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1383             src_channels = 4;
  1384             cvt->len_ratio /= 2;
  1385         }
  1386         /* This assumes that 4 channel audio is in the format:
  1387            Left {front/back} + Right {front/back}
  1388            so converting to L/R stereo works properly.
  1389          */
  1390         while (((src_channels % 2) == 0) &&
  1391                ((src_channels / 2) >= dst_channels)) {
  1392             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1393             src_channels /= 2;
  1394             cvt->len_ratio /= 2;
  1395         }
  1396         if (src_channels != dst_channels) {
  1397             /* Uh oh.. */ ;
  1398         }
  1399     }
  1400 
  1401     /* Do rate conversion */
  1402     cvt->rate_incr = 0.0;
  1403     if ((src_rate / 100) != (dst_rate / 100)) {
  1404         Uint32 hi_rate, lo_rate;
  1405         int len_mult;
  1406         double len_ratio;
  1407         SDL_AudioFilter rate_cvt = NULL;
  1408 
  1409         if (src_rate > dst_rate) {
  1410             hi_rate = src_rate;
  1411             lo_rate = dst_rate;
  1412             switch (src_channels) {
  1413             case 1:
  1414                 rate_cvt = SDL_RateDIV2;
  1415                 break;
  1416             case 2:
  1417                 rate_cvt = SDL_RateDIV2_c2;
  1418                 break;
  1419             case 4:
  1420                 rate_cvt = SDL_RateDIV2_c4;
  1421                 break;
  1422             case 6:
  1423                 rate_cvt = SDL_RateDIV2_c6;
  1424                 break;
  1425             default:
  1426                 return -1;
  1427             }
  1428             len_mult = 1;
  1429             len_ratio = 0.5;
  1430         } else {
  1431             hi_rate = dst_rate;
  1432             lo_rate = src_rate;
  1433             switch (src_channels) {
  1434             case 1:
  1435                 rate_cvt = SDL_RateMUL2;
  1436                 break;
  1437             case 2:
  1438                 rate_cvt = SDL_RateMUL2_c2;
  1439                 break;
  1440             case 4:
  1441                 rate_cvt = SDL_RateMUL2_c4;
  1442                 break;
  1443             case 6:
  1444                 rate_cvt = SDL_RateMUL2_c6;
  1445                 break;
  1446             default:
  1447                 return -1;
  1448             }
  1449             len_mult = 2;
  1450             len_ratio = 2.0;
  1451         }
  1452         /* If hi_rate = lo_rate*2^x then conversion is easy */
  1453         while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1454             cvt->filters[cvt->filter_index++] = rate_cvt;
  1455             cvt->len_mult *= len_mult;
  1456             lo_rate *= 2;
  1457             cvt->len_ratio *= len_ratio;
  1458         }
  1459         /* We may need a slow conversion here to finish up */
  1460         if ((lo_rate / 100) != (hi_rate / 100)) {
  1461 #if 1
  1462             /* The problem with this is that if the input buffer is
  1463                say 1K, and the conversion rate is say 1.1, then the
  1464                output buffer is 1.1K, which may not be an acceptable
  1465                buffer size for the audio driver (not a power of 2)
  1466              */
  1467             /* For now, punt and hope the rate distortion isn't great.
  1468              */
  1469 #else
  1470             if (src_rate < dst_rate) {
  1471                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1472                 cvt->len_mult *= 2;
  1473                 cvt->len_ratio /= cvt->rate_incr;
  1474             } else {
  1475                 cvt->rate_incr = (double) hi_rate / lo_rate;
  1476                 cvt->len_ratio *= cvt->rate_incr;
  1477             }
  1478             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1479 #endif
  1480         }
  1481     }
  1482 
  1483     /* Set up the filter information */
  1484     if (cvt->filter_index != 0) {
  1485         cvt->needed = 1;
  1486         cvt->src_format = src_fmt;
  1487         cvt->dst_format = dst_fmt;
  1488         cvt->len = 0;
  1489         cvt->buf = NULL;
  1490         cvt->filters[cvt->filter_index] = NULL;
  1491     }
  1492     return (cvt->needed);
  1493 }
  1494 
  1495 /* vi: set ts=4 sw=4 expandtab: */