src/audio/SDL_audiocvt.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 24 Aug 2006 12:10:46 +0000
changeset 1982 3b4ce57c6215
parent 1895 c121d94672cb
child 1985 8055185ae4ed
permissions -rw-r--r--
First shot at new audio data types (int32 and float32).

Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.

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