src/audio/SDL_audiocvt.c
author Aaron Wishnick <schnarf@gmail.com>
Sun, 22 Jun 2008 00:36:35 +0000
branchgsoc2008_audio_resampling
changeset 2659 8da698bc1205
parent 2658 de29a03cb108
child 2660 a55543cef395
permissions -rw-r--r--
Fixed lots of bugs in FIR filtering. Fixed point code is closer to working, but there seems to be overflow in the FIR filter resulting in distortion.
     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 #define DEBUG_CONVERT
    31 
    32 /* Perform fractional multiplication of two 32-bit integers to produce a 32-bit result. Assumes sizeof(long) = 4 */
    33 /*#define SDL_FixMpy32(v1, v2, dest) { \
    34 			long a, b, c, d; \
    35 			long x, y; \
    36 			a = (v1 >> 16) & 0xffff; \
    37 			b = v1 & 0xffff; \
    38 			c = (v2 >> 16); \
    39 			d = v2 & 0xffff; \
    40 			x = a * d + c * b; \
    41 			y = (((b*d) >> 16) & 0xffff) + x; \
    42 			dest = ((y >> 16) & 0xffff) + (a * c); \
    43 		}*/
    44 /* TODO: Check if 64-bit type exists. If not, see http://www.8052.com/mul16.phtml or http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html */
    45 
    46 /* We hope here that the right shift includes sign extension */
    47 #ifdef SDL_HAS_64BIT_Type		
    48 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    49 #else
    50 /* need to do something more complicated here */
    51 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    52 #endif
    53 /* Confirmed that SDL_FixMpy16 works, need to check 8 and 32 */
    54 #define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
    55 #define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
    56 /* Everything is signed! */
    57 #define SDL_Make_1_7(a) (Sint8)(a * 127.0f)
    58 #define SDL_Make_1_15(a) (Sint16)(a * 32767.0f)
    59 #define SDL_Make_1_31(a) (Sint32)(a * 2147483647.0f)
    60 #define SDL_Make_2_6(a) (Sint8)(a * 63.0f)
    61 #define SDL_Make_2_14(a) (Sint16)(a * 16383.0f)
    62 #define SDL_Make_2_30(a) (Sint32)(a * 1073741823.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 SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
  1356 	float fc;			/* cutoff frequency */
  1357 	float coeff[6];		/* floating point iir coefficients b0, b1, b2, a0, a1, a2 */
  1358 	float scale;
  1359 	float w0, alpha, cosw0;
  1360 	int i;
  1361 	
  1362 	/* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */
  1363 	static const float Q = 5.0f;
  1364 	static const float CUTOFF = 0.4f;
  1365 	
  1366 	fc = (cvt->len_mult > cvt->len_div) ? CUTOFF / (float)cvt->len_mult : CUTOFF / (float)cvt->len_div;
  1367 	
  1368 	w0 = 2.0f * M_PI * fc;
  1369 	cosw0 = cosf(w0);
  1370 	alpha = sin(w0) / (2.0f * Q);
  1371 	
  1372 	/* Compute coefficients, normalizing by a0 */
  1373 	scale = 1.0f / (1.0f + alpha);
  1374 	
  1375 	coeff[0] = (1.0f - cosw0) / 2.0f * scale;
  1376 	coeff[1] = (1.0f - cosw0) * scale;
  1377 	coeff[2] = coeff[0];
  1378 	
  1379 	coeff[3] = 1.0f;	/* a0 is normalized to 1 */
  1380 	coeff[4] = -2.0f * cosw0 * scale;
  1381 	coeff[5] = (1.0f - alpha) * scale;
  1382 	
  1383 	/* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */
  1384 #define convert_fixed(type, fix) { \
  1385 			type *cvt_coeff = (type *)cvt->coeff; \
  1386 			for(i = 0; i < 6; ++i) { \
  1387 				cvt_coeff[i] = fix(coeff[i]); \
  1388 			} \
  1389 		}
  1390 		
  1391 	if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1392 		float *cvt_coeff = (float *)cvt->coeff;
  1393 		for(i = 0; i < 6; ++i) {
  1394 			cvt_coeff[i] = coeff[i];
  1395 		}
  1396 	} else {
  1397 		switch(SDL_AUDIO_BITSIZE(format)) {
  1398 			case 8:
  1399 				convert_fixed(Uint8, SDL_Make_2_6);
  1400 				break;
  1401 			case 16:
  1402 				convert_fixed(Uint16, SDL_Make_2_14);
  1403 				break;
  1404 			case 32:
  1405 				convert_fixed(Uint32, SDL_Make_2_30);
  1406 				break;
  1407 		}
  1408 	}
  1409 	
  1410 #ifdef DEBUG_CONVERT
  1411 #define debug_iir(type) { \
  1412 			type *cvt_coeff = (type *)cvt->coeff; \
  1413 			for(i = 0; i < 6; ++i) { \
  1414 				printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \
  1415 			} \
  1416 		}
  1417 		if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1418 			float *cvt_coeff = (float *)cvt->coeff;
  1419 			for(i = 0; i < 6; ++i) { \
  1420 				printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]); \
  1421 			}
  1422 		} else {
  1423 			switch(SDL_AUDIO_BITSIZE(format)) {
  1424 				case 8:
  1425 					debug_iir(Uint8);
  1426 					break;
  1427 				case 16:
  1428 					debug_iir(Uint16);
  1429 					break;
  1430 				case 32:
  1431 					debug_iir(Uint32);
  1432 					break;
  1433 			}
  1434 		}
  1435 #undef debug_iir
  1436 #endif
  1437 	
  1438 	/* Initialize the state buffer to all zeroes, and set initial position */
  1439 	memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4);
  1440 	cvt->state_pos = 0;
  1441 #undef convert_fixed
  1442 }
  1443 
  1444 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
  1445 static void SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
  1446 	Uint32 i, n;
  1447 	
  1448 	/* TODO: Check that n is calculated right */
  1449 	n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
  1450 
  1451 	/* 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.*/
  1452 	/* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
  1453 #define iir_fix(type, mult) {\
  1454 			type *coeff = (type *)cvt->coeff; \
  1455 			type *state = (type *)cvt->state_buf; \
  1456 			type *buf = (type *)cvt->buf; \
  1457 			type temp; \
  1458 			for(i = 0; i < n; ++i) { \
  1459 					temp = buf[i] >> 1; \
  1460 					if(cvt->state_pos) { \
  1461 						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]); \
  1462 						state[1] = temp; \
  1463 						state[3] = buf[i]; \
  1464 						cvt->state_pos = 0; \
  1465 					} else { \
  1466 						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]); \
  1467 						state[0] = temp; \
  1468 						state[2] = buf[i]; \
  1469 						cvt->state_pos = 1; \
  1470 					} \
  1471 				} \
  1472 		}
  1473 /* Need to test to see if the previous method or this one is faster */
  1474 /*#define iir_fix(type, mult) {\
  1475 			type *coeff = (type *)cvt->coeff; \
  1476 			type *state = (type *)cvt->state_buf; \
  1477 			type *buf = (type *)cvt->buf; \
  1478 			type temp; \
  1479 			for(i = 0; i < n; ++i) { \
  1480 					temp = buf[i] >> 1; \
  1481 					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]); \
  1482 					state[1] = state[0]; \
  1483 					state[0] = temp; \
  1484 					state[3] = state[2]; \
  1485 					state[2] = buf[i]; \
  1486 				} \
  1487 		}*/
  1488 
  1489 	if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1490 		float *coeff = (float *)cvt->coeff;
  1491 		float *state = (float *)cvt->state_buf;
  1492 		float *buf = (float *)cvt->buf;
  1493 		float temp;
  1494 
  1495 		for(i = 0; i < n; ++i) {
  1496 			/* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
  1497 			temp = buf[i];
  1498 			if(cvt->state_pos) {
  1499 				buf[i] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3];
  1500 				state[1] = temp;
  1501 				state[3] = buf[i];
  1502 				cvt->state_pos = 0;
  1503 			} else {
  1504 				buf[i] = coeff[0] * buf[n] + coeff[1] * state[1] + coeff[2] * state[0] - coeff[4] * state[3] - coeff[5] * state[2];
  1505 				state[0] = temp;
  1506 				state[2] = buf[i];
  1507 				cvt->state_pos = 1;
  1508 			}
  1509 		}
  1510 	} else {
  1511 		/* Treat everything as signed! */
  1512 		switch(SDL_AUDIO_BITSIZE(format)) {
  1513 			case 8:
  1514 				iir_fix(Sint8, SDL_FixMpy8);
  1515 				break;
  1516 			case 16:
  1517 				iir_fix(Sint16, SDL_FixMpy16);
  1518 				break;
  1519 			case 32:
  1520 				iir_fix(Sint32, SDL_FixMpy32);
  1521 				break;
  1522 		}
  1523 	}
  1524 #undef iir_fix
  1525 }
  1526 
  1527 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct */
  1528 static void SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
  1529 	int n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
  1530 	int m = cvt->len_sinc;
  1531 	int i, j;
  1532 				
  1533 	/* Note: this makes use of the symmetry of the sinc filter.
  1534 	   We can also make a big optimization here by taking advantage
  1535 	   of the fact that the signal is zero stuffed, so we can do
  1536 	   significantly fewer multiplications and additions.
  1537 	*/
  1538 #define filter_sinc(type, mult) { \
  1539 			type *sinc = (type *)cvt->coeff; \
  1540 			type *state = (type *)cvt->state_buf; \
  1541 			type *buf = (type *)cvt->buf; \
  1542 			for(i = 0; i < n; ++i) { \
  1543 				cvt->state_pos++; \
  1544 				if(cvt->state_pos >= m) cvt->state_pos = 0; \
  1545 				state[cvt->state_pos] = buf[i]; \
  1546 				buf[i] = 0; \
  1547 				for(j = 0; j < m;  ++j) { \
  1548 					buf[i] += mult(state[(cvt->state_pos - j) % m], sinc[j]); \
  1549 				} \
  1550 			} \
  1551 		}
  1552 	
  1553 	/* If it's floating point, we don't need to do any shifting */
  1554 	if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1555 		float *sinc = (float *)cvt->coeff;
  1556 		float *state = (float *)cvt->state_buf;
  1557 		float *buf = (float *)cvt->buf;
  1558 		
  1559 		for(i = 0; i < n; ++i) {
  1560 			state[cvt->state_pos++] = buf[i];
  1561 			if(cvt->state_pos == m) cvt->state_pos = 0;
  1562 			buf[i] = 0.0f;
  1563 			for(j = 0; j < m; ++j) {
  1564 				buf[i] += state[j] * sinc[j];
  1565 			}
  1566 		}
  1567 	} else {
  1568 		switch (SDL_AUDIO_BITSIZE(format)) {
  1569 			case 8:
  1570 				filter_sinc(Sint8, SDL_FixMpy8);
  1571 				break;
  1572 			case 16:
  1573 				filter_sinc(Sint16, SDL_FixMpy16);
  1574 				break;
  1575 			case 32:
  1576 				filter_sinc(Sint32, SDL_FixMpy32);
  1577 				break;
  1578 		}
  1579 	}
  1580 	
  1581 #undef filter_sinc
  1582 			
  1583 }
  1584 
  1585 /* Generate the necessary windowed sinc filter for resampling.
  1586    Assume that the SDL_AudioCVT struct is already set up with
  1587    the correct values for len_mult and len_div, and use the
  1588    type of dst_format. Also assume the buffer is allocated.
  1589    Note the buffer needs to be m+1 units long.
  1590 */
  1591 int
  1592 SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format, unsigned int m) {
  1593 	float fScale;		/* scale factor for fixed point */
  1594 	float *fSinc;		/* floating point sinc buffer, to be converted to fixed point */
  1595 	float fc;			/* cutoff frequency */
  1596 	float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
  1597 	float norm_sum, norm_fact;
  1598 	unsigned int i;
  1599 
  1600 	/* Check that the buffer is allocated */
  1601 	if( cvt->coeff == NULL ) {
  1602 		return -1;
  1603 	}
  1604 
  1605 	/* Set the length */
  1606 	cvt->len_sinc = m + 1;
  1607 	
  1608 	/* Allocate the floating point windowed sinc. */
  1609 	fSinc = (float *)malloc(m * sizeof(float));
  1610 	if( fSinc == NULL ) {
  1611 		return -1;
  1612 	}
  1613 	
  1614 	/* Set up the filter parameters */
  1615 	fc = (cvt->len_mult > cvt->len_div) ? 0.5f / (float)cvt->len_mult : 0.5f / (float)cvt->len_div;
  1616 	fc = 0.04f;
  1617 	two_pi_fc = 2.0f * M_PI * fc;
  1618 	two_pi_over_m = 2.0f * M_PI / (float)m;
  1619 	four_pi_over_m = 2.0f * two_pi_over_m;
  1620 	m_over_two = (float)m / 2.0f;
  1621 	norm_sum = 0.0f;
  1622 	
  1623 	for(i = 0; i <= m; ++i ) {
  1624 		if( i == m/2 ) {
  1625 			fSinc[i] = two_pi_fc;
  1626 		} else {
  1627 			fSinc[i] = sinf(two_pi_fc * ((float)i - m_over_two)) / ((float)i - m_over_two);
  1628 			/* Apply blackman window */
  1629 			fSinc[i] *= 0.42f - 0.5f * cosf(two_pi_over_m * (float)i) + 0.08f * cosf(four_pi_over_m * (float)i);
  1630 		}
  1631 		norm_sum += abs(fSinc[i]);
  1632 		printf("%f\n", fSinc[i]);
  1633 	}
  1634 
  1635 	/* Now normalize and convert to fixed point. We scale everything to half the precision
  1636 	   of whatever datatype we're using, for example, 16 bit data means we use 8 bits */
  1637 	
  1638 #define convert_fixed(type, fix) { \
  1639 		norm_fact = 0.9f / norm_sum; \
  1640 		norm_fact = 0.15f; \
  1641 		type *dst = (type *)cvt->coeff; \
  1642 		for( i = 0; i <= m; ++i ) { \
  1643 			dst[i] = fix(fSinc[i] * norm_fact); \
  1644 			printf("%f = 0x%x\n", fSinc[i], dst[i]); \
  1645 		} \
  1646 	}
  1647 	
  1648 	/* If we're using floating point, we only need to normalize */
  1649 	if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
  1650 		float *fDest = (float *)cvt->coeff;
  1651 		norm_fact = 1.0f / norm_sum;
  1652 		for(i = 0; i <= m; ++i) {
  1653 			fDest[i] = fSinc[i] * norm_fact;
  1654 		}
  1655 	} else {
  1656 		switch (SDL_AUDIO_BITSIZE(format)) {
  1657 			case 8:
  1658 				convert_fixed(Uint8, SDL_Make_1_7);
  1659 				break;
  1660 			case 16:
  1661 				convert_fixed(Uint16, SDL_Make_1_15);
  1662 				break;
  1663 			case 32:
  1664 				convert_fixed(Uint32, SDL_Make_1_31);
  1665 				break;
  1666 		}
  1667 	}
  1668 	
  1669 	/* Initialize the state buffer to all zeroes, and set initial position */
  1670 	//memset(cvt->state_buf, 0, cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
  1671 	cvt->state_pos = 0;
  1672 	
  1673 	/* Clean up */
  1674 #undef convert_fixed
  1675 	free(fSinc);
  1676 }
  1677 
  1678 /* This is used to reduce the resampling ratio */
  1679 inline int SDL_GCD(int a, int b) {
  1680 	int temp;
  1681 	while(b != 0) {
  1682 		temp = a % b;
  1683 		a = b;
  1684 		b = temp;
  1685 	}
  1686 	return a;
  1687 }
  1688 
  1689 /* Perform proper resampling */
  1690 static void SDLCALL
  1691 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  1692 {
  1693     int i, j;
  1694 
  1695 #ifdef DEBUG_CONVERT
  1696     printf("Converting audio rate via proper resampling (mono)\n");
  1697 #endif
  1698 
  1699 #define zerostuff_mono(type) { \
  1700         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
  1701         type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \
  1702         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
  1703             src--; \
  1704             dst[-1] = src[0]; \
  1705 			for( j = -cvt->len_mult; j < -1; ++j ) { \
  1706 				dst[j] = 0; \
  1707 			} \
  1708             dst -= cvt->len_mult; \
  1709         } \
  1710     }
  1711 	
  1712 #define discard_mono(type) { \
  1713         const type *src = (const type *) (cvt->buf); \
  1714         type *dst = (type *) (cvt->buf); \
  1715         for (i = 0; i < cvt->len_cvt / cvt->len_div / sizeof (type); ++i) { \
  1716             dst[0] = src[0]; \
  1717             src += cvt->len_div; \
  1718             ++dst; \
  1719         } \
  1720     }
  1721 
  1722 	// Step 1: Zero stuff the conversion buffer
  1723 #ifdef DEBUG_CONVERT
  1724 	printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
  1725 #endif
  1726     switch (SDL_AUDIO_BITSIZE(format)) {
  1727     case 8:
  1728         zerostuff_mono(Uint8);
  1729         break;
  1730     case 16:
  1731         zerostuff_mono(Uint16);
  1732         break;
  1733     case 32:
  1734         zerostuff_mono(Uint32);
  1735         break;
  1736     }
  1737 	
  1738 	cvt->len_cvt *= cvt->len_mult;
  1739 
  1740 	// Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies
  1741 	SDL_FilterFIR( cvt, format );
  1742 	
  1743 	// Step 3: Discard unnecessary samples
  1744 #ifdef DEBUG_CONVERT
  1745 	printf("Discarding samples by a factor of %u\n", cvt->len_div);
  1746 #endif
  1747     switch (SDL_AUDIO_BITSIZE(format)) {
  1748     case 8:
  1749         discard_mono(Uint8);
  1750         break;
  1751     case 16:
  1752         discard_mono(Uint16);
  1753         break;
  1754     case 32:
  1755         discard_mono(Uint32);
  1756         break;
  1757     }
  1758 	
  1759 #undef zerostuff_mono
  1760 #undef discard_mono
  1761 
  1762     cvt->len_cvt /= cvt->len_div;
  1763 	
  1764     if (cvt->filters[++cvt->filter_index]) {
  1765         cvt->filters[cvt->filter_index] (cvt, format);
  1766     }
  1767 }
  1768 
  1769 
  1770 /* Creates a set of audio filters to convert from one format to another.
  1771    Returns -1 if the format conversion is not supported, 0 if there's
  1772    no conversion needed, or 1 if the audio filter is set up.
  1773 */
  1774 
  1775 int
  1776 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
  1777                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1778                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1779 {
  1780     /* there are no unsigned types over 16 bits, so catch this upfront. */
  1781     if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1782         return -1;
  1783     }
  1784     if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1785         return -1;
  1786     }
  1787 #ifdef DEBUG_CONVERT
  1788     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1789            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1790 #endif
  1791 
  1792     /* Start off with no conversion necessary */
  1793 
  1794     cvt->src_format = src_fmt;
  1795     cvt->dst_format = dst_fmt;
  1796     cvt->needed = 0;
  1797     cvt->filter_index = 0;
  1798     cvt->filters[0] = NULL;
  1799     cvt->len_mult = 1;
  1800     cvt->len_ratio = 1.0;
  1801 
  1802     /* Convert data types, if necessary. Updates (cvt). */
  1803     if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1804         return -1;              /* shouldn't happen, but just in case... */
  1805 
  1806     /* Channel conversion */
  1807     if (src_channels != dst_channels) {
  1808         if ((src_channels == 1) && (dst_channels > 1)) {
  1809             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1810             cvt->len_mult *= 2;
  1811             src_channels = 2;
  1812             cvt->len_ratio *= 2;
  1813         }
  1814         if ((src_channels == 2) && (dst_channels == 6)) {
  1815             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
  1816             src_channels = 6;
  1817             cvt->len_mult *= 3;
  1818             cvt->len_ratio *= 3;
  1819         }
  1820         if ((src_channels == 2) && (dst_channels == 4)) {
  1821             cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
  1822             src_channels = 4;
  1823             cvt->len_mult *= 2;
  1824             cvt->len_ratio *= 2;
  1825         }
  1826         while ((src_channels * 2) <= dst_channels) {
  1827             cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
  1828             cvt->len_mult *= 2;
  1829             src_channels *= 2;
  1830             cvt->len_ratio *= 2;
  1831         }
  1832         if ((src_channels == 6) && (dst_channels <= 2)) {
  1833             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
  1834             src_channels = 2;
  1835             cvt->len_ratio /= 3;
  1836         }
  1837         if ((src_channels == 6) && (dst_channels == 4)) {
  1838             cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
  1839             src_channels = 4;
  1840             cvt->len_ratio /= 2;
  1841         }
  1842         /* This assumes that 4 channel audio is in the format:
  1843            Left {front/back} + Right {front/back}
  1844            so converting to L/R stereo works properly.
  1845          */
  1846         while (((src_channels % 2) == 0) &&
  1847                ((src_channels / 2) >= dst_channels)) {
  1848             cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
  1849             src_channels /= 2;
  1850             cvt->len_ratio /= 2;
  1851         }
  1852         if (src_channels != dst_channels) {
  1853             /* Uh oh.. */ ;
  1854         }
  1855     }
  1856 
  1857     /* Do rate conversion */
  1858 	int rate_gcd;
  1859 	rate_gcd = SDL_GCD(src_rate, dst_rate);
  1860 	cvt->len_mult = dst_rate / rate_gcd;
  1861 	cvt->len_div = src_rate / rate_gcd;
  1862 	cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div;
  1863 	cvt->filters[cvt->filter_index++] = SDL_Resample;
  1864 	//SDL_BuildIIRLowpass(cvt, dst_fmt);
  1865 	SDL_BuildWindowedSinc(cvt, dst_fmt, 12);
  1866 	
  1867     /*cvt->rate_incr = 0.0;
  1868     if ((src_rate / 100) != (dst_rate / 100)) {
  1869         Uint32 hi_rate, lo_rate;
  1870         int len_mult;
  1871         double len_ratio;
  1872         SDL_AudioFilter rate_cvt = NULL;
  1873 
  1874         if (src_rate > dst_rate) {
  1875             hi_rate = src_rate;
  1876             lo_rate = dst_rate;
  1877             switch (src_channels) {
  1878             case 1:
  1879                 rate_cvt = SDL_RateDIV2;
  1880                 break;
  1881             case 2:
  1882                 rate_cvt = SDL_RateDIV2_c2;
  1883                 break;
  1884             case 4:
  1885                 rate_cvt = SDL_RateDIV2_c4;
  1886                 break;
  1887             case 6:
  1888                 rate_cvt = SDL_RateDIV2_c6;
  1889                 break;
  1890             default:
  1891                 return -1;
  1892             }
  1893             len_mult = 1;
  1894             len_ratio = 0.5;
  1895         } else {
  1896             hi_rate = dst_rate;
  1897             lo_rate = src_rate;
  1898             switch (src_channels) {
  1899             case 1:
  1900                 rate_cvt = SDL_RateMUL2;
  1901                 break;
  1902             case 2:
  1903                 rate_cvt = SDL_RateMUL2_c2;
  1904                 break;
  1905             case 4:
  1906                 rate_cvt = SDL_RateMUL2_c4;
  1907                 break;
  1908             case 6:
  1909                 rate_cvt = SDL_RateMUL2_c6;
  1910                 break;
  1911             default:
  1912                 return -1;
  1913             }
  1914             len_mult = 2;
  1915             len_ratio = 2.0;
  1916         }*/
  1917         /* If hi_rate = lo_rate*2^x then conversion is easy */
  1918         /*while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1919             cvt->filters[cvt->filter_index++] = rate_cvt;
  1920             cvt->len_mult *= len_mult;
  1921             lo_rate *= 2;
  1922             cvt->len_ratio *= len_ratio;
  1923         }*/
  1924         /* We may need a slow conversion here to finish up */
  1925         /*if ((lo_rate / 100) != (hi_rate / 100)) {*/
  1926 #if 1
  1927             /* The problem with this is that if the input buffer is
  1928                say 1K, and the conversion rate is say 1.1, then the
  1929                output buffer is 1.1K, which may not be an acceptable
  1930                buffer size for the audio driver (not a power of 2)
  1931              */
  1932             /* For now, punt and hope the rate distortion isn't great.
  1933              */
  1934 #else
  1935             if (src_rate < dst_rate) {
  1936                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1937                 cvt->len_mult *= 2;
  1938                 cvt->len_ratio /= cvt->rate_incr;
  1939             } else {
  1940                 cvt->rate_incr = (double) hi_rate / lo_rate;
  1941                 cvt->len_ratio *= cvt->rate_incr;
  1942             }
  1943             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1944 #endif
  1945 /*        }
  1946     }*/
  1947 
  1948     /* Set up the filter information */
  1949     if (cvt->filter_index != 0) {
  1950         cvt->needed = 1;
  1951         cvt->src_format = src_fmt;
  1952         cvt->dst_format = dst_fmt;
  1953         cvt->len = 0;
  1954         cvt->buf = NULL;
  1955         cvt->filters[cvt->filter_index] = NULL;
  1956     }
  1957     return (cvt->needed);
  1958 }
  1959 
  1960 #undef SDL_FixMpy8
  1961 #undef SDL_FixMpy16
  1962 #undef SDL_FixMpy32
  1963 #undef SDL_Make_1_7
  1964 #undef SDL_Make_1_15
  1965 #undef SDL_Make_1_31
  1966 #undef SDL_Make_2_6
  1967 #undef SDL_Make_2_14
  1968 #undef SDL_Make_2_30
  1969 
  1970 /* vi: set ts=4 sw=4 expandtab: */