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