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