src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 18:17:28 -0700
changeset 7523 9e9ab1dc3811
parent 7410 a9878830f05e
child 8093 b43765095a6f
permissions -rw-r--r--
Fixed bug 1919 - Window icon disappears as soon as a renderer is created

Sebastian

Setting a window icon works just fine until a renderer is added to the window.
After adding the renderer the icon disappears.

Reproduce by:
- Take the example code from the wiki: http://wiki.libsdl.org/moin.fcg/SDL_SetWindowIcon

- Add the following two lines after SDL_FreeSurface(surface);
SDL_Delay(1000);
SDL_Renderer* ren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

-compile and run

You will see the window icon correctly at first. After the Delay the Icon will disappear.
     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             src -= 1; \
   297             dst -= 2; \
   298             dst[0] = dst[1] = *src; \
   299         } \
   300     }
   301 
   302     /* this function only cares about typesize, and data as a block of bits. */
   303     switch (SDL_AUDIO_BITSIZE(format)) {
   304     case 8:
   305         dup_chans_1_to_2(Uint8);
   306         break;
   307     case 16:
   308         dup_chans_1_to_2(Uint16);
   309         break;
   310     case 32:
   311         dup_chans_1_to_2(Uint32);
   312         break;
   313     }
   314 
   315 #undef dup_chans_1_to_2
   316 
   317     cvt->len_cvt *= 2;
   318     if (cvt->filters[++cvt->filter_index]) {
   319         cvt->filters[cvt->filter_index] (cvt, format);
   320     }
   321 }
   322 
   323 
   324 /* Duplicate a stereo channel to a pseudo-5.1 stream */
   325 static void SDLCALL
   326 SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   327 {
   328     int i;
   329 
   330 #ifdef DEBUG_CONVERT
   331     fprintf(stderr, "Converting stereo to surround\n");
   332 #endif
   333 
   334     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   335     case AUDIO_U8:
   336         {
   337             Uint8 *src, *dst, lf, rf, ce;
   338 
   339             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   340             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
   341             for (i = cvt->len_cvt; i; --i) {
   342                 dst -= 6;
   343                 src -= 2;
   344                 lf = src[0];
   345                 rf = src[1];
   346                 ce = (lf / 2) + (rf / 2);
   347                 dst[0] = lf;
   348                 dst[1] = rf;
   349                 dst[2] = lf - ce;
   350                 dst[3] = rf - ce;
   351                 dst[4] = ce;
   352                 dst[5] = ce;
   353             }
   354         }
   355         break;
   356 
   357     case AUDIO_S8:
   358         {
   359             Sint8 *src, *dst, lf, rf, ce;
   360 
   361             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   362             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
   363             for (i = cvt->len_cvt; i; --i) {
   364                 dst -= 6;
   365                 src -= 2;
   366                 lf = src[0];
   367                 rf = src[1];
   368                 ce = (lf / 2) + (rf / 2);
   369                 dst[0] = lf;
   370                 dst[1] = rf;
   371                 dst[2] = lf - ce;
   372                 dst[3] = rf - ce;
   373                 dst[4] = ce;
   374                 dst[5] = ce;
   375             }
   376         }
   377         break;
   378 
   379     case AUDIO_U16:
   380         {
   381             Uint8 *src, *dst;
   382             Uint16 lf, rf, ce, lr, rr;
   383 
   384             src = cvt->buf + cvt->len_cvt;
   385             dst = cvt->buf + cvt->len_cvt * 3;
   386 
   387             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   388                 for (i = cvt->len_cvt / 4; i; --i) {
   389                     dst -= 12;
   390                     src -= 4;
   391                     lf = (Uint16) ((src[0] << 8) | src[1]);
   392                     rf = (Uint16) ((src[2] << 8) | src[3]);
   393                     ce = (lf / 2) + (rf / 2);
   394                     rr = lf - ce;
   395                     lr = rf - ce;
   396                     dst[1] = (lf & 0xFF);
   397                     dst[0] = ((lf >> 8) & 0xFF);
   398                     dst[3] = (rf & 0xFF);
   399                     dst[2] = ((rf >> 8) & 0xFF);
   400 
   401                     dst[1 + 4] = (lr & 0xFF);
   402                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   403                     dst[3 + 4] = (rr & 0xFF);
   404                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   405 
   406                     dst[1 + 8] = (ce & 0xFF);
   407                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   408                     dst[3 + 8] = (ce & 0xFF);
   409                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   410                 }
   411             } else {
   412                 for (i = cvt->len_cvt / 4; i; --i) {
   413                     dst -= 12;
   414                     src -= 4;
   415                     lf = (Uint16) ((src[1] << 8) | src[0]);
   416                     rf = (Uint16) ((src[3] << 8) | src[2]);
   417                     ce = (lf / 2) + (rf / 2);
   418                     rr = lf - ce;
   419                     lr = rf - ce;
   420                     dst[0] = (lf & 0xFF);
   421                     dst[1] = ((lf >> 8) & 0xFF);
   422                     dst[2] = (rf & 0xFF);
   423                     dst[3] = ((rf >> 8) & 0xFF);
   424 
   425                     dst[0 + 4] = (lr & 0xFF);
   426                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   427                     dst[2 + 4] = (rr & 0xFF);
   428                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   429 
   430                     dst[0 + 8] = (ce & 0xFF);
   431                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   432                     dst[2 + 8] = (ce & 0xFF);
   433                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   434                 }
   435             }
   436         }
   437         break;
   438 
   439     case AUDIO_S16:
   440         {
   441             Uint8 *src, *dst;
   442             Sint16 lf, rf, ce, lr, rr;
   443 
   444             src = cvt->buf + cvt->len_cvt;
   445             dst = cvt->buf + cvt->len_cvt * 3;
   446 
   447             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   448                 for (i = cvt->len_cvt / 4; i; --i) {
   449                     dst -= 12;
   450                     src -= 4;
   451                     lf = (Sint16) ((src[0] << 8) | src[1]);
   452                     rf = (Sint16) ((src[2] << 8) | src[3]);
   453                     ce = (lf / 2) + (rf / 2);
   454                     rr = lf - ce;
   455                     lr = rf - ce;
   456                     dst[1] = (lf & 0xFF);
   457                     dst[0] = ((lf >> 8) & 0xFF);
   458                     dst[3] = (rf & 0xFF);
   459                     dst[2] = ((rf >> 8) & 0xFF);
   460 
   461                     dst[1 + 4] = (lr & 0xFF);
   462                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   463                     dst[3 + 4] = (rr & 0xFF);
   464                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   465 
   466                     dst[1 + 8] = (ce & 0xFF);
   467                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   468                     dst[3 + 8] = (ce & 0xFF);
   469                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   470                 }
   471             } else {
   472                 for (i = cvt->len_cvt / 4; i; --i) {
   473                     dst -= 12;
   474                     src -= 4;
   475                     lf = (Sint16) ((src[1] << 8) | src[0]);
   476                     rf = (Sint16) ((src[3] << 8) | src[2]);
   477                     ce = (lf / 2) + (rf / 2);
   478                     rr = lf - ce;
   479                     lr = rf - ce;
   480                     dst[0] = (lf & 0xFF);
   481                     dst[1] = ((lf >> 8) & 0xFF);
   482                     dst[2] = (rf & 0xFF);
   483                     dst[3] = ((rf >> 8) & 0xFF);
   484 
   485                     dst[0 + 4] = (lr & 0xFF);
   486                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   487                     dst[2 + 4] = (rr & 0xFF);
   488                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   489 
   490                     dst[0 + 8] = (ce & 0xFF);
   491                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   492                     dst[2 + 8] = (ce & 0xFF);
   493                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   494                 }
   495             }
   496         }
   497         break;
   498 
   499     case AUDIO_S32:
   500         {
   501             Sint32 lf, rf, ce;
   502             const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
   503             Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
   504 
   505             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   506                 for (i = cvt->len_cvt / 8; i; --i) {
   507                     dst -= 6;
   508                     src -= 2;
   509                     lf = (Sint32) SDL_SwapBE32(src[0]);
   510                     rf = (Sint32) SDL_SwapBE32(src[1]);
   511                     ce = (lf / 2) + (rf / 2);
   512                     dst[0] = SDL_SwapBE32((Uint32) lf);
   513                     dst[1] = SDL_SwapBE32((Uint32) rf);
   514                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   515                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   516                     dst[4] = SDL_SwapBE32((Uint32) ce);
   517                     dst[5] = SDL_SwapBE32((Uint32) ce);
   518                 }
   519             } else {
   520                 for (i = cvt->len_cvt / 8; i; --i) {
   521                     dst -= 6;
   522                     src -= 2;
   523                     lf = (Sint32) SDL_SwapLE32(src[0]);
   524                     rf = (Sint32) SDL_SwapLE32(src[1]);
   525                     ce = (lf / 2) + (rf / 2);
   526                     dst[0] = src[0];
   527                     dst[1] = src[1];
   528                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   529                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   530                     dst[4] = SDL_SwapLE32((Uint32) ce);
   531                     dst[5] = SDL_SwapLE32((Uint32) ce);
   532                 }
   533             }
   534         }
   535         break;
   536 
   537     case AUDIO_F32:
   538         {
   539             float lf, rf, ce;
   540             const float *src = (const float *) cvt->buf + cvt->len_cvt;
   541             float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
   542 
   543             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   544                 for (i = cvt->len_cvt / 8; i; --i) {
   545                     dst -= 6;
   546                     src -= 2;
   547                     lf = SDL_SwapFloatBE(src[0]);
   548                     rf = SDL_SwapFloatBE(src[1]);
   549                     ce = (lf * 0.5f) + (rf * 0.5f);
   550                     dst[0] = src[0];
   551                     dst[1] = src[1];
   552                     dst[2] = SDL_SwapFloatBE(lf - ce);
   553                     dst[3] = SDL_SwapFloatBE(rf - ce);
   554                     dst[4] = dst[5] = SDL_SwapFloatBE(ce);
   555                 }
   556             } else {
   557                 for (i = cvt->len_cvt / 8; i; --i) {
   558                     dst -= 6;
   559                     src -= 2;
   560                     lf = SDL_SwapFloatLE(src[0]);
   561                     rf = SDL_SwapFloatLE(src[1]);
   562                     ce = (lf * 0.5f) + (rf * 0.5f);
   563                     dst[0] = src[0];
   564                     dst[1] = src[1];
   565                     dst[2] = SDL_SwapFloatLE(lf - ce);
   566                     dst[3] = SDL_SwapFloatLE(rf - ce);
   567                     dst[4] = dst[5] = SDL_SwapFloatLE(ce);
   568                 }
   569             }
   570         }
   571         break;
   572 
   573     }
   574     cvt->len_cvt *= 3;
   575     if (cvt->filters[++cvt->filter_index]) {
   576         cvt->filters[cvt->filter_index] (cvt, format);
   577     }
   578 }
   579 
   580 
   581 /* Duplicate a stereo channel to a pseudo-4.0 stream */
   582 static void SDLCALL
   583 SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   584 {
   585     int i;
   586 
   587 #ifdef DEBUG_CONVERT
   588     fprintf(stderr, "Converting stereo to quad\n");
   589 #endif
   590 
   591     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   592     case AUDIO_U8:
   593         {
   594             Uint8 *src, *dst, lf, rf, ce;
   595 
   596             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   597             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
   598             for (i = cvt->len_cvt; i; --i) {
   599                 dst -= 4;
   600                 src -= 2;
   601                 lf = src[0];
   602                 rf = src[1];
   603                 ce = (lf / 2) + (rf / 2);
   604                 dst[0] = lf;
   605                 dst[1] = rf;
   606                 dst[2] = lf - ce;
   607                 dst[3] = rf - ce;
   608             }
   609         }
   610         break;
   611 
   612     case AUDIO_S8:
   613         {
   614             Sint8 *src, *dst, lf, rf, ce;
   615 
   616             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   617             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
   618             for (i = cvt->len_cvt; i; --i) {
   619                 dst -= 4;
   620                 src -= 2;
   621                 lf = src[0];
   622                 rf = src[1];
   623                 ce = (lf / 2) + (rf / 2);
   624                 dst[0] = lf;
   625                 dst[1] = rf;
   626                 dst[2] = lf - ce;
   627                 dst[3] = rf - ce;
   628             }
   629         }
   630         break;
   631 
   632     case AUDIO_U16:
   633         {
   634             Uint8 *src, *dst;
   635             Uint16 lf, rf, ce, lr, rr;
   636 
   637             src = cvt->buf + cvt->len_cvt;
   638             dst = cvt->buf + cvt->len_cvt * 2;
   639 
   640             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   641                 for (i = cvt->len_cvt / 4; i; --i) {
   642                     dst -= 8;
   643                     src -= 4;
   644                     lf = (Uint16) ((src[0] << 8) | src[1]);
   645                     rf = (Uint16) ((src[2] << 8) | src[3]);
   646                     ce = (lf / 2) + (rf / 2);
   647                     rr = lf - ce;
   648                     lr = rf - ce;
   649                     dst[1] = (lf & 0xFF);
   650                     dst[0] = ((lf >> 8) & 0xFF);
   651                     dst[3] = (rf & 0xFF);
   652                     dst[2] = ((rf >> 8) & 0xFF);
   653 
   654                     dst[1 + 4] = (lr & 0xFF);
   655                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   656                     dst[3 + 4] = (rr & 0xFF);
   657                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   658                 }
   659             } else {
   660                 for (i = cvt->len_cvt / 4; i; --i) {
   661                     dst -= 8;
   662                     src -= 4;
   663                     lf = (Uint16) ((src[1] << 8) | src[0]);
   664                     rf = (Uint16) ((src[3] << 8) | src[2]);
   665                     ce = (lf / 2) + (rf / 2);
   666                     rr = lf - ce;
   667                     lr = rf - ce;
   668                     dst[0] = (lf & 0xFF);
   669                     dst[1] = ((lf >> 8) & 0xFF);
   670                     dst[2] = (rf & 0xFF);
   671                     dst[3] = ((rf >> 8) & 0xFF);
   672 
   673                     dst[0 + 4] = (lr & 0xFF);
   674                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   675                     dst[2 + 4] = (rr & 0xFF);
   676                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   677                 }
   678             }
   679         }
   680         break;
   681 
   682     case AUDIO_S16:
   683         {
   684             Uint8 *src, *dst;
   685             Sint16 lf, rf, ce, lr, rr;
   686 
   687             src = cvt->buf + cvt->len_cvt;
   688             dst = cvt->buf + cvt->len_cvt * 2;
   689 
   690             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   691                 for (i = cvt->len_cvt / 4; i; --i) {
   692                     dst -= 8;
   693                     src -= 4;
   694                     lf = (Sint16) ((src[0] << 8) | src[1]);
   695                     rf = (Sint16) ((src[2] << 8) | src[3]);
   696                     ce = (lf / 2) + (rf / 2);
   697                     rr = lf - ce;
   698                     lr = rf - ce;
   699                     dst[1] = (lf & 0xFF);
   700                     dst[0] = ((lf >> 8) & 0xFF);
   701                     dst[3] = (rf & 0xFF);
   702                     dst[2] = ((rf >> 8) & 0xFF);
   703 
   704                     dst[1 + 4] = (lr & 0xFF);
   705                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   706                     dst[3 + 4] = (rr & 0xFF);
   707                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   708                 }
   709             } else {
   710                 for (i = cvt->len_cvt / 4; i; --i) {
   711                     dst -= 8;
   712                     src -= 4;
   713                     lf = (Sint16) ((src[1] << 8) | src[0]);
   714                     rf = (Sint16) ((src[3] << 8) | src[2]);
   715                     ce = (lf / 2) + (rf / 2);
   716                     rr = lf - ce;
   717                     lr = rf - ce;
   718                     dst[0] = (lf & 0xFF);
   719                     dst[1] = ((lf >> 8) & 0xFF);
   720                     dst[2] = (rf & 0xFF);
   721                     dst[3] = ((rf >> 8) & 0xFF);
   722 
   723                     dst[0 + 4] = (lr & 0xFF);
   724                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   725                     dst[2 + 4] = (rr & 0xFF);
   726                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   727                 }
   728             }
   729         }
   730         break;
   731 
   732     case AUDIO_S32:
   733         {
   734             const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
   735             Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
   736             Sint32 lf, rf, ce;
   737 
   738             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   739                 for (i = cvt->len_cvt / 8; i; --i) {
   740                     dst -= 4;
   741                     src -= 2;
   742                     lf = (Sint32) SDL_SwapBE32(src[0]);
   743                     rf = (Sint32) SDL_SwapBE32(src[1]);
   744                     ce = (lf / 2) + (rf / 2);
   745                     dst[0] = src[0];
   746                     dst[1] = src[1];
   747                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   748                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   749                 }
   750             } else {
   751                 for (i = cvt->len_cvt / 8; i; --i) {
   752                     dst -= 4;
   753                     src -= 2;
   754                     lf = (Sint32) SDL_SwapLE32(src[0]);
   755                     rf = (Sint32) SDL_SwapLE32(src[1]);
   756                     ce = (lf / 2) + (rf / 2);
   757                     dst[0] = src[0];
   758                     dst[1] = src[1];
   759                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   760                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   761                 }
   762             }
   763         }
   764         break;
   765     }
   766     cvt->len_cvt *= 2;
   767     if (cvt->filters[++cvt->filter_index]) {
   768         cvt->filters[cvt->filter_index] (cvt, format);
   769     }
   770 }
   771 
   772 
   773 int
   774 SDL_ConvertAudio(SDL_AudioCVT * cvt)
   775 {
   776     /* !!! FIXME: (cvt) should be const; stack-copy it here. */
   777     /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
   778 
   779     /* Make sure there's data to convert */
   780     if (cvt->buf == NULL) {
   781         SDL_SetError("No buffer allocated for conversion");
   782         return (-1);
   783     }
   784     /* Return okay if no conversion is necessary */
   785     cvt->len_cvt = cvt->len;
   786     if (cvt->filters[0] == NULL) {
   787         return (0);
   788     }
   789 
   790     /* Set up the conversion and go! */
   791     cvt->filter_index = 0;
   792     cvt->filters[0] (cvt, cvt->src_format);
   793     return (0);
   794 }
   795 
   796 
   797 static SDL_AudioFilter
   798 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
   799 {
   800     /*
   801      * Fill in any future conversions that are specialized to a
   802      *  processor, platform, compiler, or library here.
   803      */
   804 
   805     return NULL;                /* no specialized converter code available. */
   806 }
   807 
   808 
   809 /*
   810  * Find a converter between two data types. We try to select a hand-tuned
   811  *  asm/vectorized/optimized function first, and then fallback to an
   812  *  autogenerated function that is customized to convert between two
   813  *  specific data types.
   814  */
   815 static int
   816 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
   817                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
   818 {
   819     if (src_fmt != dst_fmt) {
   820         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
   821         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
   822         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
   823 
   824         /* No hand-tuned converter? Try the autogenerated ones. */
   825         if (filter == NULL) {
   826             int i;
   827             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
   828                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
   829                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
   830                     filter = filt->filter;
   831                     break;
   832                 }
   833             }
   834 
   835             if (filter == NULL) {
   836                 SDL_SetError("No conversion available for these formats");
   837                 return -1;
   838             }
   839         }
   840 
   841         /* Update (cvt) with filter details... */
   842         cvt->filters[cvt->filter_index++] = filter;
   843         if (src_bitsize < dst_bitsize) {
   844             const int mult = (dst_bitsize / src_bitsize);
   845             cvt->len_mult *= mult;
   846             cvt->len_ratio *= mult;
   847         } else if (src_bitsize > dst_bitsize) {
   848             cvt->len_ratio /= (src_bitsize / dst_bitsize);
   849         }
   850 
   851         return 1;               /* added a converter. */
   852     }
   853 
   854     return 0;                   /* no conversion necessary. */
   855 }
   856 
   857 
   858 static SDL_AudioFilter
   859 SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
   860                          int src_rate, int dst_rate)
   861 {
   862     /*
   863      * Fill in any future conversions that are specialized to a
   864      *  processor, platform, compiler, or library here.
   865      */
   866 
   867     return NULL;                /* no specialized converter code available. */
   868 }
   869 
   870 static int
   871 SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
   872 {
   873     int retval = 0;
   874 
   875     /* If we only built with the arbitrary resamplers, ignore multiples. */
   876 #if !LESS_RESAMPLERS
   877     int lo, hi;
   878     int div;
   879 
   880     SDL_assert(src_rate != 0);
   881     SDL_assert(dst_rate != 0);
   882     SDL_assert(src_rate != dst_rate);
   883 
   884     if (src_rate < dst_rate) {
   885         lo = src_rate;
   886         hi = dst_rate;
   887     } else {
   888         lo = dst_rate;
   889         hi = src_rate;
   890     }
   891 
   892     /* zero means "not a supported multiple" ... we only do 2x and 4x. */
   893     if ((hi % lo) != 0)
   894         return 0;               /* not a multiple. */
   895 
   896     div = hi / lo;
   897     retval = ((div == 2) || (div == 4)) ? div : 0;
   898 #endif
   899 
   900     return retval;
   901 }
   902 
   903 static int
   904 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
   905                           int src_rate, int dst_rate)
   906 {
   907     if (src_rate != dst_rate) {
   908         SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
   909                                                           src_rate, dst_rate);
   910 
   911         /* No hand-tuned converter? Try the autogenerated ones. */
   912         if (filter == NULL) {
   913             int i;
   914             const int upsample = (src_rate < dst_rate) ? 1 : 0;
   915             const int multiple =
   916                 SDL_FindFrequencyMultiple(src_rate, dst_rate);
   917 
   918             for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
   919                 const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i];
   920                 if ((filt->fmt == cvt->dst_format) &&
   921                     (filt->channels == dst_channels) &&
   922                     (filt->upsample == upsample) &&
   923                     (filt->multiple == multiple)) {
   924                     filter = filt->filter;
   925                     break;
   926                 }
   927             }
   928 
   929             if (filter == NULL) {
   930                 SDL_SetError("No conversion available for these rates");
   931                 return -1;
   932             }
   933         }
   934 
   935         /* Update (cvt) with filter details... */
   936         cvt->filters[cvt->filter_index++] = filter;
   937         if (src_rate < dst_rate) {
   938             const double mult = ((double) dst_rate) / ((double) src_rate);
   939             cvt->len_mult *= (int) SDL_ceil(mult);
   940             cvt->len_ratio *= mult;
   941         } else {
   942             cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
   943         }
   944 
   945         return 1;               /* added a converter. */
   946     }
   947 
   948     return 0;                   /* no conversion necessary. */
   949 }
   950 
   951 
   952 /* Creates a set of audio filters to convert from one format to another.
   953    Returns -1 if the format conversion is not supported, 0 if there's
   954    no conversion needed, or 1 if the audio filter is set up.
   955 */
   956 
   957 int
   958 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
   959                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
   960                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
   961 {
   962     /*
   963      * !!! FIXME: reorder filters based on which grow/shrink the buffer.
   964      * !!! FIXME: ideally, we should do everything that shrinks the buffer
   965      * !!! FIXME: first, so we don't have to process as many bytes in a given
   966      * !!! FIXME: filter and abuse the CPU cache less. This might not be as
   967      * !!! FIXME: good in practice as it sounds in theory, though.
   968      */
   969 
   970     /* Sanity check target pointer */
   971     if (cvt == NULL) {
   972         return SDL_InvalidParamError("cvt");
   973     }
   974 
   975     /* there are no unsigned types over 16 bits, so catch this up front. */
   976     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
   977         return SDL_SetError("Invalid source format");
   978     }
   979     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
   980         return SDL_SetError("Invalid destination format");
   981     }
   982 
   983     /* prevent possible divisions by zero, etc. */
   984     if ((src_channels == 0) || (dst_channels == 0)) {
   985         return SDL_SetError("Source or destination channels is zero");
   986     }
   987     if ((src_rate == 0) || (dst_rate == 0)) {
   988         return SDL_SetError("Source or destination rate is zero");
   989     }
   990 #ifdef DEBUG_CONVERT
   991     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
   992            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
   993 #endif
   994 
   995     /* Start off with no conversion necessary */
   996     SDL_zerop(cvt);
   997     cvt->src_format = src_fmt;
   998     cvt->dst_format = dst_fmt;
   999     cvt->needed = 0;
  1000     cvt->filter_index = 0;
  1001     cvt->filters[0] = NULL;
  1002     cvt->len_mult = 1;
  1003     cvt->len_ratio = 1.0;
  1004     cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
  1005 
  1006     /* Convert data types, if necessary. Updates (cvt). */
  1007     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) {
  1008         return -1;              /* shouldn't happen, but just in case... */
  1009     }
  1010 
  1011     /* Channel conversion */
  1012     if (src_channels != dst_channels) {
  1013         if ((src_channels == 1) && (dst_channels > 1)) {
  1014             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1015             cvt->len_mult *= 2;
  1016             src_channels = 2;
  1017             cvt->len_ratio *= 2;
  1018         }
  1019         if ((src_channels == 2) && (dst_channels == 6)) {
  1020             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1021             src_channels = 6;
  1022             cvt->len_mult *= 3;
  1023             cvt->len_ratio *= 3;
  1024         }
  1025         if ((src_channels == 2) && (dst_channels == 4)) {
  1026             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1027             src_channels = 4;
  1028             cvt->len_mult *= 2;
  1029             cvt->len_ratio *= 2;
  1030         }
  1031         while ((src_channels * 2) <= dst_channels) {
  1032             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1033             cvt->len_mult *= 2;
  1034             src_channels *= 2;
  1035             cvt->len_ratio *= 2;
  1036         }
  1037         if ((src_channels == 6) && (dst_channels <= 2)) {
  1038             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1039             src_channels = 2;
  1040             cvt->len_ratio /= 3;
  1041         }
  1042         if ((src_channels == 6) && (dst_channels == 4)) {
  1043             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1044             src_channels = 4;
  1045             cvt->len_ratio /= 2;
  1046         }
  1047         /* This assumes that 4 channel audio is in the format:
  1048            Left {front/back} + Right {front/back}
  1049            so converting to L/R stereo works properly.
  1050          */
  1051         while (((src_channels % 2) == 0) &&
  1052                ((src_channels / 2) >= dst_channels)) {
  1053             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1054             src_channels /= 2;
  1055             cvt->len_ratio /= 2;
  1056         }
  1057         if (src_channels != dst_channels) {
  1058             /* Uh oh.. */ ;
  1059         }
  1060     }
  1061 
  1062     /* Do rate conversion, if necessary. Updates (cvt). */
  1063     if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) ==
  1064         -1) {
  1065         return -1;              /* shouldn't happen, but just in case... */
  1066     }
  1067 
  1068     /* Set up the filter information */
  1069     if (cvt->filter_index != 0) {
  1070         cvt->needed = 1;
  1071         cvt->src_format = src_fmt;
  1072         cvt->dst_format = dst_fmt;
  1073         cvt->len = 0;
  1074         cvt->buf = NULL;
  1075         cvt->filters[cvt->filter_index] = NULL;
  1076     }
  1077     return (cvt->needed);
  1078 }
  1079 
  1080 
  1081 /* vi: set ts=4 sw=4 expandtab: */