src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 01 Sep 2008 16:04:20 +0000
changeset 2738 79c1bd651f04
parent 2728 2768bd7281e0
child 2760 02aa80d7905f
permissions -rw-r--r--
Fixed a bunch of compile warnings on Mac OS X
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #define _USE_MATH_DEFINES
    25 #include <math.h>
    26 
    27 /* Functions for audio drivers to perform runtime conversion of audio format */
    28 
    29 #include "SDL_audio.h"
    30 #include "SDL_audio_c.h"
    31 
    32 //#define DEBUG_CONVERT
    33 
    34 /* These are fractional multiplication routines. That is, their inputs
    35    are two numbers in the range [-1, 1) and the result falls in that
    36    same range. The output is the same size as the inputs, i.e.
    37    32-bit x 32-bit = 32-bit.
    38  */
    39 
    40 /* We hope here that the right shift includes sign extension */
    41 #ifdef SDL_HAS_64BIT_Type
    42 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    43 #else
    44 /* If we don't have the 64-bit type, do something more complicated. See http://www.8052.com/mul16.phtml or http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html */
    45 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    46 #endif
    47 #define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
    48 #define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
    49 /* This macro just makes the floating point filtering code not have to be a special case. */
    50 #define SDL_FloatMpy(a, b) (a * b)
    51 
    52 /* These macros take floating point numbers in the range [-1.0f, 1.0f) and
    53    represent them as fixed-point numbers in that same range. There's no
    54    checking that the floating point argument is inside the appropriate range.
    55  */
    56 
    57 #define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
    58 #define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
    59 #define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
    60 #define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
    61 #define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
    62 #define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
    63 
    64 /* Effectively mix right and left channels into a single channel */
    65 static void SDLCALL
    66 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    67 {
    68     int i;
    69     Sint32 sample;
    70 
    71 #ifdef DEBUG_CONVERT
    72     fprintf(stderr, "Converting to mono\n");
    73 #endif
    74     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
    75     case AUDIO_U8:
    76         {
    77             Uint8 *src, *dst;
    78 
    79             src = cvt->buf;
    80             dst = cvt->buf;
    81             for (i = cvt->len_cvt / 2; i; --i) {
    82                 sample = src[0] + src[1];
    83                 *dst = (Uint8) (sample / 2);
    84                 src += 2;
    85                 dst += 1;
    86             }
    87         }
    88         break;
    89 
    90     case AUDIO_S8:
    91         {
    92             Sint8 *src, *dst;
    93 
    94             src = (Sint8 *) cvt->buf;
    95             dst = (Sint8 *) cvt->buf;
    96             for (i = cvt->len_cvt / 2; i; --i) {
    97                 sample = src[0] + src[1];
    98                 *dst = (Sint8) (sample / 2);
    99                 src += 2;
   100                 dst += 1;
   101             }
   102         }
   103         break;
   104 
   105     case AUDIO_U16:
   106         {
   107             Uint8 *src, *dst;
   108 
   109             src = cvt->buf;
   110             dst = cvt->buf;
   111             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   112                 for (i = cvt->len_cvt / 4; i; --i) {
   113                     sample = (Uint16) ((src[0] << 8) | src[1]) +
   114                         (Uint16) ((src[2] << 8) | src[3]);
   115                     sample /= 2;
   116                     dst[1] = (sample & 0xFF);
   117                     sample >>= 8;
   118                     dst[0] = (sample & 0xFF);
   119                     src += 4;
   120                     dst += 2;
   121                 }
   122             } else {
   123                 for (i = cvt->len_cvt / 4; i; --i) {
   124                     sample = (Uint16) ((src[1] << 8) | src[0]) +
   125                         (Uint16) ((src[3] << 8) | src[2]);
   126                     sample /= 2;
   127                     dst[0] = (sample & 0xFF);
   128                     sample >>= 8;
   129                     dst[1] = (sample & 0xFF);
   130                     src += 4;
   131                     dst += 2;
   132                 }
   133             }
   134         }
   135         break;
   136 
   137     case AUDIO_S16:
   138         {
   139             Uint8 *src, *dst;
   140 
   141             src = cvt->buf;
   142             dst = cvt->buf;
   143             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   144                 for (i = cvt->len_cvt / 4; i; --i) {
   145                     sample = (Sint16) ((src[0] << 8) | src[1]) +
   146                         (Sint16) ((src[2] << 8) | src[3]);
   147                     sample /= 2;
   148                     dst[1] = (sample & 0xFF);
   149                     sample >>= 8;
   150                     dst[0] = (sample & 0xFF);
   151                     src += 4;
   152                     dst += 2;
   153                 }
   154             } else {
   155                 for (i = cvt->len_cvt / 4; i; --i) {
   156                     sample = (Sint16) ((src[1] << 8) | src[0]) +
   157                         (Sint16) ((src[3] << 8) | src[2]);
   158                     sample /= 2;
   159                     dst[0] = (sample & 0xFF);
   160                     sample >>= 8;
   161                     dst[1] = (sample & 0xFF);
   162                     src += 4;
   163                     dst += 2;
   164                 }
   165             }
   166         }
   167         break;
   168 
   169     case AUDIO_S32:
   170         {
   171             const Uint32 *src = (const Uint32 *) cvt->buf;
   172             Uint32 *dst = (Uint32 *) cvt->buf;
   173             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   174                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   175                     const Sint64 added =
   176                         (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
   177                          ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
   178                     *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
   179                 }
   180             } else {
   181                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   182                     const Sint64 added =
   183                         (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
   184                          ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
   185                     *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
   186                 }
   187             }
   188         }
   189         break;
   190 
   191     case AUDIO_F32:
   192         {
   193             const float *src = (const float *) cvt->buf;
   194             float *dst = (float *) cvt->buf;
   195             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   196                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   197                     const float src1 = SDL_SwapFloatBE(src[0]);
   198                     const float src2 = SDL_SwapFloatBE(src[1]);
   199                     const double added = ((double) src1) + ((double) src2);
   200                     const float halved = (float) (added * 0.5);
   201                     *(dst++) = SDL_SwapFloatBE(halved);
   202                 }
   203             } else {
   204                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
   205                     const float src1 = SDL_SwapFloatLE(src[0]);
   206                     const float src2 = SDL_SwapFloatLE(src[1]);
   207                     const double added = ((double) src1) + ((double) src2);
   208                     const float halved = (float) (added * 0.5);
   209                     *(dst++) = SDL_SwapFloatLE(halved);
   210                 }
   211             }
   212         }
   213         break;
   214     }
   215 
   216     cvt->len_cvt /= 2;
   217     if (cvt->filters[++cvt->filter_index]) {
   218         cvt->filters[cvt->filter_index] (cvt, format);
   219     }
   220 }
   221 
   222 
   223 /* Discard top 4 channels */
   224 static void SDLCALL
   225 SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   226 {
   227     int i;
   228 
   229 #ifdef DEBUG_CONVERT
   230     fprintf(stderr, "Converting down from 6 channels to stereo\n");
   231 #endif
   232 
   233 #define strip_chans_6_to_2(type) \
   234     { \
   235         const type *src = (const type *) cvt->buf; \
   236         type *dst = (type *) cvt->buf; \
   237         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   238             dst[0] = src[0]; \
   239             dst[1] = src[1]; \
   240             src += 6; \
   241             dst += 2; \
   242         } \
   243     }
   244 
   245     /* this function only cares about typesize, and data as a block of bits. */
   246     switch (SDL_AUDIO_BITSIZE(format)) {
   247     case 8:
   248         strip_chans_6_to_2(Uint8);
   249         break;
   250     case 16:
   251         strip_chans_6_to_2(Uint16);
   252         break;
   253     case 32:
   254         strip_chans_6_to_2(Uint32);
   255         break;
   256     }
   257 
   258 #undef strip_chans_6_to_2
   259 
   260     cvt->len_cvt /= 3;
   261     if (cvt->filters[++cvt->filter_index]) {
   262         cvt->filters[cvt->filter_index] (cvt, format);
   263     }
   264 }
   265 
   266 
   267 /* Discard top 2 channels of 6 */
   268 static void SDLCALL
   269 SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   270 {
   271     int i;
   272 
   273 #ifdef DEBUG_CONVERT
   274     fprintf(stderr, "Converting 6 down to quad\n");
   275 #endif
   276 
   277 #define strip_chans_6_to_4(type) \
   278     { \
   279         const type *src = (const type *) cvt->buf; \
   280         type *dst = (type *) cvt->buf; \
   281         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   282             dst[0] = src[0]; \
   283             dst[1] = src[1]; \
   284             dst[2] = src[2]; \
   285             dst[3] = src[3]; \
   286             src += 6; \
   287             dst += 4; \
   288         } \
   289     }
   290 
   291     /* this function only cares about typesize, and data as a block of bits. */
   292     switch (SDL_AUDIO_BITSIZE(format)) {
   293     case 8:
   294         strip_chans_6_to_4(Uint8);
   295         break;
   296     case 16:
   297         strip_chans_6_to_4(Uint16);
   298         break;
   299     case 32:
   300         strip_chans_6_to_4(Uint32);
   301         break;
   302     }
   303 
   304 #undef strip_chans_6_to_4
   305 
   306     cvt->len_cvt /= 6;
   307     cvt->len_cvt *= 4;
   308     if (cvt->filters[++cvt->filter_index]) {
   309         cvt->filters[cvt->filter_index] (cvt, format);
   310     }
   311 }
   312 
   313 /* Duplicate a mono channel to both stereo channels */
   314 static void SDLCALL
   315 SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   316 {
   317     int i;
   318 
   319 #ifdef DEBUG_CONVERT
   320     fprintf(stderr, "Converting to stereo\n");
   321 #endif
   322 
   323 #define dup_chans_1_to_2(type) \
   324     { \
   325         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   326         type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
   327         for (i = cvt->len_cvt / 2; i; --i, --src) { \
   328             const type val = *src; \
   329             dst -= 2; \
   330             dst[0] = dst[1] = val; \
   331         } \
   332     }
   333 
   334     /* this function only cares about typesize, and data as a block of bits. */
   335     switch (SDL_AUDIO_BITSIZE(format)) {
   336     case 8:
   337         dup_chans_1_to_2(Uint8);
   338         break;
   339     case 16:
   340         dup_chans_1_to_2(Uint16);
   341         break;
   342     case 32:
   343         dup_chans_1_to_2(Uint32);
   344         break;
   345     }
   346 
   347 #undef dup_chans_1_to_2
   348 
   349     cvt->len_cvt *= 2;
   350     if (cvt->filters[++cvt->filter_index]) {
   351         cvt->filters[cvt->filter_index] (cvt, format);
   352     }
   353 }
   354 
   355 
   356 /* Duplicate a stereo channel to a pseudo-5.1 stream */
   357 static void SDLCALL
   358 SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   359 {
   360     int i;
   361 
   362 #ifdef DEBUG_CONVERT
   363     fprintf(stderr, "Converting stereo to surround\n");
   364 #endif
   365 
   366     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   367     case AUDIO_U8:
   368         {
   369             Uint8 *src, *dst, lf, rf, ce;
   370 
   371             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   372             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
   373             for (i = cvt->len_cvt; i; --i) {
   374                 dst -= 6;
   375                 src -= 2;
   376                 lf = src[0];
   377                 rf = src[1];
   378                 ce = (lf / 2) + (rf / 2);
   379                 dst[0] = lf;
   380                 dst[1] = rf;
   381                 dst[2] = lf - ce;
   382                 dst[3] = rf - ce;
   383                 dst[4] = ce;
   384                 dst[5] = ce;
   385             }
   386         }
   387         break;
   388 
   389     case AUDIO_S8:
   390         {
   391             Sint8 *src, *dst, lf, rf, ce;
   392 
   393             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   394             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
   395             for (i = cvt->len_cvt; i; --i) {
   396                 dst -= 6;
   397                 src -= 2;
   398                 lf = src[0];
   399                 rf = src[1];
   400                 ce = (lf / 2) + (rf / 2);
   401                 dst[0] = lf;
   402                 dst[1] = rf;
   403                 dst[2] = lf - ce;
   404                 dst[3] = rf - ce;
   405                 dst[4] = ce;
   406                 dst[5] = ce;
   407             }
   408         }
   409         break;
   410 
   411     case AUDIO_U16:
   412         {
   413             Uint8 *src, *dst;
   414             Uint16 lf, rf, ce, lr, rr;
   415 
   416             src = cvt->buf + cvt->len_cvt;
   417             dst = cvt->buf + cvt->len_cvt * 3;
   418 
   419             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   420                 for (i = cvt->len_cvt / 4; i; --i) {
   421                     dst -= 12;
   422                     src -= 4;
   423                     lf = (Uint16) ((src[0] << 8) | src[1]);
   424                     rf = (Uint16) ((src[2] << 8) | src[3]);
   425                     ce = (lf / 2) + (rf / 2);
   426                     rr = lf - ce;
   427                     lr = rf - ce;
   428                     dst[1] = (lf & 0xFF);
   429                     dst[0] = ((lf >> 8) & 0xFF);
   430                     dst[3] = (rf & 0xFF);
   431                     dst[2] = ((rf >> 8) & 0xFF);
   432 
   433                     dst[1 + 4] = (lr & 0xFF);
   434                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   435                     dst[3 + 4] = (rr & 0xFF);
   436                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   437 
   438                     dst[1 + 8] = (ce & 0xFF);
   439                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   440                     dst[3 + 8] = (ce & 0xFF);
   441                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   442                 }
   443             } else {
   444                 for (i = cvt->len_cvt / 4; i; --i) {
   445                     dst -= 12;
   446                     src -= 4;
   447                     lf = (Uint16) ((src[1] << 8) | src[0]);
   448                     rf = (Uint16) ((src[3] << 8) | src[2]);
   449                     ce = (lf / 2) + (rf / 2);
   450                     rr = lf - ce;
   451                     lr = rf - ce;
   452                     dst[0] = (lf & 0xFF);
   453                     dst[1] = ((lf >> 8) & 0xFF);
   454                     dst[2] = (rf & 0xFF);
   455                     dst[3] = ((rf >> 8) & 0xFF);
   456 
   457                     dst[0 + 4] = (lr & 0xFF);
   458                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   459                     dst[2 + 4] = (rr & 0xFF);
   460                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   461 
   462                     dst[0 + 8] = (ce & 0xFF);
   463                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   464                     dst[2 + 8] = (ce & 0xFF);
   465                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   466                 }
   467             }
   468         }
   469         break;
   470 
   471     case AUDIO_S16:
   472         {
   473             Uint8 *src, *dst;
   474             Sint16 lf, rf, ce, lr, rr;
   475 
   476             src = cvt->buf + cvt->len_cvt;
   477             dst = cvt->buf + cvt->len_cvt * 3;
   478 
   479             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   480                 for (i = cvt->len_cvt / 4; i; --i) {
   481                     dst -= 12;
   482                     src -= 4;
   483                     lf = (Sint16) ((src[0] << 8) | src[1]);
   484                     rf = (Sint16) ((src[2] << 8) | src[3]);
   485                     ce = (lf / 2) + (rf / 2);
   486                     rr = lf - ce;
   487                     lr = rf - ce;
   488                     dst[1] = (lf & 0xFF);
   489                     dst[0] = ((lf >> 8) & 0xFF);
   490                     dst[3] = (rf & 0xFF);
   491                     dst[2] = ((rf >> 8) & 0xFF);
   492 
   493                     dst[1 + 4] = (lr & 0xFF);
   494                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   495                     dst[3 + 4] = (rr & 0xFF);
   496                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   497 
   498                     dst[1 + 8] = (ce & 0xFF);
   499                     dst[0 + 8] = ((ce >> 8) & 0xFF);
   500                     dst[3 + 8] = (ce & 0xFF);
   501                     dst[2 + 8] = ((ce >> 8) & 0xFF);
   502                 }
   503             } else {
   504                 for (i = cvt->len_cvt / 4; i; --i) {
   505                     dst -= 12;
   506                     src -= 4;
   507                     lf = (Sint16) ((src[1] << 8) | src[0]);
   508                     rf = (Sint16) ((src[3] << 8) | src[2]);
   509                     ce = (lf / 2) + (rf / 2);
   510                     rr = lf - ce;
   511                     lr = rf - ce;
   512                     dst[0] = (lf & 0xFF);
   513                     dst[1] = ((lf >> 8) & 0xFF);
   514                     dst[2] = (rf & 0xFF);
   515                     dst[3] = ((rf >> 8) & 0xFF);
   516 
   517                     dst[0 + 4] = (lr & 0xFF);
   518                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   519                     dst[2 + 4] = (rr & 0xFF);
   520                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   521 
   522                     dst[0 + 8] = (ce & 0xFF);
   523                     dst[1 + 8] = ((ce >> 8) & 0xFF);
   524                     dst[2 + 8] = (ce & 0xFF);
   525                     dst[3 + 8] = ((ce >> 8) & 0xFF);
   526                 }
   527             }
   528         }
   529         break;
   530 
   531     case AUDIO_S32:
   532         {
   533             Sint32 lf, rf, ce;
   534             const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
   535             Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
   536 
   537             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   538                 for (i = cvt->len_cvt / 8; i; --i) {
   539                     dst -= 6;
   540                     src -= 2;
   541                     lf = (Sint32) SDL_SwapBE32(src[0]);
   542                     rf = (Sint32) SDL_SwapBE32(src[1]);
   543                     ce = (lf / 2) + (rf / 2);
   544                     dst[0] = SDL_SwapBE32((Uint32) lf);
   545                     dst[1] = SDL_SwapBE32((Uint32) rf);
   546                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   547                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   548                     dst[4] = SDL_SwapBE32((Uint32) ce);
   549                     dst[5] = SDL_SwapBE32((Uint32) ce);
   550                 }
   551             } else {
   552                 for (i = cvt->len_cvt / 8; i; --i) {
   553                     dst -= 6;
   554                     src -= 2;
   555                     lf = (Sint32) SDL_SwapLE32(src[0]);
   556                     rf = (Sint32) SDL_SwapLE32(src[1]);
   557                     ce = (lf / 2) + (rf / 2);
   558                     dst[0] = src[0];
   559                     dst[1] = src[1];
   560                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   561                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   562                     dst[4] = SDL_SwapLE32((Uint32) ce);
   563                     dst[5] = SDL_SwapLE32((Uint32) ce);
   564                 }
   565             }
   566         }
   567         break;
   568 
   569     case AUDIO_F32:
   570         {
   571             float lf, rf, ce;
   572             const float *src = (const float *) cvt->buf + cvt->len_cvt;
   573             float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
   574 
   575             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   576                 for (i = cvt->len_cvt / 8; i; --i) {
   577                     dst -= 6;
   578                     src -= 2;
   579                     lf = SDL_SwapFloatBE(src[0]);
   580                     rf = SDL_SwapFloatBE(src[1]);
   581                     ce = (lf * 0.5f) + (rf * 0.5f);
   582                     dst[0] = src[0];
   583                     dst[1] = src[1];
   584                     dst[2] = SDL_SwapFloatBE(lf - ce);
   585                     dst[3] = SDL_SwapFloatBE(rf - ce);
   586                     dst[4] = dst[5] = SDL_SwapFloatBE(ce);
   587                 }
   588             } else {
   589                 for (i = cvt->len_cvt / 8; i; --i) {
   590                     dst -= 6;
   591                     src -= 2;
   592                     lf = SDL_SwapFloatLE(src[0]);
   593                     rf = SDL_SwapFloatLE(src[1]);
   594                     ce = (lf * 0.5f) + (rf * 0.5f);
   595                     dst[0] = src[0];
   596                     dst[1] = src[1];
   597                     dst[2] = SDL_SwapFloatLE(lf - ce);
   598                     dst[3] = SDL_SwapFloatLE(rf - ce);
   599                     dst[4] = dst[5] = SDL_SwapFloatLE(ce);
   600                 }
   601             }
   602         }
   603         break;
   604 
   605     }
   606     cvt->len_cvt *= 3;
   607     if (cvt->filters[++cvt->filter_index]) {
   608         cvt->filters[cvt->filter_index] (cvt, format);
   609     }
   610 }
   611 
   612 
   613 /* Duplicate a stereo channel to a pseudo-4.0 stream */
   614 static void SDLCALL
   615 SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   616 {
   617     int i;
   618 
   619 #ifdef DEBUG_CONVERT
   620     fprintf(stderr, "Converting stereo to quad\n");
   621 #endif
   622 
   623     switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
   624     case AUDIO_U8:
   625         {
   626             Uint8 *src, *dst, lf, rf, ce;
   627 
   628             src = (Uint8 *) (cvt->buf + cvt->len_cvt);
   629             dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
   630             for (i = cvt->len_cvt; i; --i) {
   631                 dst -= 4;
   632                 src -= 2;
   633                 lf = src[0];
   634                 rf = src[1];
   635                 ce = (lf / 2) + (rf / 2);
   636                 dst[0] = lf;
   637                 dst[1] = rf;
   638                 dst[2] = lf - ce;
   639                 dst[3] = rf - ce;
   640             }
   641         }
   642         break;
   643 
   644     case AUDIO_S8:
   645         {
   646             Sint8 *src, *dst, lf, rf, ce;
   647 
   648             src = (Sint8 *) cvt->buf + cvt->len_cvt;
   649             dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
   650             for (i = cvt->len_cvt; i; --i) {
   651                 dst -= 4;
   652                 src -= 2;
   653                 lf = src[0];
   654                 rf = src[1];
   655                 ce = (lf / 2) + (rf / 2);
   656                 dst[0] = lf;
   657                 dst[1] = rf;
   658                 dst[2] = lf - ce;
   659                 dst[3] = rf - ce;
   660             }
   661         }
   662         break;
   663 
   664     case AUDIO_U16:
   665         {
   666             Uint8 *src, *dst;
   667             Uint16 lf, rf, ce, lr, rr;
   668 
   669             src = cvt->buf + cvt->len_cvt;
   670             dst = cvt->buf + cvt->len_cvt * 2;
   671 
   672             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   673                 for (i = cvt->len_cvt / 4; i; --i) {
   674                     dst -= 8;
   675                     src -= 4;
   676                     lf = (Uint16) ((src[0] << 8) | src[1]);
   677                     rf = (Uint16) ((src[2] << 8) | src[3]);
   678                     ce = (lf / 2) + (rf / 2);
   679                     rr = lf - ce;
   680                     lr = rf - ce;
   681                     dst[1] = (lf & 0xFF);
   682                     dst[0] = ((lf >> 8) & 0xFF);
   683                     dst[3] = (rf & 0xFF);
   684                     dst[2] = ((rf >> 8) & 0xFF);
   685 
   686                     dst[1 + 4] = (lr & 0xFF);
   687                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   688                     dst[3 + 4] = (rr & 0xFF);
   689                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   690                 }
   691             } else {
   692                 for (i = cvt->len_cvt / 4; i; --i) {
   693                     dst -= 8;
   694                     src -= 4;
   695                     lf = (Uint16) ((src[1] << 8) | src[0]);
   696                     rf = (Uint16) ((src[3] << 8) | src[2]);
   697                     ce = (lf / 2) + (rf / 2);
   698                     rr = lf - ce;
   699                     lr = rf - ce;
   700                     dst[0] = (lf & 0xFF);
   701                     dst[1] = ((lf >> 8) & 0xFF);
   702                     dst[2] = (rf & 0xFF);
   703                     dst[3] = ((rf >> 8) & 0xFF);
   704 
   705                     dst[0 + 4] = (lr & 0xFF);
   706                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   707                     dst[2 + 4] = (rr & 0xFF);
   708                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   709                 }
   710             }
   711         }
   712         break;
   713 
   714     case AUDIO_S16:
   715         {
   716             Uint8 *src, *dst;
   717             Sint16 lf, rf, ce, lr, rr;
   718 
   719             src = cvt->buf + cvt->len_cvt;
   720             dst = cvt->buf + cvt->len_cvt * 2;
   721 
   722             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   723                 for (i = cvt->len_cvt / 4; i; --i) {
   724                     dst -= 8;
   725                     src -= 4;
   726                     lf = (Sint16) ((src[0] << 8) | src[1]);
   727                     rf = (Sint16) ((src[2] << 8) | src[3]);
   728                     ce = (lf / 2) + (rf / 2);
   729                     rr = lf - ce;
   730                     lr = rf - ce;
   731                     dst[1] = (lf & 0xFF);
   732                     dst[0] = ((lf >> 8) & 0xFF);
   733                     dst[3] = (rf & 0xFF);
   734                     dst[2] = ((rf >> 8) & 0xFF);
   735 
   736                     dst[1 + 4] = (lr & 0xFF);
   737                     dst[0 + 4] = ((lr >> 8) & 0xFF);
   738                     dst[3 + 4] = (rr & 0xFF);
   739                     dst[2 + 4] = ((rr >> 8) & 0xFF);
   740                 }
   741             } else {
   742                 for (i = cvt->len_cvt / 4; i; --i) {
   743                     dst -= 8;
   744                     src -= 4;
   745                     lf = (Sint16) ((src[1] << 8) | src[0]);
   746                     rf = (Sint16) ((src[3] << 8) | src[2]);
   747                     ce = (lf / 2) + (rf / 2);
   748                     rr = lf - ce;
   749                     lr = rf - ce;
   750                     dst[0] = (lf & 0xFF);
   751                     dst[1] = ((lf >> 8) & 0xFF);
   752                     dst[2] = (rf & 0xFF);
   753                     dst[3] = ((rf >> 8) & 0xFF);
   754 
   755                     dst[0 + 4] = (lr & 0xFF);
   756                     dst[1 + 4] = ((lr >> 8) & 0xFF);
   757                     dst[2 + 4] = (rr & 0xFF);
   758                     dst[3 + 4] = ((rr >> 8) & 0xFF);
   759                 }
   760             }
   761         }
   762         break;
   763 
   764     case AUDIO_S32:
   765         {
   766             const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
   767             Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
   768             Sint32 lf, rf, ce;
   769 
   770             if (SDL_AUDIO_ISBIGENDIAN(format)) {
   771                 for (i = cvt->len_cvt / 8; i; --i) {
   772                     dst -= 4;
   773                     src -= 2;
   774                     lf = (Sint32) SDL_SwapBE32(src[0]);
   775                     rf = (Sint32) SDL_SwapBE32(src[1]);
   776                     ce = (lf / 2) + (rf / 2);
   777                     dst[0] = src[0];
   778                     dst[1] = src[1];
   779                     dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
   780                     dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
   781                 }
   782             } else {
   783                 for (i = cvt->len_cvt / 8; i; --i) {
   784                     dst -= 4;
   785                     src -= 2;
   786                     lf = (Sint32) SDL_SwapLE32(src[0]);
   787                     rf = (Sint32) SDL_SwapLE32(src[1]);
   788                     ce = (lf / 2) + (rf / 2);
   789                     dst[0] = src[0];
   790                     dst[1] = src[1];
   791                     dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
   792                     dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
   793                 }
   794             }
   795         }
   796         break;
   797     }
   798     cvt->len_cvt *= 2;
   799     if (cvt->filters[++cvt->filter_index]) {
   800         cvt->filters[cvt->filter_index] (cvt, format);
   801     }
   802 }
   803 
   804 /* Convert rate up by multiple of 2 */
   805 static void SDLCALL
   806 SDL_RateMUL2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   807 {
   808     int i;
   809 
   810 #ifdef DEBUG_CONVERT
   811     fprintf(stderr, "Converting audio rate * 2 (mono)\n");
   812 #endif
   813 
   814 #define mul2_mono(type) { \
   815         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   816         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   817         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
   818             src--; \
   819             dst[-1] = dst[-2] = src[0]; \
   820             dst -= 2; \
   821         } \
   822     }
   823 
   824     switch (SDL_AUDIO_BITSIZE(format)) {
   825     case 8:
   826         mul2_mono(Uint8);
   827         break;
   828     case 16:
   829         mul2_mono(Uint16);
   830         break;
   831     case 32:
   832         mul2_mono(Uint32);
   833         break;
   834     }
   835 
   836 #undef mul2_mono
   837 
   838     cvt->len_cvt *= 2;
   839     if (cvt->filters[++cvt->filter_index]) {
   840         cvt->filters[cvt->filter_index] (cvt, format);
   841     }
   842 }
   843 
   844 
   845 /* Convert rate up by multiple of 2, for stereo */
   846 static void SDLCALL
   847 SDL_RateMUL2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   848 {
   849     int i;
   850 
   851 #ifdef DEBUG_CONVERT
   852     fprintf(stderr, "Converting audio rate * 2 (stereo)\n");
   853 #endif
   854 
   855 #define mul2_stereo(type) { \
   856         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   857         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   858         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   859             const type r = src[-1]; \
   860             const type l = src[-2]; \
   861             src -= 2; \
   862             dst[-1] = r; \
   863             dst[-2] = l; \
   864             dst[-3] = r; \
   865             dst[-4] = l; \
   866             dst -= 4; \
   867         } \
   868     }
   869 
   870     switch (SDL_AUDIO_BITSIZE(format)) {
   871     case 8:
   872         mul2_stereo(Uint8);
   873         break;
   874     case 16:
   875         mul2_stereo(Uint16);
   876         break;
   877     case 32:
   878         mul2_stereo(Uint32);
   879         break;
   880     }
   881 
   882 #undef mul2_stereo
   883 
   884     cvt->len_cvt *= 2;
   885     if (cvt->filters[++cvt->filter_index]) {
   886         cvt->filters[cvt->filter_index] (cvt, format);
   887     }
   888 }
   889 
   890 /* Convert rate up by multiple of 2, for quad */
   891 static void SDLCALL
   892 SDL_RateMUL2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   893 {
   894     int i;
   895 
   896 #ifdef DEBUG_CONVERT
   897     fprintf(stderr, "Converting audio rate * 2 (quad)\n");
   898 #endif
   899 
   900 #define mul2_quad(type) { \
   901         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   902         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   903         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
   904             const type c1 = src[-1]; \
   905             const type c2 = src[-2]; \
   906             const type c3 = src[-3]; \
   907             const type c4 = src[-4]; \
   908             src -= 4; \
   909             dst[-1] = c1; \
   910             dst[-2] = c2; \
   911             dst[-3] = c3; \
   912             dst[-4] = c4; \
   913             dst[-5] = c1; \
   914             dst[-6] = c2; \
   915             dst[-7] = c3; \
   916             dst[-8] = c4; \
   917             dst -= 8; \
   918         } \
   919     }
   920 
   921     switch (SDL_AUDIO_BITSIZE(format)) {
   922     case 8:
   923         mul2_quad(Uint8);
   924         break;
   925     case 16:
   926         mul2_quad(Uint16);
   927         break;
   928     case 32:
   929         mul2_quad(Uint32);
   930         break;
   931     }
   932 
   933 #undef mul2_quad
   934 
   935     cvt->len_cvt *= 2;
   936     if (cvt->filters[++cvt->filter_index]) {
   937         cvt->filters[cvt->filter_index] (cvt, format);
   938     }
   939 }
   940 
   941 
   942 /* Convert rate up by multiple of 2, for 5.1 */
   943 static void SDLCALL
   944 SDL_RateMUL2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   945 {
   946     int i;
   947 
   948 #ifdef DEBUG_CONVERT
   949     fprintf(stderr, "Converting audio rate * 2 (six channels)\n");
   950 #endif
   951 
   952 #define mul2_chansix(type) { \
   953         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   954         type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   955         for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   956             const type c1 = src[-1]; \
   957             const type c2 = src[-2]; \
   958             const type c3 = src[-3]; \
   959             const type c4 = src[-4]; \
   960             const type c5 = src[-5]; \
   961             const type c6 = src[-6]; \
   962             src -= 6; \
   963             dst[-1] = c1; \
   964             dst[-2] = c2; \
   965             dst[-3] = c3; \
   966             dst[-4] = c4; \
   967             dst[-5] = c5; \
   968             dst[-6] = c6; \
   969             dst[-7] = c1; \
   970             dst[-8] = c2; \
   971             dst[-9] = c3; \
   972             dst[-10] = c4; \
   973             dst[-11] = c5; \
   974             dst[-12] = c6; \
   975             dst -= 12; \
   976         } \
   977     }
   978 
   979     switch (SDL_AUDIO_BITSIZE(format)) {
   980     case 8:
   981         mul2_chansix(Uint8);
   982         break;
   983     case 16:
   984         mul2_chansix(Uint16);
   985         break;
   986     case 32:
   987         mul2_chansix(Uint32);
   988         break;
   989     }
   990 
   991 #undef mul2_chansix
   992 
   993     cvt->len_cvt *= 2;
   994     if (cvt->filters[++cvt->filter_index]) {
   995         cvt->filters[cvt->filter_index] (cvt, format);
   996     }
   997 }
   998 
   999 /* Convert rate down by multiple of 2 */
  1000 static void SDLCALL
  1001 SDL_RateDIV2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1002 {
  1003     int i;
  1004 
  1005 #ifdef DEBUG_CONVERT
  1006     fprintf(stderr, "Converting audio rate / 2 (mono)\n");
  1007 #endif
  1008 
  1009 #define div2_mono(type) { \
  1010         const type *src = (const type *) cvt->buf; \
  1011         type *dst = (type *) cvt->buf; \
  1012         for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
  1013             dst[0] = src[0]; \
  1014             src += 2; \
  1015             dst++; \
  1016         } \
  1017     }
  1018 
  1019     switch (SDL_AUDIO_BITSIZE(format)) {
  1020     case 8:
  1021         div2_mono(Uint8);
  1022         break;
  1023     case 16:
  1024         div2_mono(Uint16);
  1025         break;
  1026     case 32:
  1027         div2_mono(Uint32);
  1028         break;
  1029     }
  1030 
  1031 #undef div2_mono
  1032 
  1033     cvt->len_cvt /= 2;
  1034     if (cvt->filters[++cvt->filter_index]) {
  1035         cvt->filters[cvt->filter_index] (cvt, format);
  1036     }
  1037 }
  1038 
  1039 
  1040 /* Convert rate down by multiple of 2, for stereo */
  1041 static void SDLCALL
  1042 SDL_RateDIV2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1043 {
  1044     int i;
  1045 
  1046 #ifdef DEBUG_CONVERT
  1047     fprintf(stderr, "Converting audio rate / 2 (stereo)\n");
  1048 #endif
  1049 
  1050 #define div2_stereo(type) { \
  1051         const type *src = (const type *) cvt->buf; \
  1052         type *dst = (type *) cvt->buf; \
  1053         for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
  1054             dst[0] = src[0]; \
  1055             dst[1] = src[1]; \
  1056             src += 4; \
  1057             dst += 2; \
  1058         } \
  1059     }
  1060 
  1061     switch (SDL_AUDIO_BITSIZE(format)) {
  1062     case 8:
  1063         div2_stereo(Uint8);
  1064         break;
  1065     case 16:
  1066         div2_stereo(Uint16);
  1067         break;
  1068     case 32:
  1069         div2_stereo(Uint32);
  1070         break;
  1071     }
  1072 
  1073 #undef div2_stereo
  1074 
  1075     cvt->len_cvt /= 2;
  1076     if (cvt->filters[++cvt->filter_index]) {
  1077         cvt->filters[cvt->filter_index] (cvt, format);
  1078     }
  1079 }
  1080 
  1081 
  1082 /* Convert rate down by multiple of 2, for quad */
  1083 static void SDLCALL
  1084 SDL_RateDIV2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1085 {
  1086     int i;
  1087 
  1088 #ifdef DEBUG_CONVERT
  1089     fprintf(stderr, "Converting audio rate / 2 (quad)\n");
  1090 #endif
  1091 
  1092 #define div2_quad(type) { \
  1093         const type *src = (const type *) cvt->buf; \
  1094         type *dst = (type *) cvt->buf; \
  1095         for (i = cvt->len_cvt / (sizeof (type) * 8); i; --i) { \
  1096             dst[0] = src[0]; \
  1097             dst[1] = src[1]; \
  1098             dst[2] = src[2]; \
  1099             dst[3] = src[3]; \
  1100             src += 8; \
  1101             dst += 4; \
  1102         } \
  1103     }
  1104 
  1105     switch (SDL_AUDIO_BITSIZE(format)) {
  1106     case 8:
  1107         div2_quad(Uint8);
  1108         break;
  1109     case 16:
  1110         div2_quad(Uint16);
  1111         break;
  1112     case 32:
  1113         div2_quad(Uint32);
  1114         break;
  1115     }
  1116 
  1117 #undef div2_quad
  1118 
  1119     cvt->len_cvt /= 2;
  1120     if (cvt->filters[++cvt->filter_index]) {
  1121         cvt->filters[cvt->filter_index] (cvt, format);
  1122     }
  1123 }
  1124 
  1125 /* Convert rate down by multiple of 2, for 5.1 */
  1126 static void SDLCALL
  1127 SDL_RateDIV2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1128 {
  1129     int i;
  1130 
  1131 #ifdef DEBUG_CONVERT
  1132     fprintf(stderr, "Converting audio rate / 2 (six channels)\n");
  1133 #endif
  1134 
  1135 #define div2_chansix(type) { \
  1136         const type *src = (const type *) cvt->buf; \
  1137         type *dst = (type *) cvt->buf; \
  1138         for (i = cvt->len_cvt / (sizeof (type) * 12); i; --i) { \
  1139             dst[0] = src[0]; \
  1140             dst[1] = src[1]; \
  1141             dst[2] = src[2]; \
  1142             dst[3] = src[3]; \
  1143             dst[4] = src[4]; \
  1144             dst[5] = src[5]; \
  1145             src += 12; \
  1146             dst += 6; \
  1147         } \
  1148     }
  1149 
  1150     switch (SDL_AUDIO_BITSIZE(format)) {
  1151     case 8:
  1152         div2_chansix(Uint8);
  1153         break;
  1154     case 16:
  1155         div2_chansix(Uint16);
  1156         break;
  1157     case 32:
  1158         div2_chansix(Uint32);
  1159         break;
  1160     }
  1161 
  1162 #undef div_chansix
  1163 
  1164     cvt->len_cvt /= 2;
  1165     if (cvt->filters[++cvt->filter_index]) {
  1166         cvt->filters[cvt->filter_index] (cvt, format);
  1167     }
  1168 }
  1169 
  1170 /* Very slow rate conversion routine */
  1171 static void SDLCALL
  1172 SDL_RateSLOW(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1173 {
  1174     double ipos;
  1175     int i, clen;
  1176 
  1177 #ifdef DEBUG_CONVERT
  1178     fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
  1179 #endif
  1180     clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
  1181     if (cvt->rate_incr > 1.0) {
  1182         switch (SDL_AUDIO_BITSIZE(format)) {
  1183         case 8:
  1184             {
  1185                 Uint8 *output;
  1186 
  1187                 output = cvt->buf;
  1188                 ipos = 0.0;
  1189                 for (i = clen; i; --i) {
  1190                     *output = cvt->buf[(int) ipos];
  1191                     ipos += cvt->rate_incr;
  1192                     output += 1;
  1193                 }
  1194             }
  1195             break;
  1196 
  1197         case 16:
  1198             {
  1199                 Uint16 *output;
  1200 
  1201                 clen &= ~1;
  1202                 output = (Uint16 *) cvt->buf;
  1203                 ipos = 0.0;
  1204                 for (i = clen / 2; i; --i) {
  1205                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1206                     ipos += cvt->rate_incr;
  1207                     output += 1;
  1208                 }
  1209             }
  1210             break;
  1211 
  1212         case 32:
  1213             {
  1214                 /* !!! FIXME: need 32-bit converter here! */
  1215 #ifdef DEBUG_CONVERT
  1216                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1217 #endif
  1218             }
  1219         }
  1220     } else {
  1221         switch (SDL_AUDIO_BITSIZE(format)) {
  1222         case 8:
  1223             {
  1224                 Uint8 *output;
  1225 
  1226                 output = cvt->buf + clen;
  1227                 ipos = (double) cvt->len_cvt;
  1228                 for (i = clen; i; --i) {
  1229                     ipos -= cvt->rate_incr;
  1230                     output -= 1;
  1231                     *output = cvt->buf[(int) ipos];
  1232                 }
  1233             }
  1234             break;
  1235 
  1236         case 16:
  1237             {
  1238                 Uint16 *output;
  1239 
  1240                 clen &= ~1;
  1241                 output = (Uint16 *) (cvt->buf + clen);
  1242                 ipos = (double) cvt->len_cvt / 2;
  1243                 for (i = clen / 2; i; --i) {
  1244                     ipos -= cvt->rate_incr;
  1245                     output -= 1;
  1246                     *output = ((Uint16 *) cvt->buf)[(int) ipos];
  1247                 }
  1248             }
  1249             break;
  1250 
  1251         case 32:
  1252             {
  1253                 /* !!! FIXME: need 32-bit converter here! */
  1254 #ifdef DEBUG_CONVERT
  1255                 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
  1256 #endif
  1257             }
  1258         }
  1259     }
  1260 
  1261     cvt->len_cvt = clen;
  1262     if (cvt->filters[++cvt->filter_index]) {
  1263         cvt->filters[cvt->filter_index] (cvt, format);
  1264     }
  1265 }
  1266 
  1267 int
  1268 SDL_ConvertAudio(SDL_AudioCVT * cvt)
  1269 {
  1270     /* Make sure there's data to convert */
  1271     if (cvt->buf == NULL) {
  1272         SDL_SetError("No buffer allocated for conversion");
  1273         return (-1);
  1274     }
  1275     /* Return okay if no conversion is necessary */
  1276     cvt->len_cvt = cvt->len;
  1277     if (cvt->filters[0] == NULL) {
  1278         return (0);
  1279     }
  1280 
  1281     /* Set up the conversion and go! */
  1282     cvt->filter_index = 0;
  1283     cvt->filters[0] (cvt, cvt->src_format);
  1284     return (0);
  1285 }
  1286 
  1287 
  1288 static SDL_AudioFilter
  1289 SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1290 {
  1291     /*
  1292      * Fill in any future conversions that are specialized to a
  1293      *  processor, platform, compiler, or library here.
  1294      */
  1295 
  1296     return NULL;                /* no specialized converter code available. */
  1297 }
  1298 
  1299 
  1300 /*
  1301  * Find a converter between two data types. We try to select a hand-tuned
  1302  *  asm/vectorized/optimized function first, and then fallback to an
  1303  *  autogenerated function that is customized to convert between two
  1304  *  specific data types.
  1305  */
  1306 static int
  1307 SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
  1308                       SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
  1309 {
  1310     if (src_fmt != dst_fmt) {
  1311         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
  1312         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
  1313         SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
  1314 
  1315         /* No hand-tuned converter? Try the autogenerated ones. */
  1316         if (filter == NULL) {
  1317             int i;
  1318             for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
  1319                 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
  1320                 if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
  1321                     filter = filt->filter;
  1322                     break;
  1323                 }
  1324             }
  1325 
  1326             if (filter == NULL) {
  1327                 return -1;      /* Still no matching converter?! */
  1328             }
  1329         }
  1330 
  1331         /* Update (cvt) with filter details... */
  1332         cvt->filters[cvt->filter_index++] = filter;
  1333         if (src_bitsize < dst_bitsize) {
  1334             const int mult = (dst_bitsize / src_bitsize);
  1335             cvt->len_mult *= mult;
  1336             cvt->len_ratio *= mult;
  1337         } else if (src_bitsize > dst_bitsize) {
  1338             cvt->len_ratio /= (src_bitsize / dst_bitsize);
  1339         }
  1340 
  1341         return 1;               /* added a converter. */
  1342     }
  1343 
  1344     return 0;                   /* no conversion necessary. */
  1345 }
  1346 
  1347 /* Generate the necessary IIR lowpass coefficients for resampling.
  1348    Assume that the SDL_AudioCVT struct is already set up with
  1349    the correct values for len_mult and len_div, and use the
  1350    type of dst_format. Also assume the buffer is allocated.
  1351    Note the buffer needs to be 6 units long.
  1352    For now, use RBJ's cookbook coefficients. It might be more
  1353    optimal to create a Butterworth filter, but this is more difficult.
  1354 */
  1355 int
  1356 SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1357 {
  1358     float fc;                   /* cutoff frequency */
  1359     float coeff[6];             /* floating point iir coefficients b0, b1, b2, a0, a1, a2 */
  1360     float scale;
  1361     float w0, alpha, cosw0;
  1362     int i;
  1363 
  1364     /* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */
  1365     static const float Q = 5.0f;
  1366     static const float CUTOFF = 0.4f;
  1367 
  1368     fc = (cvt->len_mult >
  1369           cvt->len_div) ? CUTOFF / (float) cvt->len_mult : CUTOFF /
  1370         (float) cvt->len_div;
  1371 
  1372     w0 = 2.0f * M_PI * fc;
  1373     cosw0 = cosf(w0);
  1374     alpha = sinf(w0) / (2.0f * Q);
  1375 
  1376     /* Compute coefficients, normalizing by a0 */
  1377     scale = 1.0f / (1.0f + alpha);
  1378 
  1379     coeff[0] = (1.0f - cosw0) / 2.0f * scale;
  1380     coeff[1] = (1.0f - cosw0) * scale;
  1381     coeff[2] = coeff[0];
  1382 
  1383     coeff[3] = 1.0f;            /* a0 is normalized to 1 */
  1384     coeff[4] = -2.0f * cosw0 * scale;
  1385     coeff[5] = (1.0f - alpha) * scale;
  1386 
  1387     /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */
  1388 #define convert_fixed(type, fix) { \
  1389             type *cvt_coeff = (type *)cvt->coeff; \
  1390             for(i = 0; i < 6; ++i) { \
  1391                 cvt_coeff[i] = fix(coeff[i]); \
  1392             } \
  1393         }
  1394 
  1395     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1396         float *cvt_coeff = (float *) cvt->coeff;
  1397         for (i = 0; i < 6; ++i) {
  1398             cvt_coeff[i] = coeff[i];
  1399         }
  1400     } else {
  1401         switch (SDL_AUDIO_BITSIZE(format)) {
  1402         case 8:
  1403             convert_fixed(Uint8, SDL_Make_2_6);
  1404             break;
  1405         case 16:
  1406             convert_fixed(Uint16, SDL_Make_2_14);
  1407             break;
  1408         case 32:
  1409             convert_fixed(Uint32, SDL_Make_2_30);
  1410             break;
  1411         }
  1412     }
  1413 
  1414 #ifdef DEBUG_CONVERT
  1415 #define debug_iir(type) { \
  1416             type *cvt_coeff = (type *)cvt->coeff; \
  1417             for(i = 0; i < 6; ++i) { \
  1418                 printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \
  1419             } \
  1420         }
  1421     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1422         float *cvt_coeff = (float *) cvt->coeff;
  1423         for (i = 0; i < 6; ++i) {
  1424             printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]);
  1425         }
  1426     } else {
  1427         switch (SDL_AUDIO_BITSIZE(format)) {
  1428         case 8:
  1429             debug_iir(Uint8);
  1430             break;
  1431         case 16:
  1432             debug_iir(Uint16);
  1433             break;
  1434         case 32:
  1435             debug_iir(Uint32);
  1436             break;
  1437         }
  1438     }
  1439 #undef debug_iir
  1440 #endif
  1441 
  1442     /* Initialize the state buffer to all zeroes, and set initial position */
  1443     SDL_memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4);
  1444     cvt->state_pos = 0;
  1445 #undef convert_fixed
  1446 }
  1447 
  1448 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
  1449 /* This was implemented because it would be much faster than the fir filter, 
  1450    but it doesn't seem to have a steep enough cutoff so we'd need several
  1451    cascaded biquads, which probably isn't a great idea. Therefore, this
  1452    function can probably be discarded.
  1453 */
  1454 static void
  1455 SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1456 {
  1457     Uint32 i, n;
  1458 
  1459     /* TODO: Check that n is calculated right */
  1460     n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
  1461 
  1462     /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? The right shift temp = buf[n] >> 1 needs to depend on whether the type is signed or not for sign extension. */
  1463     /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
  1464 #define iir_fix(type, mult) {\
  1465             type *coeff = (type *)cvt->coeff; \
  1466             type *state = (type *)cvt->state_buf; \
  1467             type *buf = (type *)cvt->buf; \
  1468             type temp; \
  1469             for(i = 0; i < n; ++i) { \
  1470                     temp = buf[i] >> 1; \
  1471                     if(cvt->state_pos) { \
  1472                         buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
  1473                         state[1] = temp; \
  1474                         state[3] = buf[i]; \
  1475                         cvt->state_pos = 0; \
  1476                     } else { \
  1477                         buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[1]) + mult(coeff[2], state[0]) - mult(coeff[4], state[3]) - mult(coeff[5], state[2]); \
  1478                         state[0] = temp; \
  1479                         state[2] = buf[i]; \
  1480                         cvt->state_pos = 1; \
  1481                     } \
  1482                 } \
  1483         }
  1484 /* Need to test to see if the previous method or this one is faster */
  1485 /*#define iir_fix(type, mult) {\
  1486             type *coeff = (type *)cvt->coeff; \
  1487             type *state = (type *)cvt->state_buf; \
  1488             type *buf = (type *)cvt->buf; \
  1489             type temp; \
  1490             for(i = 0; i < n; ++i) { \
  1491                     temp = buf[i] >> 1; \
  1492                     buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
  1493                     state[1] = state[0]; \
  1494                     state[0] = temp; \
  1495                     state[3] = state[2]; \
  1496                     state[2] = buf[i]; \
  1497                 } \
  1498         }*/
  1499 
  1500     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1501         float *coeff = (float *) cvt->coeff;
  1502         float *state = (float *) cvt->state_buf;
  1503         float *buf = (float *) cvt->buf;
  1504         float temp;
  1505 
  1506         for (i = 0; i < n; ++i) {
  1507             /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
  1508             temp = buf[i];
  1509             if (cvt->state_pos) {
  1510                 buf[i] =
  1511                     coeff[0] * buf[n] + coeff[1] * state[0] +
  1512                     coeff[2] * state[1] - coeff[4] * state[2] -
  1513                     coeff[5] * state[3];
  1514                 state[1] = temp;
  1515                 state[3] = buf[i];
  1516                 cvt->state_pos = 0;
  1517             } else {
  1518                 buf[i] =
  1519                     coeff[0] * buf[n] + coeff[1] * state[1] +
  1520                     coeff[2] * state[0] - coeff[4] * state[3] -
  1521                     coeff[5] * state[2];
  1522                 state[0] = temp;
  1523                 state[2] = buf[i];
  1524                 cvt->state_pos = 1;
  1525             }
  1526         }
  1527     } else {
  1528         /* Treat everything as signed! */
  1529         switch (SDL_AUDIO_BITSIZE(format)) {
  1530         case 8:
  1531             iir_fix(Sint8, SDL_FixMpy8);
  1532             break;
  1533         case 16:
  1534             iir_fix(Sint16, SDL_FixMpy16);
  1535             break;
  1536         case 32:
  1537             iir_fix(Sint32, SDL_FixMpy32);
  1538             break;
  1539         }
  1540     }
  1541 #undef iir_fix
  1542 }
  1543 
  1544 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct.
  1545 */
  1546 static void
  1547 SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1548 {
  1549     int n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
  1550     int m = cvt->len_sinc;
  1551     int i, j;
  1552 
  1553     /* 
  1554        Note: We can make a big optimization here by taking advantage
  1555        of the fact that the signal is zero stuffed, so we can do
  1556        significantly fewer multiplications and additions. However, this
  1557        depends on the zero stuffing ratio, so it may not pay off. This would
  1558        basically be a polyphase filter.
  1559      */
  1560     /* One other way to do this fast is to look at the fir filter from a different angle:
  1561        After we zero stuff, we have input of all zeroes, except for every len_mult
  1562        sample. If we choose a sinc length equal to len_mult, then the fir filter becomes
  1563        much more simple: we're just taking a windowed sinc, shifting it to start at each
  1564        len_mult sample, and scaling it by the value of that sample. If we do this, then
  1565        we don't even need to worry about the sample histories, and the inner loop here is
  1566        unnecessary. This probably sacrifices some quality but could really speed things up as well.
  1567      */
  1568     /* We only calculate the values of samples which are 0 (mod len_div) because
  1569        those are the only ones used. All the other ones are discarded in the
  1570        third step of resampling. This is a huge speedup. As a warning, though,
  1571        if for some reason this is used elsewhere where there are no samples discarded,
  1572        the output will not be corrrect if len_div is not 1. To make this filter a
  1573        generic FIR filter, simply remove the if statement "if(i % cvt->len_div == 0)"
  1574        around the inner loop so that every sample is processed.
  1575      */
  1576     /* This is basically just a FIR filter. i.e. for input x_n and m coefficients,
  1577        y_n = x_n*sinc_0 + x_(n-1)*sinc_1 +  x_(n-2)*sinc_2 + ... + x_(n-m+1)*sinc_(m-1)
  1578      */
  1579 #define filter_sinc(type, mult) { \
  1580             type *sinc = (type *)cvt->coeff; \
  1581             type *state = (type *)cvt->state_buf; \
  1582             type *buf = (type *)cvt->buf; \
  1583             for(i = 0; i < n; ++i) { \
  1584                 state[cvt->state_pos] = buf[i]; \
  1585                 buf[i] = 0; \
  1586                 if( i % cvt->len_div == 0 ) { \
  1587                     for(j = 0; j < m;  ++j) { \
  1588                         buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \
  1589                     } \
  1590                 }\
  1591                 cvt->state_pos = (cvt->state_pos + 1) % m; \
  1592             } \
  1593         }
  1594 
  1595     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1596         filter_sinc(float, SDL_FloatMpy);
  1597     } else {
  1598         switch (SDL_AUDIO_BITSIZE(format)) {
  1599         case 8:
  1600             filter_sinc(Sint8, SDL_FixMpy8);
  1601             break;
  1602         case 16:
  1603             filter_sinc(Sint16, SDL_FixMpy16);
  1604             break;
  1605         case 32:
  1606             filter_sinc(Sint32, SDL_FixMpy32);
  1607             break;
  1608         }
  1609     }
  1610 
  1611 #undef filter_sinc
  1612 
  1613 }
  1614 
  1615 /* Generate the necessary windowed sinc filter for resampling.
  1616    Assume that the SDL_AudioCVT struct is already set up with
  1617    the correct values for len_mult and len_div, and use the
  1618    type of dst_format. Also assume the buffer is allocated.
  1619    Note the buffer needs to be m+1 units long.
  1620 */
  1621 int
  1622 SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format,
  1623                       unsigned int m)
  1624 {
  1625     float *fSinc;               /* floating point sinc buffer, to be converted to fixed point */
  1626     float fc;                   /* cutoff frequency */
  1627     float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
  1628     float norm_sum, norm_fact;
  1629     unsigned int i;
  1630 
  1631     /* Check that the buffer is allocated */
  1632     if (cvt->coeff == NULL) {
  1633         return -1;
  1634     }
  1635 
  1636     /* Set the length */
  1637     cvt->len_sinc = m + 1;
  1638 
  1639     /* Allocate the floating point windowed sinc. */
  1640     fSinc = SDL_stack_alloc(float, (m + 1));
  1641     if (fSinc == NULL) {
  1642         return -1;
  1643     }
  1644 
  1645     /* Set up the filter parameters */
  1646     fc = (cvt->len_mult >
  1647           cvt->len_div) ? 0.5f / (float) cvt->len_mult : 0.5f /
  1648         (float) cvt->len_div;
  1649 #ifdef DEBUG_CONVERT
  1650     printf("Lowpass cutoff frequency = %f\n", fc);
  1651 #endif
  1652     two_pi_fc = 2.0f * M_PI * fc;
  1653     two_pi_over_m = 2.0f * M_PI / (float) m;
  1654     four_pi_over_m = 2.0f * two_pi_over_m;
  1655     m_over_two = (float) m / 2.0f;
  1656     norm_sum = 0.0f;
  1657 
  1658     for (i = 0; i <= m; ++i) {
  1659         if (i == m / 2) {
  1660             fSinc[i] = two_pi_fc;
  1661         } else {
  1662             fSinc[i] =
  1663                 sinf(two_pi_fc * ((float) i - m_over_two)) / ((float) i -
  1664                                                               m_over_two);
  1665             /* Apply blackman window */
  1666             fSinc[i] *=
  1667                 0.42f - 0.5f * cosf(two_pi_over_m * (float) i) +
  1668                 0.08f * cosf(four_pi_over_m * (float) i);
  1669         }
  1670         norm_sum += fabs(fSinc[i]);
  1671     }
  1672 
  1673     norm_fact = 1.0f / norm_sum;
  1674 
  1675 #define convert_fixed(type, fix) { \
  1676         type *dst = (type *)cvt->coeff; \
  1677         for( i = 0; i <= m; ++i ) { \
  1678             dst[i] = fix(fSinc[i] * norm_fact); \
  1679         } \
  1680     }
  1681 
  1682     /* If we're using floating point, we only need to normalize */
  1683     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1684         float *fDest = (float *) cvt->coeff;
  1685         for (i = 0; i <= m; ++i) {
  1686             fDest[i] = fSinc[i] * norm_fact;
  1687         }
  1688     } else {
  1689         switch (SDL_AUDIO_BITSIZE(format)) {
  1690         case 8:
  1691             convert_fixed(Uint8, SDL_Make_1_7);
  1692             break;
  1693         case 16:
  1694             convert_fixed(Uint16, SDL_Make_1_15);
  1695             break;
  1696         case 32:
  1697             convert_fixed(Uint32, SDL_Make_1_31);
  1698             break;
  1699         }
  1700     }
  1701 
  1702     /* Initialize the state buffer to all zeroes, and set initial position */
  1703     SDL_memset(cvt->state_buf, 0,
  1704                cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
  1705     cvt->state_pos = 0;
  1706 
  1707     /* Clean up */
  1708 #undef convert_fixed
  1709     SDL_stack_free(fSinc);
  1710 
  1711     return 0;
  1712 }
  1713 
  1714 /* This is used to reduce the resampling ratio */
  1715 static __inline__ int
  1716 SDL_GCD(int a, int b)
  1717 {
  1718     int temp;
  1719     while (b != 0) {
  1720         temp = a % b;
  1721         a = b;
  1722         b = temp;
  1723     }
  1724     return a;
  1725 }
  1726 
  1727 /* Perform proper resampling. This is pretty slow but it's the best-sounding method. */
  1728 static void SDLCALL
  1729 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1730 {
  1731     int i, j;
  1732 
  1733 #ifdef DEBUG_CONVERT
  1734     printf("Converting audio rate via proper resampling (mono)\n");
  1735 #endif
  1736 
  1737 #define zerostuff_mono(type) { \
  1738         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
  1739         type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \
  1740         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
  1741             src--; \
  1742             dst[-1] = src[0]; \
  1743             for( j = -cvt->len_mult; j < -1; ++j ) { \
  1744                 dst[j] = 0; \
  1745             } \
  1746             dst -= cvt->len_mult; \
  1747         } \
  1748     }
  1749 
  1750 #define discard_mono(type) { \
  1751         const type *src = (const type *) (cvt->buf); \
  1752         type *dst = (type *) (cvt->buf); \
  1753         for (i = 0; i < (cvt->len_cvt / sizeof(type)) / cvt->len_div; ++i) { \
  1754             dst[0] = src[0]; \
  1755             src += cvt->len_div; \
  1756             ++dst; \
  1757         } \
  1758     }
  1759 
  1760     /* Step 1: Zero stuff the conversion buffer. This upsamples by a factor of len_mult,
  1761        creating aliasing at frequencies above the original nyquist frequency.
  1762      */
  1763 #ifdef DEBUG_CONVERT
  1764     printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
  1765 #endif
  1766     switch (SDL_AUDIO_BITSIZE(format)) {
  1767     case 8:
  1768         zerostuff_mono(Uint8);
  1769         break;
  1770     case 16:
  1771         zerostuff_mono(Uint16);
  1772         break;
  1773     case 32:
  1774         zerostuff_mono(Uint32);
  1775         break;
  1776     }
  1777 
  1778     cvt->len_cvt *= cvt->len_mult;
  1779 
  1780     /* Step 2: Use a windowed sinc FIR filter (lowpass filter) to remove the alias
  1781        frequencies. This is the slow part.
  1782      */
  1783     SDL_FilterFIR(cvt, format);
  1784 
  1785     /* Step 3: Now downsample by discarding samples. */
  1786 
  1787 #ifdef DEBUG_CONVERT
  1788     printf("Discarding samples by a factor of %u\n", cvt->len_div);
  1789 #endif
  1790     switch (SDL_AUDIO_BITSIZE(format)) {
  1791     case 8:
  1792         discard_mono(Uint8);
  1793         break;
  1794     case 16:
  1795         discard_mono(Uint16);
  1796         break;
  1797     case 32:
  1798         discard_mono(Uint32);
  1799         break;
  1800     }
  1801 
  1802 #undef zerostuff_mono
  1803 #undef discard_mono
  1804 
  1805     cvt->len_cvt /= cvt->len_div;
  1806 
  1807     if (cvt->filters[++cvt->filter_index]) {
  1808         cvt->filters[cvt->filter_index] (cvt, format);
  1809     }
  1810 }
  1811 
  1812 
  1813 /* Creates a set of audio filters to convert from one format to another.
  1814    Returns -1 if the format conversion is not supported, 0 if there's
  1815    no conversion needed, or 1 if the audio filter is set up.
  1816 */
  1817 
  1818 int
  1819 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
  1820                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1821                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1822 {
  1823     /* there are no unsigned types over 16 bits, so catch this upfront. */
  1824     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1825         return -1;
  1826     }
  1827     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1828         return -1;
  1829     }
  1830 #ifdef DEBUG_CONVERT
  1831     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1832            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1833 #endif
  1834 
  1835     /* Start off with no conversion necessary */
  1836 
  1837     cvt->src_format = src_fmt;
  1838     cvt->dst_format = dst_fmt;
  1839     cvt->needed = 0;
  1840     cvt->filter_index = 0;
  1841     cvt->filters[0] = NULL;
  1842     cvt->len_mult = 1;
  1843     cvt->len_ratio = 1.0;
  1844 
  1845     /* Convert data types, if necessary. Updates (cvt). */
  1846     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1847         return -1;              /* shouldn't happen, but just in case... */
  1848 
  1849     /* Channel conversion */
  1850     if (src_channels != dst_channels) {
  1851         if ((src_channels == 1) && (dst_channels > 1)) {
  1852             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1853             cvt->len_mult *= 2;
  1854             src_channels = 2;
  1855             cvt->len_ratio *= 2;
  1856         }
  1857         if ((src_channels == 2) && (dst_channels == 6)) {
  1858             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1859             src_channels = 6;
  1860             cvt->len_mult *= 3;
  1861             cvt->len_ratio *= 3;
  1862         }
  1863         if ((src_channels == 2) && (dst_channels == 4)) {
  1864             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1865             src_channels = 4;
  1866             cvt->len_mult *= 2;
  1867             cvt->len_ratio *= 2;
  1868         }
  1869         while ((src_channels * 2) <= dst_channels) {
  1870             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1871             cvt->len_mult *= 2;
  1872             src_channels *= 2;
  1873             cvt->len_ratio *= 2;
  1874         }
  1875         if ((src_channels == 6) && (dst_channels <= 2)) {
  1876             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1877             src_channels = 2;
  1878             cvt->len_ratio /= 3;
  1879         }
  1880         if ((src_channels == 6) && (dst_channels == 4)) {
  1881             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1882             src_channels = 4;
  1883             cvt->len_ratio /= 2;
  1884         }
  1885         /* This assumes that 4 channel audio is in the format:
  1886            Left {front/back} + Right {front/back}
  1887            so converting to L/R stereo works properly.
  1888          */
  1889         while (((src_channels % 2) == 0) &&
  1890                ((src_channels / 2) >= dst_channels)) {
  1891             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1892             src_channels /= 2;
  1893             cvt->len_ratio /= 2;
  1894         }
  1895         if (src_channels != dst_channels) {
  1896             /* Uh oh.. */ ;
  1897         }
  1898     }
  1899 
  1900     /* Do rate conversion */
  1901     if (src_rate != dst_rate) {
  1902         int rate_gcd;
  1903         rate_gcd = SDL_GCD(src_rate, dst_rate);
  1904         cvt->len_mult = dst_rate / rate_gcd;
  1905         cvt->len_div = src_rate / rate_gcd;
  1906         cvt->len_ratio = (double) cvt->len_mult / (double) cvt->len_div;
  1907         cvt->filters[cvt->filter_index++] = SDL_Resample;
  1908         SDL_BuildWindowedSinc(cvt, dst_fmt, 768);
  1909     }
  1910 
  1911 /*
  1912     cvt->rate_incr = 0.0;
  1913     if ((src_rate / 100) != (dst_rate / 100)) {
  1914         Uint32 hi_rate, lo_rate;
  1915         int len_mult;
  1916         double len_ratio;
  1917         SDL_AudioFilter rate_cvt = NULL;
  1918 
  1919         if (src_rate > dst_rate) {
  1920             hi_rate = src_rate;
  1921             lo_rate = dst_rate;
  1922             switch (src_channels) {
  1923             case 1:
  1924                 rate_cvt = SDL_RateDIV2;
  1925                 break;
  1926             case 2:
  1927                 rate_cvt = SDL_RateDIV2_c2;
  1928                 break;
  1929             case 4:
  1930                 rate_cvt = SDL_RateDIV2_c4;
  1931                 break;
  1932             case 6:
  1933                 rate_cvt = SDL_RateDIV2_c6;
  1934                 break;
  1935             default:
  1936                 return -1;
  1937             }
  1938             len_mult = 1;
  1939             len_ratio = 0.5;
  1940         } else {
  1941             hi_rate = dst_rate;
  1942             lo_rate = src_rate;
  1943             switch (src_channels) {
  1944             case 1:
  1945                 rate_cvt = SDL_RateMUL2;
  1946                 break;
  1947             case 2:
  1948                 rate_cvt = SDL_RateMUL2_c2;
  1949                 break;
  1950             case 4:
  1951                 rate_cvt = SDL_RateMUL2_c4;
  1952                 break;
  1953             case 6:
  1954                 rate_cvt = SDL_RateMUL2_c6;
  1955                 break;
  1956             default:
  1957                 return -1;
  1958             }
  1959             len_mult = 2;
  1960             len_ratio = 2.0;
  1961         }*/
  1962     /* If hi_rate = lo_rate*2^x then conversion is easy */
  1963     /*   while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1964        cvt->filters[cvt->filter_index++] = rate_cvt;
  1965        cvt->len_mult *= len_mult;
  1966        lo_rate *= 2;
  1967        cvt->len_ratio *= len_ratio;
  1968        } */
  1969     /* We may need a slow conversion here to finish up */
  1970     /*    if ((lo_rate / 100) != (hi_rate / 100)) {
  1971        #if 1 */
  1972     /* The problem with this is that if the input buffer is
  1973        say 1K, and the conversion rate is say 1.1, then the
  1974        output buffer is 1.1K, which may not be an acceptable
  1975        buffer size for the audio driver (not a power of 2)
  1976      */
  1977     /* For now, punt and hope the rate distortion isn't great.
  1978      */
  1979 /*#else
  1980             if (src_rate < dst_rate) {
  1981                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1982                 cvt->len_mult *= 2;
  1983                 cvt->len_ratio /= cvt->rate_incr;
  1984             } else {
  1985                 cvt->rate_incr = (double) hi_rate / lo_rate;
  1986                 cvt->len_ratio *= cvt->rate_incr;
  1987             }
  1988             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1989 #endif
  1990         }
  1991     }*/
  1992 
  1993     /* Set up the filter information */
  1994     if (cvt->filter_index != 0) {
  1995         cvt->needed = 1;
  1996         cvt->src_format = src_fmt;
  1997         cvt->dst_format = dst_fmt;
  1998         cvt->len = 0;
  1999         cvt->buf = NULL;
  2000         cvt->filters[cvt->filter_index] = NULL;
  2001     }
  2002     return (cvt->needed);
  2003 }
  2004 
  2005 #undef SDL_FixMpy8
  2006 #undef SDL_FixMpy16
  2007 #undef SDL_FixMpy32
  2008 #undef SDL_FloatMpy
  2009 #undef SDL_Make_1_7
  2010 #undef SDL_Make_1_15
  2011 #undef SDL_Make_1_31
  2012 #undef SDL_Make_2_6
  2013 #undef SDL_Make_2_14
  2014 #undef SDL_Make_2_30
  2015 
  2016 /* vi: set ts=4 sw=4 expandtab: */