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