src/audio/SDL_audiocvt.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 6885 700f1b25f77f
child 7191 75360622e65f
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


Fixes Bugzilla #1778.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* Functions for audio drivers to perform runtime conversion of audio format */
    24 
    25 #include "SDL_audio.h"
    26 #include "SDL_audio_c.h"
    27 
    28 #include "SDL_assert.h"
    29 
    30 /* #define DEBUG_CONVERT */
    31 
    32 /* Effectively mix right and left channels into a single channel */
    33 static void SDLCALL
    34 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    35 {
    36     int i;
    37     Sint32 sample;
    38 
    39 #ifdef DEBUG_CONVERT
    40     fprintf(stderr, "Converting to mono\n");
    41 #endif
    42     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
    43     case AUDIO_U8:
    44         {
    45             Uint8 *src, *dst;
    46 
    47             src = cvt->buf;
    48             dst = cvt->buf;
    49             for (i = cvt->len_cvt / 2; i; --i) {
    50                 sample = src[0] + src[1];
    51                 *dst = (Uint8) (sample / 2);
    52                 src += 2;
    53                 dst += 1;
    54             }
    55         }
    56         break;
    57 
    58     case AUDIO_S8:
    59         {
    60             Sint8 *src, *dst;
    61 
    62             src = (Sint8 *) cvt->buf;
    63             dst = (Sint8 *) cvt->buf;
    64             for (i = cvt->len_cvt / 2; i; --i) {
    65                 sample = src[0] + src[1];
    66                 *dst = (Sint8) (sample / 2);
    67                 src += 2;
    68                 dst += 1;
    69             }
    70         }
    71         break;
    72 
    73     case AUDIO_U16:
    74         {
    75             Uint8 *src, *dst;
    76 
    77             src = cvt->buf;
    78             dst = cvt->buf;
    79             if (SDL_AUDIO_ISBIGENDIAN(format)) {
    80                 for (i = cvt->len_cvt / 4; i; --i) {
    81                     sample = (Uint16) ((src[0] << 8) | src[1]) +
    82                         (Uint16) ((src[2] << 8) | src[3]);
    83                     sample /= 2;
    84                     dst[1] = (sample & 0xFF);
    85                     sample >>= 8;
    86                     dst[0] = (sample & 0xFF);
    87                     src += 4;
    88                     dst += 2;
    89                 }
    90             } else {
    91                 for (i = cvt->len_cvt / 4; i; --i) {
    92                     sample = (Uint16) ((src[1] << 8) | src[0]) +
    93                         (Uint16) ((src[3] << 8) | src[2]);
    94                     sample /= 2;
    95                     dst[0] = (sample & 0xFF);
    96                     sample >>= 8;
    97                     dst[1] = (sample & 0xFF);
    98                     src += 4;
    99                     dst += 2;
   100                 }
   101             }
   102         }
   103         break;
   104 
   105     case AUDIO_S16:
   106         {
   107             Uint8 *src, *dst;
   108 
   109             src = cvt->buf;
   110             dst = cvt->buf;
   111             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   112                 for (i = cvt->len_cvt / 4; i; --i) {
   113                     sample = (Sint16) ((src[0] << 8) | src[1]) +
   114                         (Sint16) ((src[2] << 8) | src[3]);
   115                     sample /= 2;
   116                     dst[1] = (sample & 0xFF);
   117                     sample >>= 8;
   118                     dst[0] = (sample & 0xFF);
   119                     src += 4;
   120                     dst += 2;
   121                 }
   122             } else {
   123                 for (i = cvt->len_cvt / 4; i; --i) {
   124                     sample = (Sint16) ((src[1] << 8) | src[0]) +
   125                         (Sint16) ((src[3] << 8) | src[2]);
   126                     sample /= 2;
   127                     dst[0] = (sample & 0xFF);
   128                     sample >>= 8;
   129                     dst[1] = (sample & 0xFF);
   130                     src += 4;
   131                     dst += 2;
   132                 }
   133             }
   134         }
   135         break;
   136 
   137     case AUDIO_S32:
   138         {
   139             const Uint32 *src = (const Uint32 *) cvt->buf;
   140             Uint32 *dst = (Uint32 *) cvt->buf;
   141             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   142                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   143                     const Sint64 added =
   144                         (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
   145                          ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
   146                     *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
   147                 }
   148             } else {
   149                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   150                     const Sint64 added =
   151                         (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
   152                          ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
   153                     *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
   154                 }
   155             }
   156         }
   157         break;
   158 
   159     case AUDIO_F32:
   160         {
   161             const float *src = (const float *) cvt->buf;
   162             float *dst = (float *) cvt->buf;
   163             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   164                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   165                     const float src1 = SDL_SwapFloatBE(src[0]);
   166                     const float src2 = SDL_SwapFloatBE(src[1]);
   167                     const double added = ((double) src1) + ((double) src2);
   168                     const float halved = (float) (added * 0.5);
   169                     *(dst++) = SDL_SwapFloatBE(halved);
   170                 }
   171             } else {
   172                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   173                     const float src1 = SDL_SwapFloatLE(src[0]);
   174                     const float src2 = SDL_SwapFloatLE(src[1]);
   175                     const double added = ((double) src1) + ((double) src2);
   176                     const float halved = (float) (added * 0.5);
   177                     *(dst++) = SDL_SwapFloatLE(halved);
   178                 }
   179             }
   180         }
   181         break;
   182     }
   183 
   184     cvt->len_cvt /= 2;
   185     if (cvt->filters[++cvt->filter_index]) {
   186         cvt->filters[cvt->filter_index] (cvt, format);
   187     }
   188 }
   189 
   190 
   191 /* Discard top 4 channels */
   192 static void SDLCALL
   193 SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   194 {
   195     int i;
   196 
   197 #ifdef DEBUG_CONVERT
   198     fprintf(stderr, "Converting down from 6 channels to stereo\n");
   199 #endif
   200 
   201 #define strip_chans_6_to_2(type) \
   202     { \
   203         const type *src = (const type *) cvt->buf; \
   204         type *dst = (type *) cvt->buf; \
   205         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   206             dst[0] = src[0]; \
   207             dst[1] = src[1]; \
   208             src += 6; \
   209             dst += 2; \
   210         } \
   211     }
   212 
   213     /* this function only cares about typesize, and data as a block of bits. */
   214     switch (SDL_AUDIO_BITSIZE(format)) {
   215     case 8:
   216         strip_chans_6_to_2(Uint8);
   217         break;
   218     case 16:
   219         strip_chans_6_to_2(Uint16);
   220         break;
   221     case 32:
   222         strip_chans_6_to_2(Uint32);
   223         break;
   224     }
   225 
   226 #undef strip_chans_6_to_2
   227 
   228     cvt->len_cvt /= 3;
   229     if (cvt->filters[++cvt->filter_index]) {
   230         cvt->filters[cvt->filter_index] (cvt, format);
   231     }
   232 }
   233 
   234 
   235 /* Discard top 2 channels of 6 */
   236 static void SDLCALL
   237 SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   238 {
   239     int i;
   240 
   241 #ifdef DEBUG_CONVERT
   242     fprintf(stderr, "Converting 6 down to quad\n");
   243 #endif
   244 
   245 #define strip_chans_6_to_4(type) \
   246     { \
   247         const type *src = (const type *) cvt->buf; \
   248         type *dst = (type *) cvt->buf; \
   249         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   250             dst[0] = src[0]; \
   251             dst[1] = src[1]; \
   252             dst[2] = src[2]; \
   253             dst[3] = src[3]; \
   254             src += 6; \
   255             dst += 4; \
   256         } \
   257     }
   258 
   259     /* this function only cares about typesize, and data as a block of bits. */
   260     switch (SDL_AUDIO_BITSIZE(format)) {
   261     case 8:
   262         strip_chans_6_to_4(Uint8);
   263         break;
   264     case 16:
   265         strip_chans_6_to_4(Uint16);
   266         break;
   267     case 32:
   268         strip_chans_6_to_4(Uint32);
   269         break;
   270     }
   271 
   272 #undef strip_chans_6_to_4
   273 
   274     cvt->len_cvt /= 6;
   275     cvt->len_cvt *= 4;
   276     if (cvt->filters[++cvt->filter_index]) {
   277         cvt->filters[cvt->filter_index] (cvt, format);
   278     }
   279 }
   280 
   281 /* Duplicate a mono channel to both stereo channels */
   282 static void SDLCALL
   283 SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   284 {
   285     int i;
   286 
   287 #ifdef DEBUG_CONVERT
   288     fprintf(stderr, "Converting to stereo\n");
   289 #endif
   290 
   291 #define dup_chans_1_to_2(type) \
   292     { \
   293         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   294         type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
   295         for (i = cvt->len_cvt / sizeof(type); i; --i) { \
   296             const type val = *src; \
   297             src -= 1; \
   298             dst -= 2; \
   299             dst[0] = dst[1] = val; \
   300         } \
   301     }
   302 
   303     /* this function only cares about typesize, and data as a block of bits. */
   304     switch (SDL_AUDIO_BITSIZE(format)) {
   305     case 8:
   306         dup_chans_1_to_2(Uint8);
   307         break;
   308     case 16:
   309         dup_chans_1_to_2(Uint16);
   310         break;
   311     case 32:
   312         dup_chans_1_to_2(Uint32);
   313         break;
   314     }
   315 
   316 #undef dup_chans_1_to_2
   317 
   318     cvt->len_cvt *= 2;
   319     if (cvt->filters[++cvt->filter_index]) {
   320         cvt->filters[cvt->filter_index] (cvt, format);
   321     }
   322 }
   323 
   324 
   325 /* Duplicate a stereo channel to a pseudo-5.1 stream */
   326 static void SDLCALL
   327 SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   328 {
   329     int i;
   330 
   331 #ifdef DEBUG_CONVERT
   332     fprintf(stderr, "Converting stereo to surround\n");
   333 #endif
   334 
   335     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   336     case AUDIO_U8:
   337         {
   338             Uint8 *src, *dst, lf, rf, ce;
   339 
   340             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   341             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
   342             for (i = cvt->len_cvt; i; --i) {
   343                 dst -= 6;
   344                 src -= 2;
   345                 lf = src[0];
   346                 rf = src[1];
   347                 ce = (lf / 2) + (rf / 2);
   348                 dst[0] = lf;
   349                 dst[1] = rf;
   350                 dst[2] = lf - ce;
   351                 dst[3] = rf - ce;
   352                 dst[4] = ce;
   353                 dst[5] = ce;
   354             }
   355         }
   356         break;
   357 
   358     case AUDIO_S8:
   359         {
   360             Sint8 *src, *dst, lf, rf, ce;
   361 
   362             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   363             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
   364             for (i = cvt->len_cvt; i; --i) {
   365                 dst -= 6;
   366                 src -= 2;
   367                 lf = src[0];
   368                 rf = src[1];
   369                 ce = (lf / 2) + (rf / 2);
   370                 dst[0] = lf;
   371                 dst[1] = rf;
   372                 dst[2] = lf - ce;
   373                 dst[3] = rf - ce;
   374                 dst[4] = ce;
   375                 dst[5] = ce;
   376             }
   377         }
   378         break;
   379 
   380     case AUDIO_U16:
   381         {
   382             Uint8 *src, *dst;
   383             Uint16 lf, rf, ce, lr, rr;
   384 
   385             src = cvt->buf + cvt->len_cvt;
   386             dst = cvt->buf + cvt->len_cvt * 3;
   387 
   388             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   389                 for (i = cvt->len_cvt / 4; i; --i) {
   390                     dst -= 12;
   391                     src -= 4;
   392                     lf = (Uint16) ((src[0] << 8) | src[1]);
   393                     rf = (Uint16) ((src[2] << 8) | src[3]);
   394                     ce = (lf / 2) + (rf / 2);
   395                     rr = lf - ce;
   396                     lr = rf - ce;
   397                     dst[1] = (lf & 0xFF);
   398                     dst[0] = ((lf >> 8) & 0xFF);
   399                     dst[3] = (rf & 0xFF);
   400                     dst[2] = ((rf >> 8) & 0xFF);
   401 
   402                     dst[1 + 4] = (lr & 0xFF);
   403                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   404                     dst[3 + 4] = (rr & 0xFF);
   405                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   406 
   407                     dst[1 + 8] = (ce & 0xFF);
   408                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   409                     dst[3 + 8] = (ce & 0xFF);
   410                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   411                 }
   412             } else {
   413                 for (i = cvt->len_cvt / 4; i; --i) {
   414                     dst -= 12;
   415                     src -= 4;
   416                     lf = (Uint16) ((src[1] << 8) | src[0]);
   417                     rf = (Uint16) ((src[3] << 8) | src[2]);
   418                     ce = (lf / 2) + (rf / 2);
   419                     rr = lf - ce;
   420                     lr = rf - ce;
   421                     dst[0] = (lf & 0xFF);
   422                     dst[1] = ((lf >> 8) & 0xFF);
   423                     dst[2] = (rf & 0xFF);
   424                     dst[3] = ((rf >> 8) & 0xFF);
   425 
   426                     dst[0 + 4] = (lr & 0xFF);
   427                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   428                     dst[2 + 4] = (rr & 0xFF);
   429                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   430 
   431                     dst[0 + 8] = (ce & 0xFF);
   432                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   433                     dst[2 + 8] = (ce & 0xFF);
   434                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   435                 }
   436             }
   437         }
   438         break;
   439 
   440     case AUDIO_S16:
   441         {
   442             Uint8 *src, *dst;
   443             Sint16 lf, rf, ce, lr, rr;
   444 
   445             src = cvt->buf + cvt->len_cvt;
   446             dst = cvt->buf + cvt->len_cvt * 3;
   447 
   448             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   449                 for (i = cvt->len_cvt / 4; i; --i) {
   450                     dst -= 12;
   451                     src -= 4;
   452                     lf = (Sint16) ((src[0] << 8) | src[1]);
   453                     rf = (Sint16) ((src[2] << 8) | src[3]);
   454                     ce = (lf / 2) + (rf / 2);
   455                     rr = lf - ce;
   456                     lr = rf - ce;
   457                     dst[1] = (lf & 0xFF);
   458                     dst[0] = ((lf >> 8) & 0xFF);
   459                     dst[3] = (rf & 0xFF);
   460                     dst[2] = ((rf >> 8) & 0xFF);
   461 
   462                     dst[1 + 4] = (lr & 0xFF);
   463                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   464                     dst[3 + 4] = (rr & 0xFF);
   465                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   466 
   467                     dst[1 + 8] = (ce & 0xFF);
   468                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   469                     dst[3 + 8] = (ce & 0xFF);
   470                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   471                 }
   472             } else {
   473                 for (i = cvt->len_cvt / 4; i; --i) {
   474                     dst -= 12;
   475                     src -= 4;
   476                     lf = (Sint16) ((src[1] << 8) | src[0]);
   477                     rf = (Sint16) ((src[3] << 8) | src[2]);
   478                     ce = (lf / 2) + (rf / 2);
   479                     rr = lf - ce;
   480                     lr = rf - ce;
   481                     dst[0] = (lf & 0xFF);
   482                     dst[1] = ((lf >> 8) & 0xFF);
   483                     dst[2] = (rf & 0xFF);
   484                     dst[3] = ((rf >> 8) & 0xFF);
   485 
   486                     dst[0 + 4] = (lr & 0xFF);
   487                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   488                     dst[2 + 4] = (rr & 0xFF);
   489                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   490 
   491                     dst[0 + 8] = (ce & 0xFF);
   492                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   493                     dst[2 + 8] = (ce & 0xFF);
   494                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   495                 }
   496             }
   497         }
   498         break;
   499 
   500     case AUDIO_S32:
   501         {
   502             Sint32 lf, rf, ce;
   503             const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
   504             Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
   505 
   506             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   507                 for (i = cvt->len_cvt / 8; i; --i) {
   508                     dst -= 6;
   509                     src -= 2;
   510                     lf = (Sint32) SDL_SwapBE32(src[0]);
   511                     rf = (Sint32) SDL_SwapBE32(src[1]);
   512                     ce = (lf / 2) + (rf / 2);
   513                     dst[0] = SDL_SwapBE32((Uint32) lf);
   514                     dst[1] = SDL_SwapBE32((Uint32) rf);
   515                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   516                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   517                     dst[4] = SDL_SwapBE32((Uint32) ce);
   518                     dst[5] = SDL_SwapBE32((Uint32) ce);
   519                 }
   520             } else {
   521                 for (i = cvt->len_cvt / 8; i; --i) {
   522                     dst -= 6;
   523                     src -= 2;
   524                     lf = (Sint32) SDL_SwapLE32(src[0]);
   525                     rf = (Sint32) SDL_SwapLE32(src[1]);
   526                     ce = (lf / 2) + (rf / 2);
   527                     dst[0] = src[0];
   528                     dst[1] = src[1];
   529                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   530                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   531                     dst[4] = SDL_SwapLE32((Uint32) ce);
   532                     dst[5] = SDL_SwapLE32((Uint32) ce);
   533                 }
   534             }
   535         }
   536         break;
   537 
   538     case AUDIO_F32:
   539         {
   540             float lf, rf, ce;
   541             const float *src = (const float *) cvt->buf + cvt->len_cvt;
   542             float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
   543 
   544             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   545                 for (i = cvt->len_cvt / 8; i; --i) {
   546                     dst -= 6;
   547                     src -= 2;
   548                     lf = SDL_SwapFloatBE(src[0]);
   549                     rf = SDL_SwapFloatBE(src[1]);
   550                     ce = (lf * 0.5f) + (rf * 0.5f);
   551                     dst[0] = src[0];
   552                     dst[1] = src[1];
   553                     dst[2] = SDL_SwapFloatBE(lf - ce);
   554                     dst[3] = SDL_SwapFloatBE(rf - ce);
   555                     dst[4] = dst[5] = SDL_SwapFloatBE(ce);
   556                 }
   557             } else {
   558                 for (i = cvt->len_cvt / 8; i; --i) {
   559                     dst -= 6;
   560                     src -= 2;
   561                     lf = SDL_SwapFloatLE(src[0]);
   562                     rf = SDL_SwapFloatLE(src[1]);
   563                     ce = (lf * 0.5f) + (rf * 0.5f);
   564                     dst[0] = src[0];
   565                     dst[1] = src[1];
   566                     dst[2] = SDL_SwapFloatLE(lf - ce);
   567                     dst[3] = SDL_SwapFloatLE(rf - ce);
   568                     dst[4] = dst[5] = SDL_SwapFloatLE(ce);
   569                 }
   570             }
   571         }
   572         break;
   573 
   574     }
   575     cvt->len_cvt *= 3;
   576     if (cvt->filters[++cvt->filter_index]) {
   577         cvt->filters[cvt->filter_index] (cvt, format);
   578     }
   579 }
   580 
   581 
   582 /* Duplicate a stereo channel to a pseudo-4.0 stream */
   583 static void SDLCALL
   584 SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   585 {
   586     int i;
   587 
   588 #ifdef DEBUG_CONVERT
   589     fprintf(stderr, "Converting stereo to quad\n");
   590 #endif
   591 
   592     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   593     case AUDIO_U8:
   594         {
   595             Uint8 *src, *dst, lf, rf, ce;
   596 
   597             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   598             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
   599             for (i = cvt->len_cvt; i; --i) {
   600                 dst -= 4;
   601                 src -= 2;
   602                 lf = src[0];
   603                 rf = src[1];
   604                 ce = (lf / 2) + (rf / 2);
   605                 dst[0] = lf;
   606                 dst[1] = rf;
   607                 dst[2] = lf - ce;
   608                 dst[3] = rf - ce;
   609             }
   610         }
   611         break;
   612 
   613     case AUDIO_S8:
   614         {
   615             Sint8 *src, *dst, lf, rf, ce;
   616 
   617             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   618             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
   619             for (i = cvt->len_cvt; i; --i) {
   620                 dst -= 4;
   621                 src -= 2;
   622                 lf = src[0];
   623                 rf = src[1];
   624                 ce = (lf / 2) + (rf / 2);
   625                 dst[0] = lf;
   626                 dst[1] = rf;
   627                 dst[2] = lf - ce;
   628                 dst[3] = rf - ce;
   629             }
   630         }
   631         break;
   632 
   633     case AUDIO_U16:
   634         {
   635             Uint8 *src, *dst;
   636             Uint16 lf, rf, ce, lr, rr;
   637 
   638             src = cvt->buf + cvt->len_cvt;
   639             dst = cvt->buf + cvt->len_cvt * 2;
   640 
   641             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   642                 for (i = cvt->len_cvt / 4; i; --i) {
   643                     dst -= 8;
   644                     src -= 4;
   645                     lf = (Uint16) ((src[0] << 8) | src[1]);
   646                     rf = (Uint16) ((src[2] << 8) | src[3]);
   647                     ce = (lf / 2) + (rf / 2);
   648                     rr = lf - ce;
   649                     lr = rf - ce;
   650                     dst[1] = (lf & 0xFF);
   651                     dst[0] = ((lf >> 8) & 0xFF);
   652                     dst[3] = (rf & 0xFF);
   653                     dst[2] = ((rf >> 8) & 0xFF);
   654 
   655                     dst[1 + 4] = (lr & 0xFF);
   656                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   657                     dst[3 + 4] = (rr & 0xFF);
   658                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   659                 }
   660             } else {
   661                 for (i = cvt->len_cvt / 4; i; --i) {
   662                     dst -= 8;
   663                     src -= 4;
   664                     lf = (Uint16) ((src[1] << 8) | src[0]);
   665                     rf = (Uint16) ((src[3] << 8) | src[2]);
   666                     ce = (lf / 2) + (rf / 2);
   667                     rr = lf - ce;
   668                     lr = rf - ce;
   669                     dst[0] = (lf & 0xFF);
   670                     dst[1] = ((lf >> 8) & 0xFF);
   671                     dst[2] = (rf & 0xFF);
   672                     dst[3] = ((rf >> 8) & 0xFF);
   673 
   674                     dst[0 + 4] = (lr & 0xFF);
   675                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   676                     dst[2 + 4] = (rr & 0xFF);
   677                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   678                 }
   679             }
   680         }
   681         break;
   682 
   683     case AUDIO_S16:
   684         {
   685             Uint8 *src, *dst;
   686             Sint16 lf, rf, ce, lr, rr;
   687 
   688             src = cvt->buf + cvt->len_cvt;
   689             dst = cvt->buf + cvt->len_cvt * 2;
   690 
   691             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   692                 for (i = cvt->len_cvt / 4; i; --i) {
   693                     dst -= 8;
   694                     src -= 4;
   695                     lf = (Sint16) ((src[0] << 8) | src[1]);
   696                     rf = (Sint16) ((src[2] << 8) | src[3]);
   697                     ce = (lf / 2) + (rf / 2);
   698                     rr = lf - ce;
   699                     lr = rf - ce;
   700                     dst[1] = (lf & 0xFF);
   701                     dst[0] = ((lf >> 8) & 0xFF);
   702                     dst[3] = (rf & 0xFF);
   703                     dst[2] = ((rf >> 8) & 0xFF);
   704 
   705                     dst[1 + 4] = (lr & 0xFF);
   706                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   707                     dst[3 + 4] = (rr & 0xFF);
   708                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   709                 }
   710             } else {
   711                 for (i = cvt->len_cvt / 4; i; --i) {
   712                     dst -= 8;
   713                     src -= 4;
   714                     lf = (Sint16) ((src[1] << 8) | src[0]);
   715                     rf = (Sint16) ((src[3] << 8) | src[2]);
   716                     ce = (lf / 2) + (rf / 2);
   717                     rr = lf - ce;
   718                     lr = rf - ce;
   719                     dst[0] = (lf & 0xFF);
   720                     dst[1] = ((lf >> 8) & 0xFF);
   721                     dst[2] = (rf & 0xFF);
   722                     dst[3] = ((rf >> 8) & 0xFF);
   723 
   724                     dst[0 + 4] = (lr & 0xFF);
   725                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   726                     dst[2 + 4] = (rr & 0xFF);
   727                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   728                 }
   729             }
   730         }
   731         break;
   732 
   733     case AUDIO_S32:
   734         {
   735             const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
   736             Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
   737             Sint32 lf, rf, ce;
   738 
   739             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   740                 for (i = cvt->len_cvt / 8; i; --i) {
   741                     dst -= 4;
   742                     src -= 2;
   743                     lf = (Sint32) SDL_SwapBE32(src[0]);
   744                     rf = (Sint32) SDL_SwapBE32(src[1]);
   745                     ce = (lf / 2) + (rf / 2);
   746                     dst[0] = src[0];
   747                     dst[1] = src[1];
   748                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   749                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   750                 }
   751             } else {
   752                 for (i = cvt->len_cvt / 8; i; --i) {
   753                     dst -= 4;
   754                     src -= 2;
   755                     lf = (Sint32) SDL_SwapLE32(src[0]);
   756                     rf = (Sint32) SDL_SwapLE32(src[1]);
   757                     ce = (lf / 2) + (rf / 2);
   758                     dst[0] = src[0];
   759                     dst[1] = src[1];
   760                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   761                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   762                 }
   763             }
   764         }
   765         break;
   766     }
   767     cvt->len_cvt *= 2;
   768     if (cvt->filters[++cvt->filter_index]) {
   769         cvt->filters[cvt->filter_index] (cvt, format);
   770     }
   771 }
   772 
   773 
   774 int
   775 SDL_ConvertAudio(SDL_AudioCVT * cvt)
   776 {
   777     /* !!! FIXME: (cvt) should be const; stack-copy it here. */
   778     /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
   779 
   780     /* Make sure there's data to convert */
   781     if (cvt->buf == NULL) {
   782         SDL_SetError("No buffer allocated for conversion");
   783         return (-1);
   784     }
   785     /* Return okay if no conversion is necessary */
   786     cvt->len_cvt = cvt->len;
   787     if (cvt->filters[0] == NULL) {
   788         return (0);
   789     }
   790 
   791     /* Set up the conversion and go! */
   792     cvt->filter_index = 0;
   793     cvt->filters[0] (cvt, cvt->src_format);
   794     return (0);
   795 }
   796 
   797 
   798 static SDL_AudioFilter
   799 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
   800 {
   801     /*
   802      * Fill in any future conversions that are specialized to a
   803      *  processor, platform, compiler, or library here.
   804      */
   805 
   806     return NULL;                /* no specialized converter code available. */
   807 }
   808 
   809 
   810 /*
   811  * Find a converter between two data types. We try to select a hand-tuned
   812  *  asm/vectorized/optimized function first, and then fallback to an
   813  *  autogenerated function that is customized to convert between two
   814  *  specific data types.
   815  */
   816 static int
   817 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
   818                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
   819 {
   820     if (src_fmt != dst_fmt) {
   821         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
   822         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
   823         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
   824 
   825         /* No hand-tuned converter? Try the autogenerated ones. */
   826         if (filter == NULL) {
   827             int i;
   828             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
   829                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
   830                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
   831                     filter = filt->filter;
   832                     break;
   833                 }
   834             }
   835 
   836             if (filter == NULL) {
   837                 SDL_SetError("No conversion available for these formats");
   838                 return -1;
   839             }
   840         }
   841 
   842         /* Update (cvt) with filter details... */
   843         cvt->filters[cvt->filter_index++] = filter;
   844         if (src_bitsize < dst_bitsize) {
   845             const int mult = (dst_bitsize / src_bitsize);
   846             cvt->len_mult *= mult;
   847             cvt->len_ratio *= mult;
   848         } else if (src_bitsize > dst_bitsize) {
   849             cvt->len_ratio /= (src_bitsize / dst_bitsize);
   850         }
   851 
   852         return 1;               /* added a converter. */
   853     }
   854 
   855     return 0;                   /* no conversion necessary. */
   856 }
   857 
   858 
   859 static SDL_AudioFilter
   860 SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
   861                          int src_rate, int dst_rate)
   862 {
   863     /*
   864      * Fill in any future conversions that are specialized to a
   865      *  processor, platform, compiler, or library here.
   866      */
   867 
   868     return NULL;                /* no specialized converter code available. */
   869 }
   870 
   871 static int
   872 SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
   873 {
   874     int retval = 0;
   875 
   876     /* If we only built with the arbitrary resamplers, ignore multiples. */
   877 #if !LESS_RESAMPLERS
   878     int lo, hi;
   879     int div;
   880 
   881     SDL_assert(src_rate != 0);
   882     SDL_assert(dst_rate != 0);
   883     SDL_assert(src_rate != dst_rate);
   884 
   885     if (src_rate < dst_rate) {
   886         lo = src_rate;
   887         hi = dst_rate;
   888     } else {
   889         lo = dst_rate;
   890         hi = src_rate;
   891     }
   892 
   893     /* zero means "not a supported multiple" ... we only do 2x and 4x. */
   894     if ((hi % lo) != 0)
   895         return 0;               /* not a multiple. */
   896 
   897     div = hi / lo;
   898     retval = ((div == 2) || (div == 4)) ? div : 0;
   899 #endif
   900 
   901     return retval;
   902 }
   903 
   904 static int
   905 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
   906                           int src_rate, int dst_rate)
   907 {
   908     if (src_rate != dst_rate) {
   909         SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
   910                                                           src_rate, dst_rate);
   911 
   912         /* No hand-tuned converter? Try the autogenerated ones. */
   913         if (filter == NULL) {
   914             int i;
   915             const int upsample = (src_rate < dst_rate) ? 1 : 0;
   916             const int multiple =
   917                 SDL_FindFrequencyMultiple(src_rate, dst_rate);
   918 
   919             for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
   920                 const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i];
   921                 if ((filt->fmt == cvt->dst_format) &&
   922                     (filt->channels == dst_channels) &&
   923                     (filt->upsample == upsample) &&
   924                     (filt->multiple == multiple)) {
   925                     filter = filt->filter;
   926                     break;
   927                 }
   928             }
   929 
   930             if (filter == NULL) {
   931                 SDL_SetError("No conversion available for these rates");
   932                 return -1;
   933             }
   934         }
   935 
   936         /* Update (cvt) with filter details... */
   937         cvt->filters[cvt->filter_index++] = filter;
   938         if (src_rate < dst_rate) {
   939             const double mult = ((double) dst_rate) / ((double) src_rate);
   940             cvt->len_mult *= (int) SDL_ceil(mult);
   941             cvt->len_ratio *= mult;
   942         } else {
   943             cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
   944         }
   945 
   946         return 1;               /* added a converter. */
   947     }
   948 
   949     return 0;                   /* no conversion necessary. */
   950 }
   951 
   952 
   953 /* Creates a set of audio filters to convert from one format to another.
   954    Returns -1 if the format conversion is not supported, 0 if there's
   955    no conversion needed, or 1 if the audio filter is set up.
   956 */
   957 
   958 int
   959 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
   960                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
   961                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
   962 {
   963     /*
   964      * !!! FIXME: reorder filters based on which grow/shrink the buffer.
   965      * !!! FIXME: ideally, we should do everything that shrinks the buffer
   966      * !!! FIXME: first, so we don't have to process as many bytes in a given
   967      * !!! FIXME: filter and abuse the CPU cache less. This might not be as
   968      * !!! FIXME: good in practice as it sounds in theory, though.
   969      */
   970 
   971     /* Sanity check target pointer */
   972     if (cvt == NULL) {
   973         return SDL_InvalidParamError("cvt");
   974     }
   975     
   976     /* there are no unsigned types over 16 bits, so catch this up front. */
   977     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
   978         return SDL_SetError("Invalid source format");
   979     }
   980     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
   981         return SDL_SetError("Invalid destination format");
   982     }
   983 
   984     /* prevent possible divisions by zero, etc. */
   985     if ((src_channels == 0) || (dst_channels == 0)) {
   986         return SDL_SetError("Source or destination channels is zero");
   987     }
   988     if ((src_rate == 0) || (dst_rate == 0)) {
   989         return SDL_SetError("Source or destination rate is zero");
   990     }
   991 #ifdef DEBUG_CONVERT
   992     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
   993            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
   994 #endif
   995 
   996     /* Start off with no conversion necessary */
   997     SDL_zerop(cvt);
   998     cvt->src_format = src_fmt;
   999     cvt->dst_format = dst_fmt;
  1000     cvt->needed = 0;
  1001     cvt->filter_index = 0;
  1002     cvt->filters[0] = NULL;
  1003     cvt->len_mult = 1;
  1004     cvt->len_ratio = 1.0;
  1005     cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
  1006 
  1007     /* Convert data types, if necessary. Updates (cvt). */
  1008     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) {
  1009         return -1;              /* shouldn't happen, but just in case... */
  1010     }
  1011 
  1012     /* Channel conversion */
  1013     if (src_channels != dst_channels) {
  1014         if ((src_channels == 1) && (dst_channels > 1)) {
  1015             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1016             cvt->len_mult *= 2;
  1017             src_channels = 2;
  1018             cvt->len_ratio *= 2;
  1019         }
  1020         if ((src_channels == 2) && (dst_channels == 6)) {
  1021             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1022             src_channels = 6;
  1023             cvt->len_mult *= 3;
  1024             cvt->len_ratio *= 3;
  1025         }
  1026         if ((src_channels == 2) && (dst_channels == 4)) {
  1027             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1028             src_channels = 4;
  1029             cvt->len_mult *= 2;
  1030             cvt->len_ratio *= 2;
  1031         }
  1032         while ((src_channels * 2) <= dst_channels) {
  1033             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1034             cvt->len_mult *= 2;
  1035             src_channels *= 2;
  1036             cvt->len_ratio *= 2;
  1037         }
  1038         if ((src_channels == 6) && (dst_channels <= 2)) {
  1039             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1040             src_channels = 2;
  1041             cvt->len_ratio /= 3;
  1042         }
  1043         if ((src_channels == 6) && (dst_channels == 4)) {
  1044             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1045             src_channels = 4;
  1046             cvt->len_ratio /= 2;
  1047         }
  1048         /* This assumes that 4 channel audio is in the format:
  1049            Left {front/back} + Right {front/back}
  1050            so converting to L/R stereo works properly.
  1051          */
  1052         while (((src_channels % 2) == 0) &&
  1053                ((src_channels / 2) >= dst_channels)) {
  1054             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1055             src_channels /= 2;
  1056             cvt->len_ratio /= 2;
  1057         }
  1058         if (src_channels != dst_channels) {
  1059             /* Uh oh.. */ ;
  1060         }
  1061     }
  1062 
  1063     /* Do rate conversion, if necessary. Updates (cvt). */
  1064     if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) ==
  1065         -1) {
  1066         return -1;              /* shouldn't happen, but just in case... */
  1067     }
  1068 
  1069     /* Set up the filter information */
  1070     if (cvt->filter_index != 0) {
  1071         cvt->needed = 1;
  1072         cvt->src_format = src_fmt;
  1073         cvt->dst_format = dst_fmt;
  1074         cvt->len = 0;
  1075         cvt->buf = NULL;
  1076         cvt->filters[cvt->filter_index] = NULL;
  1077     }
  1078     return (cvt->needed);
  1079 }
  1080 
  1081 
  1082 /* vi: set ts=4 sw=4 expandtab: */