src/audio/SDL_audiocvt.c
changeset 3021 f3dcf04412cf
parent 3012 7e30c2dc7783
child 3032 77c3e67f0740
     1.1 --- a/src/audio/SDL_audiocvt.c	Sun Jan 11 04:46:14 2009 +0000
     1.2 +++ b/src/audio/SDL_audiocvt.c	Sun Jan 11 04:46:42 2009 +0000
     1.3 @@ -26,37 +26,12 @@
     1.4  #include "SDL_audio.h"
     1.5  #include "SDL_audio_c.h"
     1.6  
     1.7 -//#define DEBUG_CONVERT
     1.8 +/* #define DEBUG_CONVERT */
     1.9  
    1.10 -/* These are fractional multiplication routines. That is, their inputs
    1.11 -   are two numbers in the range [-1, 1) and the result falls in that
    1.12 -   same range. The output is the same size as the inputs, i.e.
    1.13 -   32-bit x 32-bit = 32-bit.
    1.14 - */
    1.15 -
    1.16 -/* We hope here that the right shift includes sign extension */
    1.17 -#ifdef SDL_HAS_64BIT_Type
    1.18 -#define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    1.19 -#else
    1.20 -/* 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 */
    1.21 -#define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
    1.22 +/* !!! FIXME */
    1.23 +#ifndef assert
    1.24 +#define assert(x)
    1.25  #endif
    1.26 -#define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
    1.27 -#define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
    1.28 -/* This macro just makes the floating point filtering code not have to be a special case. */
    1.29 -#define SDL_FloatMpy(a, b) (a * b)
    1.30 -
    1.31 -/* These macros take floating point numbers in the range [-1.0f, 1.0f) and
    1.32 -   represent them as fixed-point numbers in that same range. There's no
    1.33 -   checking that the floating point argument is inside the appropriate range.
    1.34 - */
    1.35 -
    1.36 -#define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
    1.37 -#define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
    1.38 -#define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
    1.39 -#define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
    1.40 -#define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
    1.41 -#define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
    1.42  
    1.43  /* Effectively mix right and left channels into a single channel */
    1.44  static void SDLCALL
    1.45 @@ -798,472 +773,13 @@
    1.46      }
    1.47  }
    1.48  
    1.49 -/* Convert rate up by multiple of 2 */
    1.50 -static void SDLCALL
    1.51 -SDL_RateMUL2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    1.52 -{
    1.53 -    int i;
    1.54 -
    1.55 -#ifdef DEBUG_CONVERT
    1.56 -    fprintf(stderr, "Converting audio rate * 2 (mono)\n");
    1.57 -#endif
    1.58 -
    1.59 -#define mul2_mono(type) { \
    1.60 -        const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
    1.61 -        type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
    1.62 -        for (i = cvt->len_cvt / sizeof (type); i; --i) { \
    1.63 -            src--; \
    1.64 -            dst[-1] = dst[-2] = src[0]; \
    1.65 -            dst -= 2; \
    1.66 -        } \
    1.67 -    }
    1.68 -
    1.69 -    switch (SDL_AUDIO_BITSIZE(format)) {
    1.70 -    case 8:
    1.71 -        mul2_mono(Uint8);
    1.72 -        break;
    1.73 -    case 16:
    1.74 -        mul2_mono(Uint16);
    1.75 -        break;
    1.76 -    case 32:
    1.77 -        mul2_mono(Uint32);
    1.78 -        break;
    1.79 -    }
    1.80 -
    1.81 -#undef mul2_mono
    1.82 -
    1.83 -    cvt->len_cvt *= 2;
    1.84 -    if (cvt->filters[++cvt->filter_index]) {
    1.85 -        cvt->filters[cvt->filter_index] (cvt, format);
    1.86 -    }
    1.87 -}
    1.88 -
    1.89 -
    1.90 -/* Convert rate up by multiple of 2, for stereo */
    1.91 -static void SDLCALL
    1.92 -SDL_RateMUL2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    1.93 -{
    1.94 -    int i;
    1.95 -
    1.96 -#ifdef DEBUG_CONVERT
    1.97 -    fprintf(stderr, "Converting audio rate * 2 (stereo)\n");
    1.98 -#endif
    1.99 -
   1.100 -#define mul2_stereo(type) { \
   1.101 -        const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   1.102 -        type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   1.103 -        for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   1.104 -            const type r = src[-1]; \
   1.105 -            const type l = src[-2]; \
   1.106 -            src -= 2; \
   1.107 -            dst[-1] = r; \
   1.108 -            dst[-2] = l; \
   1.109 -            dst[-3] = r; \
   1.110 -            dst[-4] = l; \
   1.111 -            dst -= 4; \
   1.112 -        } \
   1.113 -    }
   1.114 -
   1.115 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.116 -    case 8:
   1.117 -        mul2_stereo(Uint8);
   1.118 -        break;
   1.119 -    case 16:
   1.120 -        mul2_stereo(Uint16);
   1.121 -        break;
   1.122 -    case 32:
   1.123 -        mul2_stereo(Uint32);
   1.124 -        break;
   1.125 -    }
   1.126 -
   1.127 -#undef mul2_stereo
   1.128 -
   1.129 -    cvt->len_cvt *= 2;
   1.130 -    if (cvt->filters[++cvt->filter_index]) {
   1.131 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.132 -    }
   1.133 -}
   1.134 -
   1.135 -/* Convert rate up by multiple of 2, for quad */
   1.136 -static void SDLCALL
   1.137 -SDL_RateMUL2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.138 -{
   1.139 -    int i;
   1.140 -
   1.141 -#ifdef DEBUG_CONVERT
   1.142 -    fprintf(stderr, "Converting audio rate * 2 (quad)\n");
   1.143 -#endif
   1.144 -
   1.145 -#define mul2_quad(type) { \
   1.146 -        const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   1.147 -        type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   1.148 -        for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
   1.149 -            const type c1 = src[-1]; \
   1.150 -            const type c2 = src[-2]; \
   1.151 -            const type c3 = src[-3]; \
   1.152 -            const type c4 = src[-4]; \
   1.153 -            src -= 4; \
   1.154 -            dst[-1] = c1; \
   1.155 -            dst[-2] = c2; \
   1.156 -            dst[-3] = c3; \
   1.157 -            dst[-4] = c4; \
   1.158 -            dst[-5] = c1; \
   1.159 -            dst[-6] = c2; \
   1.160 -            dst[-7] = c3; \
   1.161 -            dst[-8] = c4; \
   1.162 -            dst -= 8; \
   1.163 -        } \
   1.164 -    }
   1.165 -
   1.166 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.167 -    case 8:
   1.168 -        mul2_quad(Uint8);
   1.169 -        break;
   1.170 -    case 16:
   1.171 -        mul2_quad(Uint16);
   1.172 -        break;
   1.173 -    case 32:
   1.174 -        mul2_quad(Uint32);
   1.175 -        break;
   1.176 -    }
   1.177 -
   1.178 -#undef mul2_quad
   1.179 -
   1.180 -    cvt->len_cvt *= 2;
   1.181 -    if (cvt->filters[++cvt->filter_index]) {
   1.182 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.183 -    }
   1.184 -}
   1.185 -
   1.186 -
   1.187 -/* Convert rate up by multiple of 2, for 5.1 */
   1.188 -static void SDLCALL
   1.189 -SDL_RateMUL2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.190 -{
   1.191 -    int i;
   1.192 -
   1.193 -#ifdef DEBUG_CONVERT
   1.194 -    fprintf(stderr, "Converting audio rate * 2 (six channels)\n");
   1.195 -#endif
   1.196 -
   1.197 -#define mul2_chansix(type) { \
   1.198 -        const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
   1.199 -        type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
   1.200 -        for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
   1.201 -            const type c1 = src[-1]; \
   1.202 -            const type c2 = src[-2]; \
   1.203 -            const type c3 = src[-3]; \
   1.204 -            const type c4 = src[-4]; \
   1.205 -            const type c5 = src[-5]; \
   1.206 -            const type c6 = src[-6]; \
   1.207 -            src -= 6; \
   1.208 -            dst[-1] = c1; \
   1.209 -            dst[-2] = c2; \
   1.210 -            dst[-3] = c3; \
   1.211 -            dst[-4] = c4; \
   1.212 -            dst[-5] = c5; \
   1.213 -            dst[-6] = c6; \
   1.214 -            dst[-7] = c1; \
   1.215 -            dst[-8] = c2; \
   1.216 -            dst[-9] = c3; \
   1.217 -            dst[-10] = c4; \
   1.218 -            dst[-11] = c5; \
   1.219 -            dst[-12] = c6; \
   1.220 -            dst -= 12; \
   1.221 -        } \
   1.222 -    }
   1.223 -
   1.224 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.225 -    case 8:
   1.226 -        mul2_chansix(Uint8);
   1.227 -        break;
   1.228 -    case 16:
   1.229 -        mul2_chansix(Uint16);
   1.230 -        break;
   1.231 -    case 32:
   1.232 -        mul2_chansix(Uint32);
   1.233 -        break;
   1.234 -    }
   1.235 -
   1.236 -#undef mul2_chansix
   1.237 -
   1.238 -    cvt->len_cvt *= 2;
   1.239 -    if (cvt->filters[++cvt->filter_index]) {
   1.240 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.241 -    }
   1.242 -}
   1.243 -
   1.244 -/* Convert rate down by multiple of 2 */
   1.245 -static void SDLCALL
   1.246 -SDL_RateDIV2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.247 -{
   1.248 -    int i;
   1.249 -
   1.250 -#ifdef DEBUG_CONVERT
   1.251 -    fprintf(stderr, "Converting audio rate / 2 (mono)\n");
   1.252 -#endif
   1.253 -
   1.254 -#define div2_mono(type) { \
   1.255 -        const type *src = (const type *) cvt->buf; \
   1.256 -        type *dst = (type *) cvt->buf; \
   1.257 -        for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
   1.258 -            dst[0] = src[0]; \
   1.259 -            src += 2; \
   1.260 -            dst++; \
   1.261 -        } \
   1.262 -    }
   1.263 -
   1.264 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.265 -    case 8:
   1.266 -        div2_mono(Uint8);
   1.267 -        break;
   1.268 -    case 16:
   1.269 -        div2_mono(Uint16);
   1.270 -        break;
   1.271 -    case 32:
   1.272 -        div2_mono(Uint32);
   1.273 -        break;
   1.274 -    }
   1.275 -
   1.276 -#undef div2_mono
   1.277 -
   1.278 -    cvt->len_cvt /= 2;
   1.279 -    if (cvt->filters[++cvt->filter_index]) {
   1.280 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.281 -    }
   1.282 -}
   1.283 -
   1.284 -
   1.285 -/* Convert rate down by multiple of 2, for stereo */
   1.286 -static void SDLCALL
   1.287 -SDL_RateDIV2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.288 -{
   1.289 -    int i;
   1.290 -
   1.291 -#ifdef DEBUG_CONVERT
   1.292 -    fprintf(stderr, "Converting audio rate / 2 (stereo)\n");
   1.293 -#endif
   1.294 -
   1.295 -#define div2_stereo(type) { \
   1.296 -        const type *src = (const type *) cvt->buf; \
   1.297 -        type *dst = (type *) cvt->buf; \
   1.298 -        for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
   1.299 -            dst[0] = src[0]; \
   1.300 -            dst[1] = src[1]; \
   1.301 -            src += 4; \
   1.302 -            dst += 2; \
   1.303 -        } \
   1.304 -    }
   1.305 -
   1.306 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.307 -    case 8:
   1.308 -        div2_stereo(Uint8);
   1.309 -        break;
   1.310 -    case 16:
   1.311 -        div2_stereo(Uint16);
   1.312 -        break;
   1.313 -    case 32:
   1.314 -        div2_stereo(Uint32);
   1.315 -        break;
   1.316 -    }
   1.317 -
   1.318 -#undef div2_stereo
   1.319 -
   1.320 -    cvt->len_cvt /= 2;
   1.321 -    if (cvt->filters[++cvt->filter_index]) {
   1.322 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.323 -    }
   1.324 -}
   1.325 -
   1.326 -
   1.327 -/* Convert rate down by multiple of 2, for quad */
   1.328 -static void SDLCALL
   1.329 -SDL_RateDIV2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.330 -{
   1.331 -    int i;
   1.332 -
   1.333 -#ifdef DEBUG_CONVERT
   1.334 -    fprintf(stderr, "Converting audio rate / 2 (quad)\n");
   1.335 -#endif
   1.336 -
   1.337 -#define div2_quad(type) { \
   1.338 -        const type *src = (const type *) cvt->buf; \
   1.339 -        type *dst = (type *) cvt->buf; \
   1.340 -        for (i = cvt->len_cvt / (sizeof (type) * 8); i; --i) { \
   1.341 -            dst[0] = src[0]; \
   1.342 -            dst[1] = src[1]; \
   1.343 -            dst[2] = src[2]; \
   1.344 -            dst[3] = src[3]; \
   1.345 -            src += 8; \
   1.346 -            dst += 4; \
   1.347 -        } \
   1.348 -    }
   1.349 -
   1.350 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.351 -    case 8:
   1.352 -        div2_quad(Uint8);
   1.353 -        break;
   1.354 -    case 16:
   1.355 -        div2_quad(Uint16);
   1.356 -        break;
   1.357 -    case 32:
   1.358 -        div2_quad(Uint32);
   1.359 -        break;
   1.360 -    }
   1.361 -
   1.362 -#undef div2_quad
   1.363 -
   1.364 -    cvt->len_cvt /= 2;
   1.365 -    if (cvt->filters[++cvt->filter_index]) {
   1.366 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.367 -    }
   1.368 -}
   1.369 -
   1.370 -/* Convert rate down by multiple of 2, for 5.1 */
   1.371 -static void SDLCALL
   1.372 -SDL_RateDIV2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.373 -{
   1.374 -    int i;
   1.375 -
   1.376 -#ifdef DEBUG_CONVERT
   1.377 -    fprintf(stderr, "Converting audio rate / 2 (six channels)\n");
   1.378 -#endif
   1.379 -
   1.380 -#define div2_chansix(type) { \
   1.381 -        const type *src = (const type *) cvt->buf; \
   1.382 -        type *dst = (type *) cvt->buf; \
   1.383 -        for (i = cvt->len_cvt / (sizeof (type) * 12); i; --i) { \
   1.384 -            dst[0] = src[0]; \
   1.385 -            dst[1] = src[1]; \
   1.386 -            dst[2] = src[2]; \
   1.387 -            dst[3] = src[3]; \
   1.388 -            dst[4] = src[4]; \
   1.389 -            dst[5] = src[5]; \
   1.390 -            src += 12; \
   1.391 -            dst += 6; \
   1.392 -        } \
   1.393 -    }
   1.394 -
   1.395 -    switch (SDL_AUDIO_BITSIZE(format)) {
   1.396 -    case 8:
   1.397 -        div2_chansix(Uint8);
   1.398 -        break;
   1.399 -    case 16:
   1.400 -        div2_chansix(Uint16);
   1.401 -        break;
   1.402 -    case 32:
   1.403 -        div2_chansix(Uint32);
   1.404 -        break;
   1.405 -    }
   1.406 -
   1.407 -#undef div_chansix
   1.408 -
   1.409 -    cvt->len_cvt /= 2;
   1.410 -    if (cvt->filters[++cvt->filter_index]) {
   1.411 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.412 -    }
   1.413 -}
   1.414 -
   1.415 -/* Very slow rate conversion routine */
   1.416 -static void SDLCALL
   1.417 -SDL_RateSLOW(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.418 -{
   1.419 -    double ipos;
   1.420 -    int i, clen;
   1.421 -
   1.422 -#ifdef DEBUG_CONVERT
   1.423 -    fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
   1.424 -#endif
   1.425 -    clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
   1.426 -    if (cvt->rate_incr > 1.0) {
   1.427 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.428 -        case 8:
   1.429 -            {
   1.430 -                Uint8 *output;
   1.431 -
   1.432 -                output = cvt->buf;
   1.433 -                ipos = 0.0;
   1.434 -                for (i = clen; i; --i) {
   1.435 -                    *output = cvt->buf[(int) ipos];
   1.436 -                    ipos += cvt->rate_incr;
   1.437 -                    output += 1;
   1.438 -                }
   1.439 -            }
   1.440 -            break;
   1.441 -
   1.442 -        case 16:
   1.443 -            {
   1.444 -                Uint16 *output;
   1.445 -
   1.446 -                clen &= ~1;
   1.447 -                output = (Uint16 *) cvt->buf;
   1.448 -                ipos = 0.0;
   1.449 -                for (i = clen / 2; i; --i) {
   1.450 -                    *output = ((Uint16 *) cvt->buf)[(int) ipos];
   1.451 -                    ipos += cvt->rate_incr;
   1.452 -                    output += 1;
   1.453 -                }
   1.454 -            }
   1.455 -            break;
   1.456 -
   1.457 -        case 32:
   1.458 -            {
   1.459 -                /* !!! FIXME: need 32-bit converter here! */
   1.460 -#ifdef DEBUG_CONVERT
   1.461 -                fprintf(stderr, "FIXME: need 32-bit converter here!\n");
   1.462 -#endif
   1.463 -            }
   1.464 -        }
   1.465 -    } else {
   1.466 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.467 -        case 8:
   1.468 -            {
   1.469 -                Uint8 *output;
   1.470 -
   1.471 -                output = cvt->buf + clen;
   1.472 -                ipos = (double) cvt->len_cvt;
   1.473 -                for (i = clen; i; --i) {
   1.474 -                    ipos -= cvt->rate_incr;
   1.475 -                    output -= 1;
   1.476 -                    *output = cvt->buf[(int) ipos];
   1.477 -                }
   1.478 -            }
   1.479 -            break;
   1.480 -
   1.481 -        case 16:
   1.482 -            {
   1.483 -                Uint16 *output;
   1.484 -
   1.485 -                clen &= ~1;
   1.486 -                output = (Uint16 *) (cvt->buf + clen);
   1.487 -                ipos = (double) cvt->len_cvt / 2;
   1.488 -                for (i = clen / 2; i; --i) {
   1.489 -                    ipos -= cvt->rate_incr;
   1.490 -                    output -= 1;
   1.491 -                    *output = ((Uint16 *) cvt->buf)[(int) ipos];
   1.492 -                }
   1.493 -            }
   1.494 -            break;
   1.495 -
   1.496 -        case 32:
   1.497 -            {
   1.498 -                /* !!! FIXME: need 32-bit converter here! */
   1.499 -#ifdef DEBUG_CONVERT
   1.500 -                fprintf(stderr, "FIXME: need 32-bit converter here!\n");
   1.501 -#endif
   1.502 -            }
   1.503 -        }
   1.504 -    }
   1.505 -
   1.506 -    cvt->len_cvt = clen;
   1.507 -    if (cvt->filters[++cvt->filter_index]) {
   1.508 -        cvt->filters[cvt->filter_index] (cvt, format);
   1.509 -    }
   1.510 -}
   1.511  
   1.512  int
   1.513  SDL_ConvertAudio(SDL_AudioCVT * cvt)
   1.514  {
   1.515 +    /* !!! FIXME: (cvt) should be const; stack-copy it here. */
   1.516 +    /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
   1.517 +
   1.518      /* Make sure there's data to convert */
   1.519      if (cvt->buf == NULL) {
   1.520          SDL_SetError("No buffer allocated for conversion");
   1.521 @@ -1341,478 +857,96 @@
   1.522      return 0;                   /* no conversion necessary. */
   1.523  }
   1.524  
   1.525 -/* Generate the necessary IIR lowpass coefficients for resampling.
   1.526 -   Assume that the SDL_AudioCVT struct is already set up with
   1.527 -   the correct values for len_mult and len_div, and use the
   1.528 -   type of dst_format. Also assume the buffer is allocated.
   1.529 -   Note the buffer needs to be 6 units long.
   1.530 -   For now, use RBJ's cookbook coefficients. It might be more
   1.531 -   optimal to create a Butterworth filter, but this is more difficult.
   1.532 -*/
   1.533 -#if 0
   1.534 -int
   1.535 -SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.536 +
   1.537 +static SDL_AudioFilter
   1.538 +SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
   1.539 +                         int src_rate, int dst_rate)
   1.540  {
   1.541 -    float fc;                   /* cutoff frequency */
   1.542 -    float coeff[6];             /* floating point iir coefficients b0, b1, b2, a0, a1, a2 */
   1.543 -    float scale;
   1.544 -    float w0, alpha, cosw0;
   1.545 -    int i;
   1.546 +    /*
   1.547 +     * Fill in any future conversions that are specialized to a
   1.548 +     *  processor, platform, compiler, or library here.
   1.549 +     */
   1.550  
   1.551 -    /* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */
   1.552 -    static const float Q = 5.0f;
   1.553 -    static const float CUTOFF = 0.4f;
   1.554 +    return NULL;                /* no specialized converter code available. */
   1.555 +}
   1.556  
   1.557 -    fc = (cvt->len_mult >
   1.558 -          cvt->len_div) ? CUTOFF / (float) cvt->len_mult : CUTOFF /
   1.559 -        (float) cvt->len_div;
   1.560 +static int
   1.561 +SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
   1.562 +{
   1.563 +    int retval = 0;
   1.564  
   1.565 -    w0 = 2.0f * M_PI * fc;
   1.566 -    cosw0 = cosf(w0);
   1.567 -    alpha = sinf(w0) / (2.0f * Q);
   1.568 +    /* If we only built with the arbitrary resamplers, ignore multiples. */
   1.569 +#if !LESS_RESAMPLERS
   1.570 +    int lo, hi;
   1.571 +    int div;
   1.572  
   1.573 -    /* Compute coefficients, normalizing by a0 */
   1.574 -    scale = 1.0f / (1.0f + alpha);
   1.575 +    assert(src_rate != 0);
   1.576 +    assert(dst_rate != 0);
   1.577 +    assert(src_rate != dst_rate);
   1.578  
   1.579 -    coeff[0] = (1.0f - cosw0) / 2.0f * scale;
   1.580 -    coeff[1] = (1.0f - cosw0) * scale;
   1.581 -    coeff[2] = coeff[0];
   1.582 +    if (src_rate < dst_rate) {
   1.583 +        lo = src_rate;
   1.584 +        hi = dst_rate;
   1.585 +    } else {
   1.586 +        lo = dst_rate;
   1.587 +        hi = src_rate;
   1.588 +    }
   1.589  
   1.590 -    coeff[3] = 1.0f;            /* a0 is normalized to 1 */
   1.591 -    coeff[4] = -2.0f * cosw0 * scale;
   1.592 -    coeff[5] = (1.0f - alpha) * scale;
   1.593 +    /* zero means "not a supported multiple" ... we only do 2x and 4x. */
   1.594 +    if ((hi % lo) != 0)
   1.595 +        return 0;   /* not a multiple. */
   1.596  
   1.597 -    /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */
   1.598 -#define convert_fixed(type, fix) { \
   1.599 -            type *cvt_coeff = (type *)cvt->coeff; \
   1.600 -            for(i = 0; i < 6; ++i) { \
   1.601 -                cvt_coeff[i] = fix(coeff[i]); \
   1.602 -            } \
   1.603 +    div = hi / lo;
   1.604 +    retval = ((div == 2) || (div == 4)) ? div : 0;
   1.605 +#endif
   1.606 +
   1.607 +    return retval;
   1.608 +}
   1.609 +
   1.610 +static int
   1.611 +SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
   1.612 +                          int src_rate, int dst_rate)
   1.613 +{
   1.614 +    if (src_rate != dst_rate) {
   1.615 +        SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
   1.616 +                                                          src_rate, dst_rate);
   1.617 +
   1.618 +        /* No hand-tuned converter? Try the autogenerated ones. */
   1.619 +        if (filter == NULL) {
   1.620 +            int i;
   1.621 +            const int upsample = (src_rate < dst_rate) ? 1 : 0;
   1.622 +            const int multiple = SDL_FindFrequencyMultiple(src_rate, dst_rate);
   1.623 +
   1.624 +            for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
   1.625 +                const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i];
   1.626 +                if ((filt->fmt == cvt->dst_format) &&
   1.627 +                    (filt->channels == dst_channels) &&
   1.628 +                    (filt->upsample == upsample) &&
   1.629 +                    (filt->multiple == multiple)) {
   1.630 +                    filter = filt->filter;
   1.631 +                    break;
   1.632 +                }
   1.633 +            }
   1.634 +
   1.635 +            if (filter == NULL) {
   1.636 +                return -1;      /* Still no matching converter?! */
   1.637 +            }
   1.638          }
   1.639  
   1.640 -    if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
   1.641 -        float *cvt_coeff = (float *) cvt->coeff;
   1.642 -        for (i = 0; i < 6; ++i) {
   1.643 -            cvt_coeff[i] = coeff[i];
   1.644 +        /* Update (cvt) with filter details... */
   1.645 +        cvt->filters[cvt->filter_index++] = filter;
   1.646 +        if (src_rate < dst_rate) {
   1.647 +            const double mult = ((double) dst_rate) / ((double) src_rate);
   1.648 +            cvt->len_mult *= (int) ceil(mult);  /* !!! FIXME: C runtime dependency. */
   1.649 +            cvt->len_ratio *= mult;
   1.650 +        } else {
   1.651 +            cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
   1.652          }
   1.653 -    } else {
   1.654 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.655 -        case 8:
   1.656 -            convert_fixed(Uint8, SDL_Make_2_6);
   1.657 -            break;
   1.658 -        case 16:
   1.659 -            convert_fixed(Uint16, SDL_Make_2_14);
   1.660 -            break;
   1.661 -        case 32:
   1.662 -            convert_fixed(Uint32, SDL_Make_2_30);
   1.663 -            break;
   1.664 -        }
   1.665 +
   1.666 +        return 1;               /* added a converter. */
   1.667      }
   1.668  
   1.669 -#ifdef DEBUG_CONVERT
   1.670 -#define debug_iir(type) { \
   1.671 -            type *cvt_coeff = (type *)cvt->coeff; \
   1.672 -            for(i = 0; i < 6; ++i) { \
   1.673 -                printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \
   1.674 -            } \
   1.675 -        }
   1.676 -    if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
   1.677 -        float *cvt_coeff = (float *) cvt->coeff;
   1.678 -        for (i = 0; i < 6; ++i) {
   1.679 -            printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]);
   1.680 -        }
   1.681 -    } else {
   1.682 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.683 -        case 8:
   1.684 -            debug_iir(Uint8);
   1.685 -            break;
   1.686 -        case 16:
   1.687 -            debug_iir(Uint16);
   1.688 -            break;
   1.689 -        case 32:
   1.690 -            debug_iir(Uint32);
   1.691 -            break;
   1.692 -        }
   1.693 -    }
   1.694 -#undef debug_iir
   1.695 -#endif
   1.696 -
   1.697 -    /* Initialize the state buffer to all zeroes, and set initial position */
   1.698 -    SDL_memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4);
   1.699 -    cvt->state_pos = 0;
   1.700 -#undef convert_fixed
   1.701 -
   1.702 -    return 0;
   1.703 -}
   1.704 -#endif
   1.705 -
   1.706 -/* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
   1.707 -/* This was implemented because it would be much faster than the fir filter, 
   1.708 -   but it doesn't seem to have a steep enough cutoff so we'd need several
   1.709 -   cascaded biquads, which probably isn't a great idea. Therefore, this
   1.710 -   function can probably be discarded.
   1.711 -*/
   1.712 -static void
   1.713 -SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.714 -{
   1.715 -    Uint32 i, n;
   1.716 -
   1.717 -    /* TODO: Check that n is calculated right */
   1.718 -    n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
   1.719 -
   1.720 -    /* 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. */
   1.721 -    /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
   1.722 -#define iir_fix(type, mult) {\
   1.723 -            type *coeff = (type *)cvt->coeff; \
   1.724 -            type *state = (type *)cvt->state_buf; \
   1.725 -            type *buf = (type *)cvt->buf; \
   1.726 -            type temp; \
   1.727 -            for(i = 0; i < n; ++i) { \
   1.728 -                    temp = buf[i] >> 1; \
   1.729 -                    if(cvt->state_pos) { \
   1.730 -                        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]); \
   1.731 -                        state[1] = temp; \
   1.732 -                        state[3] = buf[i]; \
   1.733 -                        cvt->state_pos = 0; \
   1.734 -                    } else { \
   1.735 -                        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]); \
   1.736 -                        state[0] = temp; \
   1.737 -                        state[2] = buf[i]; \
   1.738 -                        cvt->state_pos = 1; \
   1.739 -                    } \
   1.740 -                } \
   1.741 -        }
   1.742 -/* Need to test to see if the previous method or this one is faster */
   1.743 -/*#define iir_fix(type, mult) {\
   1.744 -            type *coeff = (type *)cvt->coeff; \
   1.745 -            type *state = (type *)cvt->state_buf; \
   1.746 -            type *buf = (type *)cvt->buf; \
   1.747 -            type temp; \
   1.748 -            for(i = 0; i < n; ++i) { \
   1.749 -                    temp = buf[i] >> 1; \
   1.750 -                    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]); \
   1.751 -                    state[1] = state[0]; \
   1.752 -                    state[0] = temp; \
   1.753 -                    state[3] = state[2]; \
   1.754 -                    state[2] = buf[i]; \
   1.755 -                } \
   1.756 -        }*/
   1.757 -
   1.758 -    if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
   1.759 -        float *coeff = (float *) cvt->coeff;
   1.760 -        float *state = (float *) cvt->state_buf;
   1.761 -        float *buf = (float *) cvt->buf;
   1.762 -        float temp;
   1.763 -
   1.764 -        for (i = 0; i < n; ++i) {
   1.765 -            /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
   1.766 -            temp = buf[i];
   1.767 -            if (cvt->state_pos) {
   1.768 -                buf[i] =
   1.769 -                    coeff[0] * buf[n] + coeff[1] * state[0] +
   1.770 -                    coeff[2] * state[1] - coeff[4] * state[2] -
   1.771 -                    coeff[5] * state[3];
   1.772 -                state[1] = temp;
   1.773 -                state[3] = buf[i];
   1.774 -                cvt->state_pos = 0;
   1.775 -            } else {
   1.776 -                buf[i] =
   1.777 -                    coeff[0] * buf[n] + coeff[1] * state[1] +
   1.778 -                    coeff[2] * state[0] - coeff[4] * state[3] -
   1.779 -                    coeff[5] * state[2];
   1.780 -                state[0] = temp;
   1.781 -                state[2] = buf[i];
   1.782 -                cvt->state_pos = 1;
   1.783 -            }
   1.784 -        }
   1.785 -    } else {
   1.786 -        /* Treat everything as signed! */
   1.787 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.788 -        case 8:
   1.789 -            iir_fix(Sint8, SDL_FixMpy8);
   1.790 -            break;
   1.791 -        case 16:
   1.792 -            iir_fix(Sint16, SDL_FixMpy16);
   1.793 -            break;
   1.794 -        case 32:
   1.795 -            iir_fix(Sint32, SDL_FixMpy32);
   1.796 -            break;
   1.797 -        }
   1.798 -    }
   1.799 -#undef iir_fix
   1.800 -}
   1.801 -
   1.802 -/* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct.
   1.803 -*/
   1.804 -static void
   1.805 -SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.806 -{
   1.807 -    /* !!! FIXME: (n) is incorrect, or my allocation of state_buf is wrong. */
   1.808 -    const int n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
   1.809 -    int m = cvt->len_sinc;
   1.810 -    int i, j;
   1.811 -
   1.812 -    /* 
   1.813 -       Note: We can make a big optimization here by taking advantage
   1.814 -       of the fact that the signal is zero stuffed, so we can do
   1.815 -       significantly fewer multiplications and additions. However, this
   1.816 -       depends on the zero stuffing ratio, so it may not pay off. This would
   1.817 -       basically be a polyphase filter.
   1.818 -     */
   1.819 -    /* One other way to do this fast is to look at the fir filter from a different angle:
   1.820 -       After we zero stuff, we have input of all zeroes, except for every len_mult
   1.821 -       sample. If we choose a sinc length equal to len_mult, then the fir filter becomes
   1.822 -       much more simple: we're just taking a windowed sinc, shifting it to start at each
   1.823 -       len_mult sample, and scaling it by the value of that sample. If we do this, then
   1.824 -       we don't even need to worry about the sample histories, and the inner loop here is
   1.825 -       unnecessary. This probably sacrifices some quality but could really speed things up as well.
   1.826 -     */
   1.827 -    /* We only calculate the values of samples which are 0 (mod len_div) because
   1.828 -       those are the only ones used. All the other ones are discarded in the
   1.829 -       third step of resampling. This is a huge speedup. As a warning, though,
   1.830 -       if for some reason this is used elsewhere where there are no samples discarded,
   1.831 -       the output will not be corrrect if len_div is not 1. To make this filter a
   1.832 -       generic FIR filter, simply remove the if statement "if(i % cvt->len_div == 0)"
   1.833 -       around the inner loop so that every sample is processed.
   1.834 -     */
   1.835 -    /* This is basically just a FIR filter. i.e. for input x_n and m coefficients,
   1.836 -       y_n = x_n*sinc_0 + x_(n-1)*sinc_1 +  x_(n-2)*sinc_2 + ... + x_(n-m+1)*sinc_(m-1)
   1.837 -     */
   1.838 -#define filter_sinc(type, mult) { \
   1.839 -            type *sinc = (type *)cvt->coeff; \
   1.840 -            type *state = (type *)cvt->state_buf; \
   1.841 -            type *buf = (type *)cvt->buf; \
   1.842 -            for(i = 0; i < n; ++i) { \
   1.843 -                state[cvt->state_pos] = buf[i]; \
   1.844 -                buf[i] = 0; \
   1.845 -                if( i % cvt->len_div == 0 ) { \
   1.846 -                    for(j = 0; j < m;  ++j) { \
   1.847 -                        buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \
   1.848 -                    } \
   1.849 -                }\
   1.850 -                cvt->state_pos = (cvt->state_pos + 1) % m; \
   1.851 -            } \
   1.852 -        }
   1.853 -
   1.854 -    if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
   1.855 -        filter_sinc(float, SDL_FloatMpy);
   1.856 -    } else {
   1.857 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.858 -        case 8:
   1.859 -            filter_sinc(Sint8, SDL_FixMpy8);
   1.860 -            break;
   1.861 -        case 16:
   1.862 -            filter_sinc(Sint16, SDL_FixMpy16);
   1.863 -            break;
   1.864 -        case 32:
   1.865 -            filter_sinc(Sint32, SDL_FixMpy32);
   1.866 -            break;
   1.867 -        }
   1.868 -    }
   1.869 -
   1.870 -#undef filter_sinc
   1.871 -
   1.872 -}
   1.873 -
   1.874 -/* Generate the necessary windowed sinc filter for resampling.
   1.875 -   Assume that the SDL_AudioCVT struct is already set up with
   1.876 -   the correct values for len_mult and len_div, and use the
   1.877 -   type of dst_format. Also assume the buffer is allocated.
   1.878 -   Note the buffer needs to be m+1 units long.
   1.879 -*/
   1.880 -int
   1.881 -SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format,
   1.882 -                      unsigned int m)
   1.883 -{
   1.884 -    float *fSinc;               /* floating point sinc buffer, to be converted to fixed point */
   1.885 -    float fc;                   /* cutoff frequency */
   1.886 -    float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
   1.887 -    float norm_sum, norm_fact;
   1.888 -    unsigned int i;
   1.889 -
   1.890 -    /* Set the length */
   1.891 -    cvt->len_sinc = m + 1;
   1.892 -
   1.893 -    /* Allocate the floating point windowed sinc. */
   1.894 -    fSinc = SDL_stack_alloc(float, (m + 1));
   1.895 -    if (fSinc == NULL) {
   1.896 -        return -1;
   1.897 -    }
   1.898 -
   1.899 -    /* Set up the filter parameters */
   1.900 -    fc = (cvt->len_mult >
   1.901 -          cvt->len_div) ? 0.5f / (float) cvt->len_mult : 0.5f /
   1.902 -        (float) cvt->len_div;
   1.903 -#ifdef DEBUG_CONVERT
   1.904 -    printf("Lowpass cutoff frequency = %f\n", fc);
   1.905 -#endif
   1.906 -    two_pi_fc = 2.0f * M_PI * fc;
   1.907 -    two_pi_over_m = 2.0f * M_PI / (float) m;
   1.908 -    four_pi_over_m = 2.0f * two_pi_over_m;
   1.909 -    m_over_two = (float) m / 2.0f;
   1.910 -    norm_sum = 0.0f;
   1.911 -
   1.912 -    for (i = 0; i <= m; ++i) {
   1.913 -        if (i == m / 2) {
   1.914 -            fSinc[i] = two_pi_fc;
   1.915 -        } else {
   1.916 -            fSinc[i] = SDL_sinf(two_pi_fc * ((float) i - m_over_two)) / ((float) i - m_over_two);
   1.917 -            /* Apply blackman window */
   1.918 -            fSinc[i] *= 0.42f - 0.5f * SDL_cosf(two_pi_over_m * (float) i) + 0.08f * SDL_cosf(four_pi_over_m * (float) i);
   1.919 -        }
   1.920 -        norm_sum += fSinc[i] < 0 ? -fSinc[i] : fSinc[i];        /* fabs(fSinc[i]); */
   1.921 -    }
   1.922 -
   1.923 -    norm_fact = 1.0f / norm_sum;
   1.924 -
   1.925 -#define convert_fixed(type, fix) { \
   1.926 -        type *dst = (type *)cvt->coeff; \
   1.927 -        for( i = 0; i <= m; ++i ) { \
   1.928 -            dst[i] = fix(fSinc[i] * norm_fact); \
   1.929 -        } \
   1.930 -    }
   1.931 -
   1.932 -    /* !!! FIXME: this memory leaks. */
   1.933 -    cvt->coeff =
   1.934 -        (Uint8 *) SDL_malloc((SDL_AUDIO_BITSIZE(format) / 8) * (m + 1));
   1.935 -    if (cvt->coeff == NULL) {
   1.936 -        return -1;
   1.937 -    }
   1.938 -
   1.939 -    /* If we're using floating point, we only need to normalize */
   1.940 -    if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
   1.941 -        float *fDest = (float *) cvt->coeff;
   1.942 -        for (i = 0; i <= m; ++i) {
   1.943 -            fDest[i] = fSinc[i] * norm_fact;
   1.944 -        }
   1.945 -    } else {
   1.946 -        switch (SDL_AUDIO_BITSIZE(format)) {
   1.947 -        case 8:
   1.948 -            convert_fixed(Uint8, SDL_Make_1_7);
   1.949 -            break;
   1.950 -        case 16:
   1.951 -            convert_fixed(Uint16, SDL_Make_1_15);
   1.952 -            break;
   1.953 -        case 32:
   1.954 -            convert_fixed(Uint32, SDL_Make_1_31);
   1.955 -            break;
   1.956 -        }
   1.957 -    }
   1.958 -
   1.959 -    /* Initialize the state buffer to all zeroes, and set initial position */
   1.960 -    /* !!! FIXME: this memory leaks. */
   1.961 -    cvt->state_buf =
   1.962 -        (Uint8 *) SDL_malloc(cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
   1.963 -    if (cvt->state_buf == NULL) {
   1.964 -        return -1;
   1.965 -    }
   1.966 -    SDL_memset(cvt->state_buf, 0,
   1.967 -               cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
   1.968 -    cvt->state_pos = 0;
   1.969 -
   1.970 -    /* Clean up */
   1.971 -#undef convert_fixed
   1.972 -    SDL_stack_free(fSinc);
   1.973 -
   1.974 -    return 0;
   1.975 -}
   1.976 -
   1.977 -/* This is used to reduce the resampling ratio */
   1.978 -static __inline__ int
   1.979 -SDL_GCD(int a, int b)
   1.980 -{
   1.981 -    int temp;
   1.982 -    while (b != 0) {
   1.983 -        temp = a % b;
   1.984 -        a = b;
   1.985 -        b = temp;
   1.986 -    }
   1.987 -    return a;
   1.988 -}
   1.989 -
   1.990 -/* Perform proper resampling. This is pretty slow but it's the best-sounding method. */
   1.991 -static void SDLCALL
   1.992 -SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   1.993 -{
   1.994 -    int i;
   1.995 -
   1.996 -#ifdef DEBUG_CONVERT
   1.997 -    printf("Converting audio rate via proper resampling (mono)\n");
   1.998 -#endif
   1.999 -
  1.1000 -#define zerostuff_mono(type) { \
  1.1001 -        const type *src = (const type *) (cvt->buf + cvt->len); \
  1.1002 -        type *dst = (type *) (cvt->buf + (cvt->len * cvt->len_mult)); \
  1.1003 -        for (i = cvt->len / sizeof (type); i; --i) { \
  1.1004 -            src--; \
  1.1005 -            dst[-1] = src[0]; \
  1.1006 -            if (cvt->len_mult > 1) { \
  1.1007 -                SDL_memset(dst-cvt->len_mult, 0, cvt->len_mult-1); \
  1.1008 -            } \
  1.1009 -            dst -= cvt->len_mult; \
  1.1010 -        } \
  1.1011 -    }
  1.1012 -
  1.1013 -#define discard_mono(type) { \
  1.1014 -        const type *src = (const type *) (cvt->buf); \
  1.1015 -        type *dst = (type *) (cvt->buf); \
  1.1016 -        for (i = 0; i < (cvt->len_cvt / sizeof(type)) / cvt->len_div; ++i) { \
  1.1017 -            dst[0] = src[0]; \
  1.1018 -            src += cvt->len_div; \
  1.1019 -            ++dst; \
  1.1020 -        } \
  1.1021 -    }
  1.1022 -
  1.1023 -    /* Step 1: Zero stuff the conversion buffer. This upsamples by a factor of len_mult,
  1.1024 -       creating aliasing at frequencies above the original nyquist frequency.
  1.1025 -     */
  1.1026 -#ifdef DEBUG_CONVERT
  1.1027 -    printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
  1.1028 -#endif
  1.1029 -    switch (SDL_AUDIO_BITSIZE(format)) {
  1.1030 -    case 8:
  1.1031 -        zerostuff_mono(Uint8);
  1.1032 -        break;
  1.1033 -    case 16:
  1.1034 -        zerostuff_mono(Uint16);
  1.1035 -        break;
  1.1036 -    case 32:
  1.1037 -        zerostuff_mono(Uint32);
  1.1038 -        break;
  1.1039 -    }
  1.1040 -
  1.1041 -    cvt->len_cvt *= cvt->len_mult;
  1.1042 -
  1.1043 -    /* Step 2: Use a windowed sinc FIR filter (lowpass filter) to remove the alias
  1.1044 -       frequencies. This is the slow part.
  1.1045 -     */
  1.1046 -    SDL_FilterFIR(cvt, format);
  1.1047 -
  1.1048 -    /* Step 3: Now downsample by discarding samples. */
  1.1049 -
  1.1050 -#ifdef DEBUG_CONVERT
  1.1051 -    printf("Discarding samples by a factor of %u\n", cvt->len_div);
  1.1052 -#endif
  1.1053 -    switch (SDL_AUDIO_BITSIZE(format)) {
  1.1054 -    case 8:
  1.1055 -        discard_mono(Uint8);
  1.1056 -        break;
  1.1057 -    case 16:
  1.1058 -        discard_mono(Uint16);
  1.1059 -        break;
  1.1060 -    case 32:
  1.1061 -        discard_mono(Uint32);
  1.1062 -        break;
  1.1063 -    }
  1.1064 -
  1.1065 -#undef zerostuff_mono
  1.1066 -#undef discard_mono
  1.1067 -
  1.1068 -    cvt->len_cvt /= cvt->len_div;
  1.1069 -
  1.1070 -    if (cvt->filters[++cvt->filter_index]) {
  1.1071 -        cvt->filters[cvt->filter_index] (cvt, format);
  1.1072 -    }
  1.1073 +    return 0;                   /* no conversion necessary. */
  1.1074  }
  1.1075  
  1.1076  
  1.1077 @@ -1826,6 +960,14 @@
  1.1078                    SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
  1.1079                    SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
  1.1080  {
  1.1081 +    /*
  1.1082 +     * !!! FIXME: reorder filters based on which grow/shrink the buffer.
  1.1083 +     * !!! FIXME: ideally, we should do everything that shrinks the buffer
  1.1084 +     * !!! FIXME: first, so we don't have to process as many bytes in a given
  1.1085 +     * !!! FIXME: filter and abuse the CPU cache less. This might not be as
  1.1086 +     * !!! FIXME: good in practice as it sounds in theory, though.
  1.1087 +     */
  1.1088 +
  1.1089      /* there are no unsigned types over 16 bits, so catch this upfront. */
  1.1090      if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
  1.1091          return -1;
  1.1092 @@ -1833,6 +975,12 @@
  1.1093      if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
  1.1094          return -1;
  1.1095      }
  1.1096 +
  1.1097 +    /* prevent possible divisions by zero, etc. */
  1.1098 +    if ((src_rate == 0) || (dst_rate == 0)) {
  1.1099 +        return -1;
  1.1100 +    }
  1.1101 +
  1.1102  #ifdef DEBUG_CONVERT
  1.1103      printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
  1.1104             src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
  1.1105 @@ -1847,10 +995,12 @@
  1.1106      cvt->filters[0] = NULL;
  1.1107      cvt->len_mult = 1;
  1.1108      cvt->len_ratio = 1.0;
  1.1109 +    cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
  1.1110  
  1.1111      /* Convert data types, if necessary. Updates (cvt). */
  1.1112 -    if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1)
  1.1113 +    if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) {
  1.1114          return -1;              /* shouldn't happen, but just in case... */
  1.1115 +    }
  1.1116  
  1.1117      /* Channel conversion */
  1.1118      if (src_channels != dst_channels) {
  1.1119 @@ -1903,100 +1053,11 @@
  1.1120          }
  1.1121      }
  1.1122  
  1.1123 -    /* Do rate conversion */
  1.1124 -    if (src_rate != dst_rate) {
  1.1125 -        int rate_gcd;
  1.1126 -        rate_gcd = SDL_GCD(src_rate, dst_rate);
  1.1127 -        cvt->len_mult = dst_rate / rate_gcd;
  1.1128 -        cvt->len_div = src_rate / rate_gcd;
  1.1129 -        cvt->len_ratio = (double) cvt->len_mult / (double) cvt->len_div;
  1.1130 -        cvt->filters[cvt->filter_index++] = SDL_Resample;
  1.1131 -        /* !!! FIXME: check return value. */
  1.1132 -        SDL_BuildWindowedSinc(cvt, dst_fmt, 768);
  1.1133 +    /* Do rate conversion, if necessary. Updates (cvt). */
  1.1134 +    if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) == -1) {
  1.1135 +        return -1;              /* shouldn't happen, but just in case... */
  1.1136      }
  1.1137  
  1.1138 -/*
  1.1139 -    cvt->rate_incr = 0.0;
  1.1140 -    if ((src_rate / 100) != (dst_rate / 100)) {
  1.1141 -        Uint32 hi_rate, lo_rate;
  1.1142 -        int len_mult;
  1.1143 -        double len_ratio;
  1.1144 -        SDL_AudioFilter rate_cvt = NULL;
  1.1145 -
  1.1146 -        if (src_rate > dst_rate) {
  1.1147 -            hi_rate = src_rate;
  1.1148 -            lo_rate = dst_rate;
  1.1149 -            switch (src_channels) {
  1.1150 -            case 1:
  1.1151 -                rate_cvt = SDL_RateDIV2;
  1.1152 -                break;
  1.1153 -            case 2:
  1.1154 -                rate_cvt = SDL_RateDIV2_c2;
  1.1155 -                break;
  1.1156 -            case 4:
  1.1157 -                rate_cvt = SDL_RateDIV2_c4;
  1.1158 -                break;
  1.1159 -            case 6:
  1.1160 -                rate_cvt = SDL_RateDIV2_c6;
  1.1161 -                break;
  1.1162 -            default:
  1.1163 -                return -1;
  1.1164 -            }
  1.1165 -            len_mult = 1;
  1.1166 -            len_ratio = 0.5;
  1.1167 -        } else {
  1.1168 -            hi_rate = dst_rate;
  1.1169 -            lo_rate = src_rate;
  1.1170 -            switch (src_channels) {
  1.1171 -            case 1:
  1.1172 -                rate_cvt = SDL_RateMUL2;
  1.1173 -                break;
  1.1174 -            case 2:
  1.1175 -                rate_cvt = SDL_RateMUL2_c2;
  1.1176 -                break;
  1.1177 -            case 4:
  1.1178 -                rate_cvt = SDL_RateMUL2_c4;
  1.1179 -                break;
  1.1180 -            case 6:
  1.1181 -                rate_cvt = SDL_RateMUL2_c6;
  1.1182 -                break;
  1.1183 -            default:
  1.1184 -                return -1;
  1.1185 -            }
  1.1186 -            len_mult = 2;
  1.1187 -            len_ratio = 2.0;
  1.1188 -        }*/
  1.1189 -    /* If hi_rate = lo_rate*2^x then conversion is easy */
  1.1190 -    /*   while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1.1191 -       cvt->filters[cvt->filter_index++] = rate_cvt;
  1.1192 -       cvt->len_mult *= len_mult;
  1.1193 -       lo_rate *= 2;
  1.1194 -       cvt->len_ratio *= len_ratio;
  1.1195 -       } */
  1.1196 -    /* We may need a slow conversion here to finish up */
  1.1197 -    /*    if ((lo_rate / 100) != (hi_rate / 100)) {
  1.1198 -       #if 1 */
  1.1199 -    /* The problem with this is that if the input buffer is
  1.1200 -       say 1K, and the conversion rate is say 1.1, then the
  1.1201 -       output buffer is 1.1K, which may not be an acceptable
  1.1202 -       buffer size for the audio driver (not a power of 2)
  1.1203 -     */
  1.1204 -    /* For now, punt and hope the rate distortion isn't great.
  1.1205 -     */
  1.1206 -/*#else
  1.1207 -            if (src_rate < dst_rate) {
  1.1208 -                cvt->rate_incr = (double) lo_rate / hi_rate;
  1.1209 -                cvt->len_mult *= 2;
  1.1210 -                cvt->len_ratio /= cvt->rate_incr;
  1.1211 -            } else {
  1.1212 -                cvt->rate_incr = (double) hi_rate / lo_rate;
  1.1213 -                cvt->len_ratio *= cvt->rate_incr;
  1.1214 -            }
  1.1215 -            cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1.1216 -#endif
  1.1217 -        }
  1.1218 -    }*/
  1.1219 -
  1.1220      /* Set up the filter information */
  1.1221      if (cvt->filter_index != 0) {
  1.1222          cvt->needed = 1;
  1.1223 @@ -2009,15 +1070,5 @@
  1.1224      return (cvt->needed);
  1.1225  }
  1.1226  
  1.1227 -#undef SDL_FixMpy8
  1.1228 -#undef SDL_FixMpy16
  1.1229 -#undef SDL_FixMpy32
  1.1230 -#undef SDL_FloatMpy
  1.1231 -#undef SDL_Make_1_7
  1.1232 -#undef SDL_Make_1_15
  1.1233 -#undef SDL_Make_1_31
  1.1234 -#undef SDL_Make_2_6
  1.1235 -#undef SDL_Make_2_14
  1.1236 -#undef SDL_Make_2_30
  1.1237  
  1.1238  /* vi: set ts=4 sw=4 expandtab: */