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