src/audio/SDL_audiocvt.c
author Aaron Wishnick <schnarf@gmail.com>
Wed, 18 Jun 2008 04:51:10 +0000
branchgsoc2008_audio_resampling
changeset 2655 b8e736c8a5a8
parent 2130 3ee59c43d784
child 2656 dd74182b3c3c
permissions -rw-r--r--
Added beginnings of resampling code.
     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 #include <math.h>
    24 
    25 /* Functions for audio drivers to perform runtime conversion of audio format */
    26 
    27 #include "SDL_audio.h"
    28 #include "SDL_audio_c.h"
    29 
    30 /* Effectively mix right and left channels into a single channel */
    31 static void SDLCALL
    32 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    33 {
    34     int i;
    35     Sint32 sample;
    36 
    37 #ifdef DEBUG_CONVERT
    38     fprintf(stderr, "Converting to mono\n");
    39 #endif
    40     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
    41     case AUDIO_U8:
    42         {
    43             Uint8 *src, *dst;
    44 
    45             src = cvt->buf;
    46             dst = cvt->buf;
    47             for (i = cvt->len_cvt / 2; i; --i) {
    48                 sample = src[0] + src[1];
    49                 *dst = (Uint8) (sample / 2);
    50                 src += 2;
    51                 dst += 1;
    52             }
    53         }
    54         break;
    55 
    56     case AUDIO_S8:
    57         {
    58             Sint8 *src, *dst;
    59 
    60             src = (Sint8 *) cvt->buf;
    61             dst = (Sint8 *) cvt->buf;
    62             for (i = cvt->len_cvt / 2; i; --i) {
    63                 sample = src[0] + src[1];
    64                 *dst = (Sint8) (sample / 2);
    65                 src += 2;
    66                 dst += 1;
    67             }
    68         }
    69         break;
    70 
    71     case AUDIO_U16:
    72         {
    73             Uint8 *src, *dst;
    74 
    75             src = cvt->buf;
    76             dst = cvt->buf;
    77             if (SDL_AUDIO_ISBIGENDIAN(format)) {
    78                 for (i = cvt->len_cvt / 4; i; --i) {
    79                     sample = (Uint16) ((src[0] << 8) | src[1]) +
    80                         (Uint16) ((src[2] << 8) | src[3]);
    81                     sample /= 2;
    82                     dst[1] = (sample & 0xFF);
    83                     sample >>= 8;
    84                     dst[0] = (sample & 0xFF);
    85                     src += 4;
    86                     dst += 2;
    87                 }
    88             } else {
    89                 for (i = cvt->len_cvt / 4; i; --i) {
    90                     sample = (Uint16) ((src[1] << 8) | src[0]) +
    91                         (Uint16) ((src[3] << 8) | src[2]);
    92                     sample /= 2;
    93                     dst[0] = (sample & 0xFF);
    94                     sample >>= 8;
    95                     dst[1] = (sample & 0xFF);
    96                     src += 4;
    97                     dst += 2;
    98                 }
    99             }
   100         }
   101         break;
   102 
   103     case AUDIO_S16:
   104         {
   105             Uint8 *src, *dst;
   106 
   107             src = cvt->buf;
   108             dst = cvt->buf;
   109             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   110                 for (i = cvt->len_cvt / 4; i; --i) {
   111                     sample = (Sint16) ((src[0] << 8) | src[1]) +
   112                         (Sint16) ((src[2] << 8) | src[3]);
   113                     sample /= 2;
   114                     dst[1] = (sample & 0xFF);
   115                     sample >>= 8;
   116                     dst[0] = (sample & 0xFF);
   117                     src += 4;
   118                     dst += 2;
   119                 }
   120             } else {
   121                 for (i = cvt->len_cvt / 4; i; --i) {
   122                     sample = (Sint16) ((src[1] << 8) | src[0]) +
   123                         (Sint16) ((src[3] << 8) | src[2]);
   124                     sample /= 2;
   125                     dst[0] = (sample & 0xFF);
   126                     sample >>= 8;
   127                     dst[1] = (sample & 0xFF);
   128                     src += 4;
   129                     dst += 2;
   130                 }
   131             }
   132         }
   133         break;
   134 
   135     case AUDIO_S32:
   136         {
   137             const Uint32 *src = (const Uint32 *) cvt->buf;
   138             Uint32 *dst = (Uint32 *) cvt->buf;
   139             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   140                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   141                     const Sint64 added =
   142                         (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
   143                          ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
   144                     *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
   145                 }
   146             } else {
   147                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   148                     const Sint64 added =
   149                         (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
   150                          ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
   151                     *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
   152                 }
   153             }
   154         }
   155         break;
   156 
   157     case AUDIO_F32:
   158         {
   159             const float *src = (const float *) cvt->buf;
   160             float *dst = (float *) cvt->buf;
   161             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   162                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   163                     const float src1 = SDL_SwapFloatBE(src[0]);
   164                     const float src2 = SDL_SwapFloatBE(src[1]);
   165                     const double added = ((double) src1) + ((double) src2);
   166                     const float halved = (float) (added * 0.5);
   167                     *(dst++) = SDL_SwapFloatBE(halved);
   168                 }
   169             } else {
   170                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   171                     const float src1 = SDL_SwapFloatLE(src[0]);
   172                     const float src2 = SDL_SwapFloatLE(src[1]);
   173                     const double added = ((double) src1) + ((double) src2);
   174                     const float halved = (float) (added * 0.5);
   175                     *(dst++) = SDL_SwapFloatLE(halved);
   176                 }
   177             }
   178         }
   179         break;
   180     }
   181 
   182     cvt->len_cvt /= 2;
   183     if (cvt->filters[++cvt->filter_index]) {
   184         cvt->filters[cvt->filter_index] (cvt, format);
   185     }
   186 }
   187 
   188 
   189 /* Discard top 4 channels */
   190 static void SDLCALL
   191 SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   192 {
   193     int i;
   194 
   195 #ifdef DEBUG_CONVERT
   196     fprintf(stderr, "Converting down from 6 channels to stereo\n");
   197 #endif
   198 
   199 #define strip_chans_6_to_2(type) \
   200     { \
   201         const type *src = (const type *) cvt->buf; \
   202         type *dst = (type *) cvt->buf; \
   203         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   204             dst[0] = src[0]; \
   205             dst[1] = src[1]; \
   206             src += 6; \
   207             dst += 2; \
   208         } \
   209     }
   210 
   211     /* this function only cares about typesize, and data as a block of bits. */
   212     switch (SDL_AUDIO_BITSIZE(format)) {
   213     case 8:
   214         strip_chans_6_to_2(Uint8);
   215         break;
   216     case 16:
   217         strip_chans_6_to_2(Uint16);
   218         break;
   219     case 32:
   220         strip_chans_6_to_2(Uint32);
   221         break;
   222     }
   223 
   224 #undef strip_chans_6_to_2
   225 
   226     cvt->len_cvt /= 3;
   227     if (cvt->filters[++cvt->filter_index]) {
   228         cvt->filters[cvt->filter_index] (cvt, format);
   229     }
   230 }
   231 
   232 
   233 /* Discard top 2 channels of 6 */
   234 static void SDLCALL
   235 SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   236 {
   237     int i;
   238 
   239 #ifdef DEBUG_CONVERT
   240     fprintf(stderr, "Converting 6 down to quad\n");
   241 #endif
   242 
   243 #define strip_chans_6_to_4(type) \
   244     { \
   245         const type *src = (const type *) cvt->buf; \
   246         type *dst = (type *) cvt->buf; \
   247         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   248             dst[0] = src[0]; \
   249             dst[1] = src[1]; \
   250             dst[2] = src[2]; \
   251             dst[3] = src[3]; \
   252             src += 6; \
   253             dst += 4; \
   254         } \
   255     }
   256 
   257     /* this function only cares about typesize, and data as a block of bits. */
   258     switch (SDL_AUDIO_BITSIZE(format)) {
   259     case 8:
   260         strip_chans_6_to_4(Uint8);
   261         break;
   262     case 16:
   263         strip_chans_6_to_4(Uint16);
   264         break;
   265     case 32:
   266         strip_chans_6_to_4(Uint32);
   267         break;
   268     }
   269 
   270 #undef strip_chans_6_to_4
   271 
   272     cvt->len_cvt /= 6;
   273     cvt->len_cvt *= 4;
   274     if (cvt->filters[++cvt->filter_index]) {
   275         cvt->filters[cvt->filter_index] (cvt, format);
   276     }
   277 }
   278 
   279 /* Duplicate a mono channel to both stereo channels */
   280 static void SDLCALL
   281 SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   282 {
   283     int i;
   284 
   285 #ifdef DEBUG_CONVERT
   286     fprintf(stderr, "Converting to stereo\n");
   287 #endif
   288 
   289 #define dup_chans_1_to_2(type) \
   290     { \
   291         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   292         type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
   293         for (i = cvt->len_cvt / 2; i; --i, --src) { \
   294             const type val = *src; \
   295             dst -= 2; \
   296             dst[0] = dst[1] = val; \
   297         } \
   298     }
   299 
   300     /* this function only cares about typesize, and data as a block of bits. */
   301     switch (SDL_AUDIO_BITSIZE(format)) {
   302     case 8:
   303         dup_chans_1_to_2(Uint8);
   304         break;
   305     case 16:
   306         dup_chans_1_to_2(Uint16);
   307         break;
   308     case 32:
   309         dup_chans_1_to_2(Uint32);
   310         break;
   311     }
   312 
   313 #undef dup_chans_1_to_2
   314 
   315     cvt->len_cvt *= 2;
   316     if (cvt->filters[++cvt->filter_index]) {
   317         cvt->filters[cvt->filter_index] (cvt, format);
   318     }
   319 }
   320 
   321 
   322 /* Duplicate a stereo channel to a pseudo-5.1 stream */
   323 static void SDLCALL
   324 SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   325 {
   326     int i;
   327 
   328 #ifdef DEBUG_CONVERT
   329     fprintf(stderr, "Converting stereo to surround\n");
   330 #endif
   331 
   332     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   333     case AUDIO_U8:
   334         {
   335             Uint8 *src, *dst, lf, rf, ce;
   336 
   337             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   338             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
   339             for (i = cvt->len_cvt; i; --i) {
   340                 dst -= 6;
   341                 src -= 2;
   342                 lf = src[0];
   343                 rf = src[1];
   344                 ce = (lf / 2) + (rf / 2);
   345                 dst[0] = lf;
   346                 dst[1] = rf;
   347                 dst[2] = lf - ce;
   348                 dst[3] = rf - ce;
   349                 dst[4] = ce;
   350                 dst[5] = ce;
   351             }
   352         }
   353         break;
   354 
   355     case AUDIO_S8:
   356         {
   357             Sint8 *src, *dst, lf, rf, ce;
   358 
   359             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   360             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
   361             for (i = cvt->len_cvt; i; --i) {
   362                 dst -= 6;
   363                 src -= 2;
   364                 lf = src[0];
   365                 rf = src[1];
   366                 ce = (lf / 2) + (rf / 2);
   367                 dst[0] = lf;
   368                 dst[1] = rf;
   369                 dst[2] = lf - ce;
   370                 dst[3] = rf - ce;
   371                 dst[4] = ce;
   372                 dst[5] = ce;
   373             }
   374         }
   375         break;
   376 
   377     case AUDIO_U16:
   378         {
   379             Uint8 *src, *dst;
   380             Uint16 lf, rf, ce, lr, rr;
   381 
   382             src = cvt->buf + cvt->len_cvt;
   383             dst = cvt->buf + cvt->len_cvt * 3;
   384 
   385             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   386                 for (i = cvt->len_cvt / 4; i; --i) {
   387                     dst -= 12;
   388                     src -= 4;
   389                     lf = (Uint16) ((src[0] << 8) | src[1]);
   390                     rf = (Uint16) ((src[2] << 8) | src[3]);
   391                     ce = (lf / 2) + (rf / 2);
   392                     rr = lf - ce;
   393                     lr = rf - ce;
   394                     dst[1] = (lf & 0xFF);
   395                     dst[0] = ((lf >> 8) & 0xFF);
   396                     dst[3] = (rf & 0xFF);
   397                     dst[2] = ((rf >> 8) & 0xFF);
   398 
   399                     dst[1 + 4] = (lr & 0xFF);
   400                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   401                     dst[3 + 4] = (rr & 0xFF);
   402                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   403 
   404                     dst[1 + 8] = (ce & 0xFF);
   405                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   406                     dst[3 + 8] = (ce & 0xFF);
   407                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   408                 }
   409             } else {
   410                 for (i = cvt->len_cvt / 4; i; --i) {
   411                     dst -= 12;
   412                     src -= 4;
   413                     lf = (Uint16) ((src[1] << 8) | src[0]);
   414                     rf = (Uint16) ((src[3] << 8) | src[2]);
   415                     ce = (lf / 2) + (rf / 2);
   416                     rr = lf - ce;
   417                     lr = rf - ce;
   418                     dst[0] = (lf & 0xFF);
   419                     dst[1] = ((lf >> 8) & 0xFF);
   420                     dst[2] = (rf & 0xFF);
   421                     dst[3] = ((rf >> 8) & 0xFF);
   422 
   423                     dst[0 + 4] = (lr & 0xFF);
   424                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   425                     dst[2 + 4] = (rr & 0xFF);
   426                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   427 
   428                     dst[0 + 8] = (ce & 0xFF);
   429                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   430                     dst[2 + 8] = (ce & 0xFF);
   431                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   432                 }
   433             }
   434         }
   435         break;
   436 
   437     case AUDIO_S16:
   438         {
   439             Uint8 *src, *dst;
   440             Sint16 lf, rf, ce, lr, rr;
   441 
   442             src = cvt->buf + cvt->len_cvt;
   443             dst = cvt->buf + cvt->len_cvt * 3;
   444 
   445             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   446                 for (i = cvt->len_cvt / 4; i; --i) {
   447                     dst -= 12;
   448                     src -= 4;
   449                     lf = (Sint16) ((src[0] << 8) | src[1]);
   450                     rf = (Sint16) ((src[2] << 8) | src[3]);
   451                     ce = (lf / 2) + (rf / 2);
   452                     rr = lf - ce;
   453                     lr = rf - ce;
   454                     dst[1] = (lf & 0xFF);
   455                     dst[0] = ((lf >> 8) & 0xFF);
   456                     dst[3] = (rf & 0xFF);
   457                     dst[2] = ((rf >> 8) & 0xFF);
   458 
   459                     dst[1 + 4] = (lr & 0xFF);
   460                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   461                     dst[3 + 4] = (rr & 0xFF);
   462                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   463 
   464                     dst[1 + 8] = (ce & 0xFF);
   465                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   466                     dst[3 + 8] = (ce & 0xFF);
   467                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   468                 }
   469             } else {
   470                 for (i = cvt->len_cvt / 4; i; --i) {
   471                     dst -= 12;
   472                     src -= 4;
   473                     lf = (Sint16) ((src[1] << 8) | src[0]);
   474                     rf = (Sint16) ((src[3] << 8) | src[2]);
   475                     ce = (lf / 2) + (rf / 2);
   476                     rr = lf - ce;
   477                     lr = rf - ce;
   478                     dst[0] = (lf & 0xFF);
   479                     dst[1] = ((lf >> 8) & 0xFF);
   480                     dst[2] = (rf & 0xFF);
   481                     dst[3] = ((rf >> 8) & 0xFF);
   482 
   483                     dst[0 + 4] = (lr & 0xFF);
   484                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   485                     dst[2 + 4] = (rr & 0xFF);
   486                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   487 
   488                     dst[0 + 8] = (ce & 0xFF);
   489                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   490                     dst[2 + 8] = (ce & 0xFF);
   491                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   492                 }
   493             }
   494         }
   495         break;
   496 
   497     case AUDIO_S32:
   498         {
   499             Sint32 lf, rf, ce;
   500             const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
   501             Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
   502 
   503             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   504                 for (i = cvt->len_cvt / 8; i; --i) {
   505                     dst -= 6;
   506                     src -= 2;
   507                     lf = (Sint32) SDL_SwapBE32(src[0]);
   508                     rf = (Sint32) SDL_SwapBE32(src[1]);
   509                     ce = (lf / 2) + (rf / 2);
   510                     dst[0] = SDL_SwapBE32((Uint32) lf);
   511                     dst[1] = SDL_SwapBE32((Uint32) rf);
   512                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   513                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   514                     dst[4] = SDL_SwapBE32((Uint32) ce);
   515                     dst[5] = SDL_SwapBE32((Uint32) ce);
   516                 }
   517             } else {
   518                 for (i = cvt->len_cvt / 8; i; --i) {
   519                     dst -= 6;
   520                     src -= 2;
   521                     lf = (Sint32) SDL_SwapLE32(src[0]);
   522                     rf = (Sint32) SDL_SwapLE32(src[1]);
   523                     ce = (lf / 2) + (rf / 2);
   524                     dst[0] = src[0];
   525                     dst[1] = src[1];
   526                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   527                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   528                     dst[4] = SDL_SwapLE32((Uint32) ce);
   529                     dst[5] = SDL_SwapLE32((Uint32) ce);
   530                 }
   531             }
   532         }
   533         break;
   534 
   535     case AUDIO_F32:
   536         {
   537             float lf, rf, ce;
   538             const float *src = (const float *) cvt->buf + cvt->len_cvt;
   539             float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
   540 
   541             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   542                 for (i = cvt->len_cvt / 8; i; --i) {
   543                     dst -= 6;
   544                     src -= 2;
   545                     lf = SDL_SwapFloatBE(src[0]);
   546                     rf = SDL_SwapFloatBE(src[1]);
   547                     ce = (lf * 0.5f) + (rf * 0.5f);
   548                     dst[0] = src[0];
   549                     dst[1] = src[1];
   550                     dst[2] = SDL_SwapFloatBE(lf - ce);
   551                     dst[3] = SDL_SwapFloatBE(rf - ce);
   552                     dst[4] = dst[5] = SDL_SwapFloatBE(ce);
   553                 }
   554             } else {
   555                 for (i = cvt->len_cvt / 8; i; --i) {
   556                     dst -= 6;
   557                     src -= 2;
   558                     lf = SDL_SwapFloatLE(src[0]);
   559                     rf = SDL_SwapFloatLE(src[1]);
   560                     ce = (lf * 0.5f) + (rf * 0.5f);
   561                     dst[0] = src[0];
   562                     dst[1] = src[1];
   563                     dst[2] = SDL_SwapFloatLE(lf - ce);
   564                     dst[3] = SDL_SwapFloatLE(rf - ce);
   565                     dst[4] = dst[5] = SDL_SwapFloatLE(ce);
   566                 }
   567             }
   568         }
   569         break;
   570 
   571     }
   572     cvt->len_cvt *= 3;
   573     if (cvt->filters[++cvt->filter_index]) {
   574         cvt->filters[cvt->filter_index] (cvt, format);
   575     }
   576 }
   577 
   578 
   579 /* Duplicate a stereo channel to a pseudo-4.0 stream */
   580 static void SDLCALL
   581 SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   582 {
   583     int i;
   584 
   585 #ifdef DEBUG_CONVERT
   586     fprintf(stderr, "Converting stereo to quad\n");
   587 #endif
   588 
   589     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   590     case AUDIO_U8:
   591         {
   592             Uint8 *src, *dst, lf, rf, ce;
   593 
   594             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   595             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
   596             for (i = cvt->len_cvt; i; --i) {
   597                 dst -= 4;
   598                 src -= 2;
   599                 lf = src[0];
   600                 rf = src[1];
   601                 ce = (lf / 2) + (rf / 2);
   602                 dst[0] = lf;
   603                 dst[1] = rf;
   604                 dst[2] = lf - ce;
   605                 dst[3] = rf - ce;
   606             }
   607         }
   608         break;
   609 
   610     case AUDIO_S8:
   611         {
   612             Sint8 *src, *dst, lf, rf, ce;
   613 
   614             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   615             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
   616             for (i = cvt->len_cvt; i; --i) {
   617                 dst -= 4;
   618                 src -= 2;
   619                 lf = src[0];
   620                 rf = src[1];
   621                 ce = (lf / 2) + (rf / 2);
   622                 dst[0] = lf;
   623                 dst[1] = rf;
   624                 dst[2] = lf - ce;
   625                 dst[3] = rf - ce;
   626             }
   627         }
   628         break;
   629 
   630     case AUDIO_U16:
   631         {
   632             Uint8 *src, *dst;
   633             Uint16 lf, rf, ce, lr, rr;
   634 
   635             src = cvt->buf + cvt->len_cvt;
   636             dst = cvt->buf + cvt->len_cvt * 2;
   637 
   638             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   639                 for (i = cvt->len_cvt / 4; i; --i) {
   640                     dst -= 8;
   641                     src -= 4;
   642                     lf = (Uint16) ((src[0] << 8) | src[1]);
   643                     rf = (Uint16) ((src[2] << 8) | src[3]);
   644                     ce = (lf / 2) + (rf / 2);
   645                     rr = lf - ce;
   646                     lr = rf - ce;
   647                     dst[1] = (lf & 0xFF);
   648                     dst[0] = ((lf >> 8) & 0xFF);
   649                     dst[3] = (rf & 0xFF);
   650                     dst[2] = ((rf >> 8) & 0xFF);
   651 
   652                     dst[1 + 4] = (lr & 0xFF);
   653                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   654                     dst[3 + 4] = (rr & 0xFF);
   655                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   656                 }
   657             } else {
   658                 for (i = cvt->len_cvt / 4; i; --i) {
   659                     dst -= 8;
   660                     src -= 4;
   661                     lf = (Uint16) ((src[1] << 8) | src[0]);
   662                     rf = (Uint16) ((src[3] << 8) | src[2]);
   663                     ce = (lf / 2) + (rf / 2);
   664                     rr = lf - ce;
   665                     lr = rf - ce;
   666                     dst[0] = (lf & 0xFF);
   667                     dst[1] = ((lf >> 8) & 0xFF);
   668                     dst[2] = (rf & 0xFF);
   669                     dst[3] = ((rf >> 8) & 0xFF);
   670 
   671                     dst[0 + 4] = (lr & 0xFF);
   672                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   673                     dst[2 + 4] = (rr & 0xFF);
   674                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   675                 }
   676             }
   677         }
   678         break;
   679 
   680     case AUDIO_S16:
   681         {
   682             Uint8 *src, *dst;
   683             Sint16 lf, rf, ce, lr, rr;
   684 
   685             src = cvt->buf + cvt->len_cvt;
   686             dst = cvt->buf + cvt->len_cvt * 2;
   687 
   688             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   689                 for (i = cvt->len_cvt / 4; i; --i) {
   690                     dst -= 8;
   691                     src -= 4;
   692                     lf = (Sint16) ((src[0] << 8) | src[1]);
   693                     rf = (Sint16) ((src[2] << 8) | src[3]);
   694                     ce = (lf / 2) + (rf / 2);
   695                     rr = lf - ce;
   696                     lr = rf - ce;
   697                     dst[1] = (lf & 0xFF);
   698                     dst[0] = ((lf >> 8) & 0xFF);
   699                     dst[3] = (rf & 0xFF);
   700                     dst[2] = ((rf >> 8) & 0xFF);
   701 
   702                     dst[1 + 4] = (lr & 0xFF);
   703                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   704                     dst[3 + 4] = (rr & 0xFF);
   705                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   706                 }
   707             } else {
   708                 for (i = cvt->len_cvt / 4; i; --i) {
   709                     dst -= 8;
   710                     src -= 4;
   711                     lf = (Sint16) ((src[1] << 8) | src[0]);
   712                     rf = (Sint16) ((src[3] << 8) | src[2]);
   713                     ce = (lf / 2) + (rf / 2);
   714                     rr = lf - ce;
   715                     lr = rf - ce;
   716                     dst[0] = (lf & 0xFF);
   717                     dst[1] = ((lf >> 8) & 0xFF);
   718                     dst[2] = (rf & 0xFF);
   719                     dst[3] = ((rf >> 8) & 0xFF);
   720 
   721                     dst[0 + 4] = (lr & 0xFF);
   722                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   723                     dst[2 + 4] = (rr & 0xFF);
   724                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   725                 }
   726             }
   727         }
   728         break;
   729 
   730     case AUDIO_S32:
   731         {
   732             const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
   733             Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
   734             Sint32 lf, rf, ce;
   735 
   736             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   737                 for (i = cvt->len_cvt / 8; i; --i) {
   738                     dst -= 4;
   739                     src -= 2;
   740                     lf = (Sint32) SDL_SwapBE32(src[0]);
   741                     rf = (Sint32) SDL_SwapBE32(src[1]);
   742                     ce = (lf / 2) + (rf / 2);
   743                     dst[0] = src[0];
   744                     dst[1] = src[1];
   745                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   746                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   747                 }
   748             } else {
   749                 for (i = cvt->len_cvt / 8; i; --i) {
   750                     dst -= 4;
   751                     src -= 2;
   752                     lf = (Sint32) SDL_SwapLE32(src[0]);
   753                     rf = (Sint32) SDL_SwapLE32(src[1]);
   754                     ce = (lf / 2) + (rf / 2);
   755                     dst[0] = src[0];
   756                     dst[1] = src[1];
   757                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   758                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   759                 }
   760             }
   761         }
   762         break;
   763     }
   764     cvt->len_cvt *= 2;
   765     if (cvt->filters[++cvt->filter_index]) {
   766         cvt->filters[cvt->filter_index] (cvt, format);
   767     }
   768 }
   769 
   770 /* Convert rate up by multiple of 2 */
   771 static void SDLCALL
   772 SDL_RateMUL2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   773 {
   774     int i;
   775 
   776 #ifdef DEBUG_CONVERT
   777     fprintf(stderr, "Converting audio rate * 2 (mono)\n");
   778 #endif
   779 
   780 #define mul2_mono(type) { \
   781         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   782         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   783         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
   784             src--; \
   785             dst[-1] = dst[-2] = src[0]; \
   786             dst -= 2; \
   787         } \
   788     }
   789 
   790     switch (SDL_AUDIO_BITSIZE(format)) {
   791     case 8:
   792         mul2_mono(Uint8);
   793         break;
   794     case 16:
   795         mul2_mono(Uint16);
   796         break;
   797     case 32:
   798         mul2_mono(Uint32);
   799         break;
   800     }
   801 
   802 #undef mul2_mono
   803 
   804     cvt->len_cvt *= 2;
   805     if (cvt->filters[++cvt->filter_index]) {
   806         cvt->filters[cvt->filter_index] (cvt, format);
   807     }
   808 }
   809 
   810 
   811 /* Convert rate up by multiple of 2, for stereo */
   812 static void SDLCALL
   813 SDL_RateMUL2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   814 {
   815     int i;
   816 
   817 #ifdef DEBUG_CONVERT
   818     fprintf(stderr, "Converting audio rate * 2 (stereo)\n");
   819 #endif
   820 
   821 #define mul2_stereo(type) { \
   822         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   823         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   824         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   825             const type r = src[-1]; \
   826             const type l = src[-2]; \
   827             src -= 2; \
   828             dst[-1] = r; \
   829             dst[-2] = l; \
   830             dst[-3] = r; \
   831             dst[-4] = l; \
   832             dst -= 4; \
   833         } \
   834     }
   835 
   836     switch (SDL_AUDIO_BITSIZE(format)) {
   837     case 8:
   838         mul2_stereo(Uint8);
   839         break;
   840     case 16:
   841         mul2_stereo(Uint16);
   842         break;
   843     case 32:
   844         mul2_stereo(Uint32);
   845         break;
   846     }
   847 
   848 #undef mul2_stereo
   849 
   850     cvt->len_cvt *= 2;
   851     if (cvt->filters[++cvt->filter_index]) {
   852         cvt->filters[cvt->filter_index] (cvt, format);
   853     }
   854 }
   855 
   856 /* Convert rate up by multiple of 2, for quad */
   857 static void SDLCALL
   858 SDL_RateMUL2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   859 {
   860     int i;
   861 
   862 #ifdef DEBUG_CONVERT
   863     fprintf(stderr, "Converting audio rate * 2 (quad)\n");
   864 #endif
   865 
   866 #define mul2_quad(type) { \
   867         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   868         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   869         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
   870             const type c1 = src[-1]; \
   871             const type c2 = src[-2]; \
   872             const type c3 = src[-3]; \
   873             const type c4 = src[-4]; \
   874             src -= 4; \
   875             dst[-1] = c1; \
   876             dst[-2] = c2; \
   877             dst[-3] = c3; \
   878             dst[-4] = c4; \
   879             dst[-5] = c1; \
   880             dst[-6] = c2; \
   881             dst[-7] = c3; \
   882             dst[-8] = c4; \
   883             dst -= 8; \
   884         } \
   885     }
   886 
   887     switch (SDL_AUDIO_BITSIZE(format)) {
   888     case 8:
   889         mul2_quad(Uint8);
   890         break;
   891     case 16:
   892         mul2_quad(Uint16);
   893         break;
   894     case 32:
   895         mul2_quad(Uint32);
   896         break;
   897     }
   898 
   899 #undef mul2_quad
   900 
   901     cvt->len_cvt *= 2;
   902     if (cvt->filters[++cvt->filter_index]) {
   903         cvt->filters[cvt->filter_index] (cvt, format);
   904     }
   905 }
   906 
   907 
   908 /* Convert rate up by multiple of 2, for 5.1 */
   909 static void SDLCALL
   910 SDL_RateMUL2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   911 {
   912     int i;
   913 
   914 #ifdef DEBUG_CONVERT
   915     fprintf(stderr, "Converting audio rate * 2 (six channels)\n");
   916 #endif
   917 
   918 #define mul2_chansix(type) { \
   919         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   920         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   921         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   922             const type c1 = src[-1]; \
   923             const type c2 = src[-2]; \
   924             const type c3 = src[-3]; \
   925             const type c4 = src[-4]; \
   926             const type c5 = src[-5]; \
   927             const type c6 = src[-6]; \
   928             src -= 6; \
   929             dst[-1] = c1; \
   930             dst[-2] = c2; \
   931             dst[-3] = c3; \
   932             dst[-4] = c4; \
   933             dst[-5] = c5; \
   934             dst[-6] = c6; \
   935             dst[-7] = c1; \
   936             dst[-8] = c2; \
   937             dst[-9] = c3; \
   938             dst[-10] = c4; \
   939             dst[-11] = c5; \
   940             dst[-12] = c6; \
   941             dst -= 12; \
   942         } \
   943     }
   944 
   945     switch (SDL_AUDIO_BITSIZE(format)) {
   946     case 8:
   947         mul2_chansix(Uint8);
   948         break;
   949     case 16:
   950         mul2_chansix(Uint16);
   951         break;
   952     case 32:
   953         mul2_chansix(Uint32);
   954         break;
   955     }
   956 
   957 #undef mul2_chansix
   958 
   959     cvt->len_cvt *= 2;
   960     if (cvt->filters[++cvt->filter_index]) {
   961         cvt->filters[cvt->filter_index] (cvt, format);
   962     }
   963 }
   964 
   965 /* Convert rate down by multiple of 2 */
   966 static void SDLCALL
   967 SDL_RateDIV2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   968 {
   969     int i;
   970 
   971 #ifdef DEBUG_CONVERT
   972     fprintf(stderr, "Converting audio rate / 2 (mono)\n");
   973 #endif
   974 
   975 #define div2_mono(type) { \
   976         const type *src = (const type *) cvt->buf; \
   977         type *dst = (type *) cvt->buf; \
   978         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   979             dst[0] = src[0]; \
   980             src += 2; \
   981             dst++; \
   982         } \
   983     }
   984 
   985     switch (SDL_AUDIO_BITSIZE(format)) {
   986     case 8:
   987         div2_mono(Uint8);
   988         break;
   989     case 16:
   990         div2_mono(Uint16);
   991         break;
   992     case 32:
   993         div2_mono(Uint32);
   994         break;
   995     }
   996 
   997 #undef div2_mono
   998 
   999     cvt->len_cvt /= 2;
  1000     if (cvt->filters[++cvt->filter_index]) {
  1001         cvt->filters[cvt->filter_index] (cvt, format);
  1002     }
  1003 }
  1004 
  1005 
  1006 /* Convert rate down by multiple of 2, for stereo */
  1007 static void SDLCALL
  1008 SDL_RateDIV2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1009 {
  1010     int i;
  1011 
  1012 #ifdef DEBUG_CONVERT
  1013     fprintf(stderr, "Converting audio rate / 2 (stereo)\n");
  1014 #endif
  1015 
  1016 #define div2_stereo(type) { \
  1017         const type *src = (const type *) cvt->buf; \
  1018         type *dst = (type *) cvt->buf; \
  1019         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
  1020             dst[0] = src[0]; \
  1021             dst[1] = src[1]; \
  1022             src += 4; \
  1023             dst += 2; \
  1024         } \
  1025     }
  1026 
  1027     switch (SDL_AUDIO_BITSIZE(format)) {
  1028     case 8:
  1029         div2_stereo(Uint8);
  1030         break;
  1031     case 16:
  1032         div2_stereo(Uint16);
  1033         break;
  1034     case 32:
  1035         div2_stereo(Uint32);
  1036         break;
  1037     }
  1038 
  1039 #undef div2_stereo
  1040 
  1041     cvt->len_cvt /= 2;
  1042     if (cvt->filters[++cvt->filter_index]) {
  1043         cvt->filters[cvt->filter_index] (cvt, format);
  1044     }
  1045 }
  1046 
  1047 
  1048 /* Convert rate down by multiple of 2, for quad */
  1049 static void SDLCALL
  1050 SDL_RateDIV2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1051 {
  1052     int i;
  1053 
  1054 #ifdef DEBUG_CONVERT
  1055     fprintf(stderr, "Converting audio rate / 2 (quad)\n");
  1056 #endif
  1057 
  1058 #define div2_quad(type) { \
  1059         const type *src = (const type *) cvt->buf; \
  1060         type *dst = (type *) cvt->buf; \
  1061         for (i = cvt->len_cvt / (sizeof (type) * 8); i; --i) { \
  1062             dst[0] = src[0]; \
  1063             dst[1] = src[1]; \
  1064             dst[2] = src[2]; \
  1065             dst[3] = src[3]; \
  1066             src += 8; \
  1067             dst += 4; \
  1068         } \
  1069     }
  1070 
  1071     switch (SDL_AUDIO_BITSIZE(format)) {
  1072     case 8:
  1073         div2_quad(Uint8);
  1074         break;
  1075     case 16:
  1076         div2_quad(Uint16);
  1077         break;
  1078     case 32:
  1079         div2_quad(Uint32);
  1080         break;
  1081     }
  1082 
  1083 #undef div2_quad
  1084 
  1085     cvt->len_cvt /= 2;
  1086     if (cvt->filters[++cvt->filter_index]) {
  1087         cvt->filters[cvt->filter_index] (cvt, format);
  1088     }
  1089 }
  1090 
  1091 /* Convert rate down by multiple of 2, for 5.1 */
  1092 static void SDLCALL
  1093 SDL_RateDIV2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1094 {
  1095     int i;
  1096 
  1097 #ifdef DEBUG_CONVERT
  1098     fprintf(stderr, "Converting audio rate / 2 (six channels)\n");
  1099 #endif
  1100 
  1101 #define div2_chansix(type) { \
  1102         const type *src = (const type *) cvt->buf; \
  1103         type *dst = (type *) cvt->buf; \
  1104         for (i = cvt->len_cvt / (sizeof (type) * 12); i; --i) { \
  1105             dst[0] = src[0]; \
  1106             dst[1] = src[1]; \
  1107             dst[2] = src[2]; \
  1108             dst[3] = src[3]; \
  1109             dst[4] = src[4]; \
  1110             dst[5] = src[5]; \
  1111             src += 12; \
  1112             dst += 6; \
  1113         } \
  1114     }
  1115 
  1116     switch (SDL_AUDIO_BITSIZE(format)) {
  1117     case 8:
  1118         div2_chansix(Uint8);
  1119         break;
  1120     case 16:
  1121         div2_chansix(Uint16);
  1122         break;
  1123     case 32:
  1124         div2_chansix(Uint32);
  1125         break;
  1126     }
  1127 
  1128 #undef div_chansix
  1129 
  1130     cvt->len_cvt /= 2;
  1131     if (cvt->filters[++cvt->filter_index]) {
  1132         cvt->filters[cvt->filter_index] (cvt, format);
  1133     }
  1134 }
  1135 
  1136 /* Very slow rate conversion routine */
  1137 static void SDLCALL
  1138 SDL_RateSLOW(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1139 {
  1140     double ipos;
  1141     int i, clen;
  1142 
  1143 #ifdef DEBUG_CONVERT
  1144     fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
  1145 #endif
  1146     clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
  1147     if (cvt->rate_incr > 1.0) {
  1148         switch (SDL_AUDIO_BITSIZE(format)) {
  1149         case 8:
  1150             {
  1151                 Uint8 *output;
  1152 
  1153                 output = cvt->buf;
  1154                 ipos = 0.0;
  1155                 for (i = clen; i; --i) {
  1156                     *output = cvt->buf[(int) ipos];
  1157                     ipos += cvt->rate_incr;
  1158                     output += 1;
  1159                 }
  1160             }
  1161             break;
  1162 
  1163         case 16:
  1164             {
  1165                 Uint16 *output;
  1166 
  1167                 clen &= ~1;
  1168                 output = (Uint16 *) cvt->buf;
  1169                 ipos = 0.0;
  1170                 for (i = clen / 2; i; --i) {
  1171                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1172                     ipos += cvt->rate_incr;
  1173                     output += 1;
  1174                 }
  1175             }
  1176             break;
  1177 
  1178         case 32:
  1179             {
  1180                 /* !!! FIXME: need 32-bit converter here! */
  1181 #ifdef DEBUG_CONVERT
  1182                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1183 #endif
  1184             }
  1185         }
  1186     } else {
  1187         switch (SDL_AUDIO_BITSIZE(format)) {
  1188         case 8:
  1189             {
  1190                 Uint8 *output;
  1191 
  1192                 output = cvt->buf + clen;
  1193                 ipos = (double) cvt->len_cvt;
  1194                 for (i = clen; i; --i) {
  1195                     ipos -= cvt->rate_incr;
  1196                     output -= 1;
  1197                     *output = cvt->buf[(int) ipos];
  1198                 }
  1199             }
  1200             break;
  1201 
  1202         case 16:
  1203             {
  1204                 Uint16 *output;
  1205 
  1206                 clen &= ~1;
  1207                 output = (Uint16 *) (cvt->buf + clen);
  1208                 ipos = (double) cvt->len_cvt / 2;
  1209                 for (i = clen / 2; i; --i) {
  1210                     ipos -= cvt->rate_incr;
  1211                     output -= 1;
  1212                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1213                 }
  1214             }
  1215             break;
  1216 
  1217         case 32:
  1218             {
  1219                 /* !!! FIXME: need 32-bit converter here! */
  1220 #ifdef DEBUG_CONVERT
  1221                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1222 #endif
  1223             }
  1224         }
  1225     }
  1226 
  1227     cvt->len_cvt = clen;
  1228     if (cvt->filters[++cvt->filter_index]) {
  1229         cvt->filters[cvt->filter_index] (cvt, format);
  1230     }
  1231 }
  1232 
  1233 /* Perform proper resampling */
  1234 static void SDLCALL
  1235 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1236 {
  1237     int i, j;
  1238 
  1239 #ifdef DEBUG_CONVERT
  1240     fprintf(stderr, "Converting audio rate via proper resampling (mono)\n");
  1241 #endif
  1242 
  1243 #define zerostuff_mono(type) { \
  1244         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
  1245         type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \
  1246         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
  1247             src--; \
  1248             dst[-1] = src[0]; \
  1249 			for( j = -cvt->len_mult; j < -1; ++j ) { \
  1250 				dst[j] = 0; \
  1251 			} \
  1252             dst -= cvt->len_mult; \
  1253         } \
  1254     }
  1255 	
  1256 #define discard_mono(type) { \
  1257         const type *src = (const type *) (cvt->buf); \
  1258         type *dst = (type *) (cvt->buf); \
  1259         for (i = 0; i < cvt->len_cvt / sizeof (type); ++i) { \
  1260             dst[0] = src[0]; \
  1261             src += cvt->len_div; \
  1262             ++dst; \
  1263         } \
  1264     }
  1265 
  1266 	// Step 1: Zero stuff the conversion buffer
  1267     switch (SDL_AUDIO_BITSIZE(format)) {
  1268     case 8:
  1269         zerostuff_mono(Uint8);
  1270         break;
  1271     case 16:
  1272         zerostuff_mono(Uint16);
  1273         break;
  1274     case 32:
  1275         zerostuff_mono(Uint32);
  1276         break;
  1277     }
  1278 	
  1279 	cvt->len_cvt *= cvt->len_mult;
  1280 
  1281 	// Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies
  1282 	
  1283 	// Step 3: Discard unnecessary samples
  1284     switch (SDL_AUDIO_BITSIZE(format)) {
  1285     case 8:
  1286         discard_mono(Uint8);
  1287         break;
  1288     case 16:
  1289         discard_mono(Uint16);
  1290         break;
  1291     case 32:
  1292         discard_mono(Uint32);
  1293         break;
  1294     }
  1295 	
  1296 #undef zerostuff_mono
  1297 #undef discard_mono
  1298 
  1299     cvt->len_cvt /= cvt->len_div;
  1300 	
  1301     if (cvt->filters[++cvt->filter_index]) {
  1302         cvt->filters[cvt->filter_index] (cvt, format);
  1303     }
  1304 }
  1305 
  1306 int
  1307 SDL_ConvertAudio(SDL_AudioCVT * cvt)
  1308 {
  1309     /* Make sure there's data to convert */
  1310     if (cvt->buf == NULL) {
  1311         SDL_SetError("No buffer allocated for conversion");
  1312         return (-1);
  1313     }
  1314     /* Return okay if no conversion is necessary */
  1315     cvt->len_cvt = cvt->len;
  1316     if (cvt->filters[0] == NULL) {
  1317         return (0);
  1318     }
  1319 
  1320     /* Set up the conversion and go! */
  1321     cvt->filter_index = 0;
  1322     cvt->filters[0] (cvt, cvt->src_format);
  1323     return (0);
  1324 }
  1325 
  1326 
  1327 static SDL_AudioFilter
  1328 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1329 {
  1330     /*
  1331      * Fill in any future conversions that are specialized to a
  1332      *  processor, platform, compiler, or library here.
  1333      */
  1334 
  1335     return NULL;                /* no specialized converter code available. */
  1336 }
  1337 
  1338 
  1339 /*
  1340  * Find a converter between two data types. We try to select a hand-tuned
  1341  *  asm/vectorized/optimized function first, and then fallback to an
  1342  *  autogenerated function that is customized to convert between two
  1343  *  specific data types.
  1344  */
  1345 static int
  1346 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
  1347                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1348 {
  1349     if (src_fmt != dst_fmt) {
  1350         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
  1351         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
  1352         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
  1353 
  1354         /* No hand-tuned converter? Try the autogenerated ones. */
  1355         if (filter == NULL) {
  1356             int i;
  1357             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
  1358                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
  1359                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
  1360                     filter = filt->filter;
  1361                     break;
  1362                 }
  1363             }
  1364 
  1365             if (filter == NULL) {
  1366                 return -1;      /* Still no matching converter?! */
  1367             }
  1368         }
  1369 
  1370         /* Update (cvt) with filter details... */
  1371         cvt->filters[cvt->filter_index++] = filter;
  1372         if (src_bitsize < dst_bitsize) {
  1373             const int mult = (dst_bitsize / src_bitsize);
  1374             cvt->len_mult *= mult;
  1375             cvt->len_ratio *= mult;
  1376         } else if (src_bitsize > dst_bitsize) {
  1377             cvt->len_ratio /= (src_bitsize / dst_bitsize);
  1378         }
  1379 
  1380         return 1;               /* added a converter. */
  1381     }
  1382 
  1383     return 0;                   /* no conversion necessary. */
  1384 }
  1385 
  1386 /* Generate the necessary IIR lowpass coefficients for resampling.
  1387    Assume that the SDL_AudioCVT struct is already set up with
  1388    the correct values for len_mult and len_div, and use the
  1389    type of dst_format. Also assume the buffer is allocated.
  1390    Note the buffer needs to be 6 units long.
  1391    For now, use RBJ's cookbook coefficients. It might be more
  1392    optimal to create a Butterworth filter, but this is more difficult.
  1393 */
  1394 int SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
  1395 	float fc;			/* cutoff frequency */
  1396 	float coeff[6];		/* floating point iir coefficients b0, b1, b2, a0, a1, a2 */
  1397 	float scale;
  1398 	float w0, alpha, cosw0;
  1399 	
  1400 	/* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */
  1401 	static const float Q = 5.0f;
  1402 	static const float CUTOFF = 0.4f;
  1403 	
  1404 	fc = (cvt->len_mult > cvt->len_div) ? CUTOFF / (float)cvt->len_mult : CUTOFF / (float)cvt->len_div;
  1405 	
  1406 	w0 = 2.0f * M_PI * fc;
  1407 	cosw0 = cosf(w0);
  1408 	alpha = sin(w0) / (2.0f * Q);
  1409 	
  1410 	/* Compute coefficients, normalizing by a0 */
  1411 	scale = 1.0f / (1.0f + alpha);
  1412 	
  1413 	coeff[0] = (1.0f - cosw0) / 2.0f * scale;
  1414 	coeff[1] = (1.0f - cosw0) * scale;
  1415 	coeff[2] = coeff[0];
  1416 	
  1417 	coeff[3] = 1.0f;	/* a0 is normalized to 1 */
  1418 	coeff[4] = -2.0f * cosw0 * scale;
  1419 	coeff[5] = (1.0f - alpha) * scale;
  1420 	
  1421 	/* Convert coefficients to fixed point, using the range (-2.0, 2.0) */
  1422 	
  1423 	/* Initialize the state buffer to all zeroes, and set initial position */
  1424 	memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4);
  1425 	cvt->state_pos = 0;
  1426 }
  1427 
  1428 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct */
  1429 int SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
  1430 	int n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4);
  1431 	int m = cvt->len_sinc;
  1432 	int i, j;
  1433 	
  1434 	/* Note: this makes use of the symmetry of the sinc filter.
  1435 	   We can also make a big optimization here by taking advantage
  1436 	   of the fact that the signal is zero stuffed, so we can do
  1437 	   significantly fewer multiplications and additions.
  1438 	*/
  1439 #define filter_sinc(type, shift_bits) { \
  1440 			type *sinc = (type *)cvt->sinc; \
  1441 			type *state = (type *)cvt->state_buf; \
  1442 			type *buf = (type *)cvt->buf; \
  1443 			for(i = 0; i < n; ++i) { \
  1444 				state[cvt->state_pos++] = buf[i] >> shift_bits; \
  1445 				if(cvt->state_pos == m) cvt->state_pos = 0; \
  1446 				buf[i] = 0; \
  1447 				for(j = 0; j < m;  ++j) { \
  1448 					buf[i] += state[j] * sinc[j]; \
  1449 				} \
  1450 			} \
  1451 		}
  1452 			
  1453 	switch (SDL_AUDIO_BITSIZE(format)) {
  1454 		case 8:
  1455 			filter_sinc(Uint8, 4);
  1456 			break;
  1457 		case 16:
  1458 			filter_sinc(Uint16, 8);
  1459 			break;
  1460 		case 32:
  1461 			filter_sinc(Uint32, 16);
  1462 			break;
  1463 	}
  1464 	
  1465 #undef filter_sinc
  1466 			
  1467 }
  1468 
  1469 /* Generate the necessary windowed sinc filter for resampling.
  1470    Assume that the SDL_AudioCVT struct is already set up with
  1471    the correct values for len_mult and len_div, and use the
  1472    type of dst_format. Also assume the buffer is allocated.
  1473    Note the buffer needs to be m+1 units long.
  1474 */
  1475 int
  1476 SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format, unsigned int m) {
  1477 	float fScale;		/* scale factor for fixed point */
  1478 	float *fSinc;		/* floating point sinc buffer, to be converted to fixed point */
  1479 	float fc;			/* cutoff frequency */
  1480 	float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
  1481 	float norm_sum, norm_fact;
  1482 	unsigned int i;
  1483 
  1484 	/* Check that the buffer is allocated */
  1485 	if( cvt->sinc == NULL ) {
  1486 		return -1;
  1487 	}
  1488 
  1489 	/* Set the length */
  1490 	cvt->len_sinc = m;
  1491 	
  1492 	/* Allocate the floating point windowed sinc. */
  1493 	fSinc = (float *)malloc(m * sizeof(float));
  1494 	if( fSinc == NULL ) {
  1495 		return -1;
  1496 	}
  1497 	
  1498 	/* Set up the filter parameters */
  1499 	fc = (cvt->len_mult > cvt->len_div) ? 0.5f / (float)cvt->len_mult : 0.5f / (float)cvt->len_div;
  1500 	two_pi_fc = 2.0f * M_PI * fc;
  1501 	two_pi_over_m = 2.0f * M_PI / (float)m;
  1502 	four_pi_over_m = 2.0f * two_pi_over_m;
  1503 	m_over_two = (float)m / 2.0f;
  1504 	norm_sum = 0.0f;
  1505 	
  1506 	for(i = 0; i <= m; ++i ) {
  1507 		if( i == m/2 ) {
  1508 			fSinc[i] = two_pi_fc;
  1509 		} else {
  1510 			fSinc[i] = sinf(two_pi_fc * ((float)i - m_over_two)) / ((float)i - m_over_two);
  1511 			/* Apply blackman window */
  1512 			fSinc[i] *= 0.42f - 0.5f * cosf(two_pi_over_m * (float)i) + 0.08f * cosf(four_pi_over_m * (float)i);
  1513 		}
  1514 		norm_sum += abs(fSinc[i]);
  1515 	}
  1516 
  1517 	/* Now normalize and convert to fixed point. We scale everything to half the precision
  1518 	   of whatever datatype we're using, for example, 16 bit data means we use 8 bits */
  1519 	
  1520 #define convert_fixed(type, size) { \
  1521 		norm_fact = size / norm_sum; \
  1522 		type *dst = (type *)cvt->sinc; \
  1523 		for( i = 0; i <= m; ++i ) { \
  1524 			dst[i] = (type)(fSinc[i] * norm_fact); \
  1525 		} \
  1526 	}
  1527 	
  1528 	/* If we're using floating point, we only need to normalize */
  1529 	if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1530 		float *fDest = (float *)cvt->sinc;
  1531 		norm_fact = 1.0f / norm_sum;
  1532 		for(i = 0; i <= m; ++i) {
  1533 			fDest[i] = fSinc[i] * norm_fact;
  1534 		}
  1535 	} else {
  1536 		switch (SDL_AUDIO_BITSIZE(format)) {
  1537 			case 8:
  1538 				convert_fixed(Uint8, 0x0e);
  1539 				break;
  1540 			case 16:
  1541 				convert_fixed(Uint16, 0xfe);
  1542 				break;
  1543 			case 32:
  1544 				convert_fixed(Uint32, 0xfffe);
  1545 				break;
  1546 		}
  1547 	}
  1548 	
  1549 	/* Initialize the state buffer to all zeroes, and set initial position */
  1550 	memset(cvt->state_buf, 0, cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
  1551 	cvt->state_pos = 0;
  1552 	
  1553 	/* Clean up */
  1554 #undef convert_fixed
  1555 	free(fSinc);
  1556 }
  1557 
  1558 
  1559 /* Creates a set of audio filters to convert from one format to another.
  1560    Returns -1 if the format conversion is not supported, 0 if there's
  1561    no conversion needed, or 1 if the audio filter is set up.
  1562 */
  1563 
  1564 int
  1565 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
  1566                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1567                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1568 {
  1569     /* there are no unsigned types over 16 bits, so catch this upfront. */
  1570     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1571         return -1;
  1572     }
  1573     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1574         return -1;
  1575     }
  1576 #ifdef DEBUG_CONVERT
  1577     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1578            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1579 #endif
  1580 
  1581     /* Start off with no conversion necessary */
  1582 
  1583     cvt->src_format = src_fmt;
  1584     cvt->dst_format = dst_fmt;
  1585     cvt->needed = 0;
  1586     cvt->filter_index = 0;
  1587     cvt->filters[0] = NULL;
  1588     cvt->len_mult = 1;
  1589     cvt->len_ratio = 1.0;
  1590 
  1591     /* Convert data types, if necessary. Updates (cvt). */
  1592     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1593         return -1;              /* shouldn't happen, but just in case... */
  1594 
  1595     /* Channel conversion */
  1596     if (src_channels != dst_channels) {
  1597         if ((src_channels == 1) && (dst_channels > 1)) {
  1598             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1599             cvt->len_mult *= 2;
  1600             src_channels = 2;
  1601             cvt->len_ratio *= 2;
  1602         }
  1603         if ((src_channels == 2) && (dst_channels == 6)) {
  1604             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1605             src_channels = 6;
  1606             cvt->len_mult *= 3;
  1607             cvt->len_ratio *= 3;
  1608         }
  1609         if ((src_channels == 2) && (dst_channels == 4)) {
  1610             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1611             src_channels = 4;
  1612             cvt->len_mult *= 2;
  1613             cvt->len_ratio *= 2;
  1614         }
  1615         while ((src_channels * 2) <= dst_channels) {
  1616             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1617             cvt->len_mult *= 2;
  1618             src_channels *= 2;
  1619             cvt->len_ratio *= 2;
  1620         }
  1621         if ((src_channels == 6) && (dst_channels <= 2)) {
  1622             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1623             src_channels = 2;
  1624             cvt->len_ratio /= 3;
  1625         }
  1626         if ((src_channels == 6) && (dst_channels == 4)) {
  1627             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1628             src_channels = 4;
  1629             cvt->len_ratio /= 2;
  1630         }
  1631         /* This assumes that 4 channel audio is in the format:
  1632            Left {front/back} + Right {front/back}
  1633            so converting to L/R stereo works properly.
  1634          */
  1635         while (((src_channels % 2) == 0) &&
  1636                ((src_channels / 2) >= dst_channels)) {
  1637             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1638             src_channels /= 2;
  1639             cvt->len_ratio /= 2;
  1640         }
  1641         if (src_channels != dst_channels) {
  1642             /* Uh oh.. */ ;
  1643         }
  1644     }
  1645 
  1646     /* Do rate conversion */
  1647     cvt->rate_incr = 0.0;
  1648     if ((src_rate / 100) != (dst_rate / 100)) {
  1649         Uint32 hi_rate, lo_rate;
  1650         int len_mult;
  1651         double len_ratio;
  1652         SDL_AudioFilter rate_cvt = NULL;
  1653 
  1654         if (src_rate > dst_rate) {
  1655             hi_rate = src_rate;
  1656             lo_rate = dst_rate;
  1657             switch (src_channels) {
  1658             case 1:
  1659                 rate_cvt = SDL_RateDIV2;
  1660                 break;
  1661             case 2:
  1662                 rate_cvt = SDL_RateDIV2_c2;
  1663                 break;
  1664             case 4:
  1665                 rate_cvt = SDL_RateDIV2_c4;
  1666                 break;
  1667             case 6:
  1668                 rate_cvt = SDL_RateDIV2_c6;
  1669                 break;
  1670             default:
  1671                 return -1;
  1672             }
  1673             len_mult = 1;
  1674             len_ratio = 0.5;
  1675         } else {
  1676             hi_rate = dst_rate;
  1677             lo_rate = src_rate;
  1678             switch (src_channels) {
  1679             case 1:
  1680                 rate_cvt = SDL_RateMUL2;
  1681                 break;
  1682             case 2:
  1683                 rate_cvt = SDL_RateMUL2_c2;
  1684                 break;
  1685             case 4:
  1686                 rate_cvt = SDL_RateMUL2_c4;
  1687                 break;
  1688             case 6:
  1689                 rate_cvt = SDL_RateMUL2_c6;
  1690                 break;
  1691             default:
  1692                 return -1;
  1693             }
  1694             len_mult = 2;
  1695             len_ratio = 2.0;
  1696         }
  1697         /* If hi_rate = lo_rate*2^x then conversion is easy */
  1698         while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1699             cvt->filters[cvt->filter_index++] = rate_cvt;
  1700             cvt->len_mult *= len_mult;
  1701             lo_rate *= 2;
  1702             cvt->len_ratio *= len_ratio;
  1703         }
  1704         /* We may need a slow conversion here to finish up */
  1705         if ((lo_rate / 100) != (hi_rate / 100)) {
  1706 #if 1
  1707             /* The problem with this is that if the input buffer is
  1708                say 1K, and the conversion rate is say 1.1, then the
  1709                output buffer is 1.1K, which may not be an acceptable
  1710                buffer size for the audio driver (not a power of 2)
  1711              */
  1712             /* For now, punt and hope the rate distortion isn't great.
  1713              */
  1714 #else
  1715             if (src_rate < dst_rate) {
  1716                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1717                 cvt->len_mult *= 2;
  1718                 cvt->len_ratio /= cvt->rate_incr;
  1719             } else {
  1720                 cvt->rate_incr = (double) hi_rate / lo_rate;
  1721                 cvt->len_ratio *= cvt->rate_incr;
  1722             }
  1723             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1724 #endif
  1725         }
  1726     }
  1727 
  1728     /* Set up the filter information */
  1729     if (cvt->filter_index != 0) {
  1730         cvt->needed = 1;
  1731         cvt->src_format = src_fmt;
  1732         cvt->dst_format = dst_fmt;
  1733         cvt->len = 0;
  1734         cvt->buf = NULL;
  1735         cvt->filters[cvt->filter_index] = NULL;
  1736     }
  1737     return (cvt->needed);
  1738 }
  1739 
  1740 /* vi: set ts=4 sw=4 expandtab: */