src/audio/SDL_audiocvt.c
changeset 2716 f8f68f47285a
parent 2130 3ee59c43d784
child 2728 2768bd7281e0
equal deleted inserted replaced
2715:336b604ec15b 2716:f8f68f47285a
    18 
    18 
    19     Sam Lantinga
    19     Sam Lantinga
    20     slouken@libsdl.org
    20     slouken@libsdl.org
    21 */
    21 */
    22 #include "SDL_config.h"
    22 #include "SDL_config.h"
       
    23 #include <math.h>
    23 
    24 
    24 /* Functions for audio drivers to perform runtime conversion of audio format */
    25 /* Functions for audio drivers to perform runtime conversion of audio format */
    25 
    26 
    26 #include "SDL_audio.h"
    27 #include "SDL_audio.h"
    27 #include "SDL_audio_c.h"
    28 #include "SDL_audio_c.h"
       
    29 
       
    30 #define DEBUG_CONVERT
       
    31 
       
    32 /* These are fractional multiplication routines. That is, their inputs
       
    33    are two numbers in the range [-1, 1) and the result falls in that
       
    34    same range. The output is the same size as the inputs, i.e.
       
    35    32-bit x 32-bit = 32-bit.
       
    36  */
       
    37 
       
    38 /* We hope here that the right shift includes sign extension */
       
    39 #ifdef SDL_HAS_64BIT_Type
       
    40 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
       
    41 #else
       
    42 /* 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 */
       
    43 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
       
    44 #endif
       
    45 #define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
       
    46 #define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
       
    47 /* This macro just makes the floating point filtering code not have to be a special case. */
       
    48 #define SDL_FloatMpy(a, b) (a * b)
       
    49 
       
    50 /* These macros take floating point numbers in the range [-1.0f, 1.0f) and
       
    51    represent them as fixed-point numbers in that same range. There's no
       
    52    checking that the floating point argument is inside the appropriate range.
       
    53  */
       
    54 
       
    55 #define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
       
    56 #define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
       
    57 #define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
       
    58 #define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
       
    59 #define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
       
    60 #define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
    28 
    61 
    29 /* Effectively mix right and left channels into a single channel */
    62 /* Effectively mix right and left channels into a single channel */
    30 static void SDLCALL
    63 static void SDLCALL
    31 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    64 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    32 {
    65 {
  1307     }
  1340     }
  1308 
  1341 
  1309     return 0;                   /* no conversion necessary. */
  1342     return 0;                   /* no conversion necessary. */
  1310 }
  1343 }
  1311 
  1344 
       
  1345 /* Generate the necessary IIR lowpass coefficients for resampling.
       
  1346    Assume that the SDL_AudioCVT struct is already set up with
       
  1347    the correct values for len_mult and len_div, and use the
       
  1348    type of dst_format. Also assume the buffer is allocated.
       
  1349    Note the buffer needs to be 6 units long.
       
  1350    For now, use RBJ's cookbook coefficients. It might be more
       
  1351    optimal to create a Butterworth filter, but this is more difficult.
       
  1352 */
       
  1353 int
       
  1354 SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format)
       
  1355 {
       
  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 >
       
  1367           cvt->len_div) ? CUTOFF / (float) cvt->len_mult : CUTOFF /
       
  1368         (float) cvt->len_div;
       
  1369 
       
  1370     w0 = 2.0f * M_PI * fc;
       
  1371     cosw0 = cosf(w0);
       
  1372     alpha = sin(w0) / (2.0f * Q);
       
  1373 
       
  1374     /* Compute coefficients, normalizing by a0 */
       
  1375     scale = 1.0f / (1.0f + alpha);
       
  1376 
       
  1377     coeff[0] = (1.0f - cosw0) / 2.0f * scale;
       
  1378     coeff[1] = (1.0f - cosw0) * scale;
       
  1379     coeff[2] = coeff[0];
       
  1380 
       
  1381     coeff[3] = 1.0f;            /* a0 is normalized to 1 */
       
  1382     coeff[4] = -2.0f * cosw0 * scale;
       
  1383     coeff[5] = (1.0f - alpha) * scale;
       
  1384 
       
  1385     /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */
       
  1386 #define convert_fixed(type, fix) { \
       
  1387             type *cvt_coeff = (type *)cvt->coeff; \
       
  1388             for(i = 0; i < 6; ++i) { \
       
  1389                 cvt_coeff[i] = fix(coeff[i]); \
       
  1390             } \
       
  1391         }
       
  1392 
       
  1393     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
       
  1394         float *cvt_coeff = (float *) cvt->coeff;
       
  1395         for (i = 0; i < 6; ++i) {
       
  1396             cvt_coeff[i] = coeff[i];
       
  1397         }
       
  1398     } else {
       
  1399         switch (SDL_AUDIO_BITSIZE(format)) {
       
  1400         case 8:
       
  1401             convert_fixed(Uint8, SDL_Make_2_6);
       
  1402             break;
       
  1403         case 16:
       
  1404             convert_fixed(Uint16, SDL_Make_2_14);
       
  1405             break;
       
  1406         case 32:
       
  1407             convert_fixed(Uint32, SDL_Make_2_30);
       
  1408             break;
       
  1409         }
       
  1410     }
       
  1411 
       
  1412 #ifdef DEBUG_CONVERT
       
  1413 #define debug_iir(type) { \
       
  1414             type *cvt_coeff = (type *)cvt->coeff; \
       
  1415             for(i = 0; i < 6; ++i) { \
       
  1416                 printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \
       
  1417             } \
       
  1418         }
       
  1419     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
       
  1420         float *cvt_coeff = (float *) cvt->coeff;
       
  1421         for (i = 0; i < 6; ++i) {
       
  1422             printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]);
       
  1423         }
       
  1424     } else {
       
  1425         switch (SDL_AUDIO_BITSIZE(format)) {
       
  1426         case 8:
       
  1427             debug_iir(Uint8);
       
  1428             break;
       
  1429         case 16:
       
  1430             debug_iir(Uint16);
       
  1431             break;
       
  1432         case 32:
       
  1433             debug_iir(Uint32);
       
  1434             break;
       
  1435         }
       
  1436     }
       
  1437 #undef debug_iir
       
  1438 #endif
       
  1439 
       
  1440     /* Initialize the state buffer to all zeroes, and set initial position */
       
  1441     memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4);
       
  1442     cvt->state_pos = 0;
       
  1443 #undef convert_fixed
       
  1444 }
       
  1445 
       
  1446 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
       
  1447 /* This was implemented because it would be much faster than the fir filter, 
       
  1448    but it doesn't seem to have a steep enough cutoff so we'd need several
       
  1449    cascaded biquads, which probably isn't a great idea. Therefore, this
       
  1450    function can probably be discarded.
       
  1451 */
       
  1452 static void
       
  1453 SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
       
  1454 {
       
  1455     Uint32 i, n;
       
  1456 
       
  1457     /* TODO: Check that n is calculated right */
       
  1458     n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
       
  1459 
       
  1460     /* 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. */
       
  1461     /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
       
  1462 #define iir_fix(type, mult) {\
       
  1463             type *coeff = (type *)cvt->coeff; \
       
  1464             type *state = (type *)cvt->state_buf; \
       
  1465             type *buf = (type *)cvt->buf; \
       
  1466             type temp; \
       
  1467             for(i = 0; i < n; ++i) { \
       
  1468                     temp = buf[i] >> 1; \
       
  1469                     if(cvt->state_pos) { \
       
  1470                         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]); \
       
  1471                         state[1] = temp; \
       
  1472                         state[3] = buf[i]; \
       
  1473                         cvt->state_pos = 0; \
       
  1474                     } else { \
       
  1475                         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]); \
       
  1476                         state[0] = temp; \
       
  1477                         state[2] = buf[i]; \
       
  1478                         cvt->state_pos = 1; \
       
  1479                     } \
       
  1480                 } \
       
  1481         }
       
  1482 /* Need to test to see if the previous method or this one is faster */
       
  1483 /*#define iir_fix(type, mult) {\
       
  1484             type *coeff = (type *)cvt->coeff; \
       
  1485             type *state = (type *)cvt->state_buf; \
       
  1486             type *buf = (type *)cvt->buf; \
       
  1487             type temp; \
       
  1488             for(i = 0; i < n; ++i) { \
       
  1489                     temp = buf[i] >> 1; \
       
  1490                     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]); \
       
  1491                     state[1] = state[0]; \
       
  1492                     state[0] = temp; \
       
  1493                     state[3] = state[2]; \
       
  1494                     state[2] = buf[i]; \
       
  1495                 } \
       
  1496         }*/
       
  1497 
       
  1498     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
       
  1499         float *coeff = (float *) cvt->coeff;
       
  1500         float *state = (float *) cvt->state_buf;
       
  1501         float *buf = (float *) cvt->buf;
       
  1502         float temp;
       
  1503 
       
  1504         for (i = 0; i < n; ++i) {
       
  1505             /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
       
  1506             temp = buf[i];
       
  1507             if (cvt->state_pos) {
       
  1508                 buf[i] =
       
  1509                     coeff[0] * buf[n] + coeff[1] * state[0] +
       
  1510                     coeff[2] * state[1] - coeff[4] * state[2] -
       
  1511                     coeff[5] * state[3];
       
  1512                 state[1] = temp;
       
  1513                 state[3] = buf[i];
       
  1514                 cvt->state_pos = 0;
       
  1515             } else {
       
  1516                 buf[i] =
       
  1517                     coeff[0] * buf[n] + coeff[1] * state[1] +
       
  1518                     coeff[2] * state[0] - coeff[4] * state[3] -
       
  1519                     coeff[5] * state[2];
       
  1520                 state[0] = temp;
       
  1521                 state[2] = buf[i];
       
  1522                 cvt->state_pos = 1;
       
  1523             }
       
  1524         }
       
  1525     } else {
       
  1526         /* Treat everything as signed! */
       
  1527         switch (SDL_AUDIO_BITSIZE(format)) {
       
  1528         case 8:
       
  1529             iir_fix(Sint8, SDL_FixMpy8);
       
  1530             break;
       
  1531         case 16:
       
  1532             iir_fix(Sint16, SDL_FixMpy16);
       
  1533             break;
       
  1534         case 32:
       
  1535             iir_fix(Sint32, SDL_FixMpy32);
       
  1536             break;
       
  1537         }
       
  1538     }
       
  1539 #undef iir_fix
       
  1540 }
       
  1541 
       
  1542 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct.
       
  1543 */
       
  1544 static void
       
  1545 SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
       
  1546 {
       
  1547     int n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
       
  1548     int m = cvt->len_sinc;
       
  1549     int i, j;
       
  1550 
       
  1551     /* 
       
  1552        Note: We can make a big optimization here by taking advantage
       
  1553        of the fact that the signal is zero stuffed, so we can do
       
  1554        significantly fewer multiplications and additions. However, this
       
  1555        depends on the zero stuffing ratio, so it may not pay off. This would
       
  1556        basically be a polyphase filter.
       
  1557      */
       
  1558     /* One other way to do this fast is to look at the fir filter from a different angle:
       
  1559        After we zero stuff, we have input of all zeroes, except for every len_mult
       
  1560        sample. If we choose a sinc length equal to len_mult, then the fir filter becomes
       
  1561        much more simple: we're just taking a windowed sinc, shifting it to start at each
       
  1562        len_mult sample, and scaling it by the value of that sample. If we do this, then
       
  1563        we don't even need to worry about the sample histories, and the inner loop here is
       
  1564        unnecessary. This probably sacrifices some quality but could really speed things up as well.
       
  1565      */
       
  1566     /* We only calculate the values of samples which are 0 (mod len_div) because
       
  1567        those are the only ones used. All the other ones are discarded in the
       
  1568        third step of resampling. This is a huge speedup. As a warning, though,
       
  1569        if for some reason this is used elsewhere where there are no samples discarded,
       
  1570        the output will not be corrrect if len_div is not 1. To make this filter a
       
  1571        generic FIR filter, simply remove the if statement "if(i % cvt->len_div == 0)"
       
  1572        around the inner loop so that every sample is processed.
       
  1573      */
       
  1574     /* This is basically just a FIR filter. i.e. for input x_n and m coefficients,
       
  1575        y_n = x_n*sinc_0 + x_(n-1)*sinc_1 +  x_(n-2)*sinc_2 + ... + x_(n-m+1)*sinc_(m-1)
       
  1576      */
       
  1577 #define filter_sinc(type, mult) { \
       
  1578             type *sinc = (type *)cvt->coeff; \
       
  1579             type *state = (type *)cvt->state_buf; \
       
  1580             type *buf = (type *)cvt->buf; \
       
  1581             for(i = 0; i < n; ++i) { \
       
  1582                 state[cvt->state_pos] = buf[i]; \
       
  1583                 buf[i] = 0; \
       
  1584                 if( i % cvt->len_div == 0 ) { \
       
  1585                     for(j = 0; j < m;  ++j) { \
       
  1586                         buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \
       
  1587                     } \
       
  1588                 }\
       
  1589                 cvt->state_pos = (cvt->state_pos + 1) % m; \
       
  1590             } \
       
  1591         }
       
  1592 
       
  1593     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
       
  1594         filter_sinc(float, SDL_FloatMpy);
       
  1595     } else {
       
  1596         switch (SDL_AUDIO_BITSIZE(format)) {
       
  1597         case 8:
       
  1598             filter_sinc(Sint8, SDL_FixMpy8);
       
  1599             break;
       
  1600         case 16:
       
  1601             filter_sinc(Sint16, SDL_FixMpy16);
       
  1602             break;
       
  1603         case 32:
       
  1604             filter_sinc(Sint32, SDL_FixMpy32);
       
  1605             break;
       
  1606         }
       
  1607     }
       
  1608 
       
  1609 #undef filter_sinc
       
  1610 
       
  1611 }
       
  1612 
       
  1613 /* Generate the necessary windowed sinc filter for resampling.
       
  1614    Assume that the SDL_AudioCVT struct is already set up with
       
  1615    the correct values for len_mult and len_div, and use the
       
  1616    type of dst_format. Also assume the buffer is allocated.
       
  1617    Note the buffer needs to be m+1 units long.
       
  1618 */
       
  1619 int
       
  1620 SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format,
       
  1621                       unsigned int m)
       
  1622 {
       
  1623     float fScale;               /* scale factor for fixed point */
       
  1624     float *fSinc;               /* floating point sinc buffer, to be converted to fixed point */
       
  1625     float fc;                   /* cutoff frequency */
       
  1626     float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
       
  1627     float norm_sum, norm_fact;
       
  1628     unsigned int i;
       
  1629 
       
  1630     /* Check that the buffer is allocated */
       
  1631     if (cvt->coeff == NULL) {
       
  1632         return -1;
       
  1633     }
       
  1634 
       
  1635     /* Set the length */
       
  1636     cvt->len_sinc = m + 1;
       
  1637 
       
  1638     /* Allocate the floating point windowed sinc. */
       
  1639     fSinc = (float *) malloc((m + 1) * sizeof(float));
       
  1640     if (fSinc == NULL) {
       
  1641         return -1;
       
  1642     }
       
  1643 
       
  1644     /* Set up the filter parameters */
       
  1645     fc = (cvt->len_mult >
       
  1646           cvt->len_div) ? 0.5f / (float) cvt->len_mult : 0.5f /
       
  1647         (float) cvt->len_div;
       
  1648 #ifdef DEBUG_CONVERT
       
  1649     printf("Lowpass cutoff frequency = %f\n", fc);
       
  1650 #endif
       
  1651     two_pi_fc = 2.0f * M_PI * fc;
       
  1652     two_pi_over_m = 2.0f * M_PI / (float) m;
       
  1653     four_pi_over_m = 2.0f * two_pi_over_m;
       
  1654     m_over_two = (float) m / 2.0f;
       
  1655     norm_sum = 0.0f;
       
  1656 
       
  1657     for (i = 0; i <= m; ++i) {
       
  1658         if (i == m / 2) {
       
  1659             fSinc[i] = two_pi_fc;
       
  1660         } else {
       
  1661             fSinc[i] =
       
  1662                 sinf(two_pi_fc * ((float) i - m_over_two)) / ((float) i -
       
  1663                                                               m_over_two);
       
  1664             /* Apply blackman window */
       
  1665             fSinc[i] *=
       
  1666                 0.42f - 0.5f * cosf(two_pi_over_m * (float) i) +
       
  1667                 0.08f * cosf(four_pi_over_m * (float) i);
       
  1668         }
       
  1669         norm_sum += fabs(fSinc[i]);
       
  1670     }
       
  1671 
       
  1672     norm_fact = 1.0f / norm_sum;
       
  1673 
       
  1674 #define convert_fixed(type, fix) { \
       
  1675         type *dst = (type *)cvt->coeff; \
       
  1676         for( i = 0; i <= m; ++i ) { \
       
  1677             dst[i] = fix(fSinc[i] * norm_fact); \
       
  1678         } \
       
  1679     }
       
  1680 
       
  1681     /* If we're using floating point, we only need to normalize */
       
  1682     if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
       
  1683         float *fDest = (float *) cvt->coeff;
       
  1684         for (i = 0; i <= m; ++i) {
       
  1685             fDest[i] = fSinc[i] * norm_fact;
       
  1686         }
       
  1687     } else {
       
  1688         switch (SDL_AUDIO_BITSIZE(format)) {
       
  1689         case 8:
       
  1690             convert_fixed(Uint8, SDL_Make_1_7);
       
  1691             break;
       
  1692         case 16:
       
  1693             convert_fixed(Uint16, SDL_Make_1_15);
       
  1694             break;
       
  1695         case 32:
       
  1696             convert_fixed(Uint32, SDL_Make_1_31);
       
  1697             break;
       
  1698         }
       
  1699     }
       
  1700 
       
  1701     /* Initialize the state buffer to all zeroes, and set initial position */
       
  1702     memset(cvt->state_buf, 0, cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
       
  1703     cvt->state_pos = 0;
       
  1704 
       
  1705     /* Clean up */
       
  1706 #undef convert_fixed
       
  1707     free(fSinc);
       
  1708 }
       
  1709 
       
  1710 /* This is used to reduce the resampling ratio */
       
  1711 inline int
       
  1712 SDL_GCD(int a, int b)
       
  1713 {
       
  1714     int temp;
       
  1715     while (b != 0) {
       
  1716         temp = a % b;
       
  1717         a = b;
       
  1718         b = temp;
       
  1719     }
       
  1720     return a;
       
  1721 }
       
  1722 
       
  1723 /* Perform proper resampling. This is pretty slow but it's the best-sounding method. */
       
  1724 static void SDLCALL
       
  1725 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
       
  1726 {
       
  1727     int i, j;
       
  1728 
       
  1729 #ifdef DEBUG_CONVERT
       
  1730     printf("Converting audio rate via proper resampling (mono)\n");
       
  1731 #endif
       
  1732 
       
  1733 #define zerostuff_mono(type) { \
       
  1734         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
       
  1735         type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \
       
  1736         for (i = cvt->len_cvt / sizeof (type); i; --i) { \
       
  1737             src--; \
       
  1738             dst[-1] = src[0]; \
       
  1739             for( j = -cvt->len_mult; j < -1; ++j ) { \
       
  1740                 dst[j] = 0; \
       
  1741             } \
       
  1742             dst -= cvt->len_mult; \
       
  1743         } \
       
  1744     }
       
  1745 
       
  1746 #define discard_mono(type) { \
       
  1747         const type *src = (const type *) (cvt->buf); \
       
  1748         type *dst = (type *) (cvt->buf); \
       
  1749         for (i = 0; i < (cvt->len_cvt / sizeof(type)) / cvt->len_div; ++i) { \
       
  1750             dst[0] = src[0]; \
       
  1751             src += cvt->len_div; \
       
  1752             ++dst; \
       
  1753         } \
       
  1754     }
       
  1755 
       
  1756     /* Step 1: Zero stuff the conversion buffer. This upsamples by a factor of len_mult,
       
  1757        creating aliasing at frequencies above the original nyquist frequency.
       
  1758      */
       
  1759 #ifdef DEBUG_CONVERT
       
  1760     printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
       
  1761 #endif
       
  1762     switch (SDL_AUDIO_BITSIZE(format)) {
       
  1763     case 8:
       
  1764         zerostuff_mono(Uint8);
       
  1765         break;
       
  1766     case 16:
       
  1767         zerostuff_mono(Uint16);
       
  1768         break;
       
  1769     case 32:
       
  1770         zerostuff_mono(Uint32);
       
  1771         break;
       
  1772     }
       
  1773 
       
  1774     cvt->len_cvt *= cvt->len_mult;
       
  1775 
       
  1776     /* Step 2: Use a windowed sinc FIR filter (lowpass filter) to remove the alias
       
  1777        frequencies. This is the slow part.
       
  1778      */
       
  1779     SDL_FilterFIR(cvt, format);
       
  1780 
       
  1781     /* Step 3: Now downsample by discarding samples. */
       
  1782 
       
  1783 #ifdef DEBUG_CONVERT
       
  1784     printf("Discarding samples by a factor of %u\n", cvt->len_div);
       
  1785 #endif
       
  1786     switch (SDL_AUDIO_BITSIZE(format)) {
       
  1787     case 8:
       
  1788         discard_mono(Uint8);
       
  1789         break;
       
  1790     case 16:
       
  1791         discard_mono(Uint16);
       
  1792         break;
       
  1793     case 32:
       
  1794         discard_mono(Uint32);
       
  1795         break;
       
  1796     }
       
  1797 
       
  1798 #undef zerostuff_mono
       
  1799 #undef discard_mono
       
  1800 
       
  1801     cvt->len_cvt /= cvt->len_div;
       
  1802 
       
  1803     if (cvt->filters[++cvt->filter_index]) {
       
  1804         cvt->filters[cvt->filter_index] (cvt, format);
       
  1805     }
       
  1806 }
  1312 
  1807 
  1313 
  1808 
  1314 /* Creates a set of audio filters to convert from one format to another.
  1809 /* Creates a set of audio filters to convert from one format to another.
  1315    Returns -1 if the format conversion is not supported, 0 if there's
  1810    Returns -1 if the format conversion is not supported, 0 if there's
  1316    no conversion needed, or 1 if the audio filter is set up.
  1811    no conversion needed, or 1 if the audio filter is set up.
  1397             /* Uh oh.. */ ;
  1892             /* Uh oh.. */ ;
  1398         }
  1893         }
  1399     }
  1894     }
  1400 
  1895 
  1401     /* Do rate conversion */
  1896     /* Do rate conversion */
       
  1897     if (src_rate != dst_rate) {
       
  1898         int rate_gcd;
       
  1899         rate_gcd = SDL_GCD(src_rate, dst_rate);
       
  1900         cvt->len_mult = dst_rate / rate_gcd;
       
  1901         cvt->len_div = src_rate / rate_gcd;
       
  1902         cvt->len_ratio = (double) cvt->len_mult / (double) cvt->len_div;
       
  1903         cvt->filters[cvt->filter_index++] = SDL_Resample;
       
  1904         SDL_BuildWindowedSinc(cvt, dst_fmt, 768);
       
  1905     }
       
  1906 
       
  1907 /*
  1402     cvt->rate_incr = 0.0;
  1908     cvt->rate_incr = 0.0;
  1403     if ((src_rate / 100) != (dst_rate / 100)) {
  1909     if ((src_rate / 100) != (dst_rate / 100)) {
  1404         Uint32 hi_rate, lo_rate;
  1910         Uint32 hi_rate, lo_rate;
  1405         int len_mult;
  1911         int len_mult;
  1406         double len_ratio;
  1912         double len_ratio;
  1446             default:
  1952             default:
  1447                 return -1;
  1953                 return -1;
  1448             }
  1954             }
  1449             len_mult = 2;
  1955             len_mult = 2;
  1450             len_ratio = 2.0;
  1956             len_ratio = 2.0;
  1451         }
  1957         }*/
  1452         /* If hi_rate = lo_rate*2^x then conversion is easy */
  1958     /* If hi_rate = lo_rate*2^x then conversion is easy */
  1453         while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1959     /*   while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
  1454             cvt->filters[cvt->filter_index++] = rate_cvt;
  1960        cvt->filters[cvt->filter_index++] = rate_cvt;
  1455             cvt->len_mult *= len_mult;
  1961        cvt->len_mult *= len_mult;
  1456             lo_rate *= 2;
  1962        lo_rate *= 2;
  1457             cvt->len_ratio *= len_ratio;
  1963        cvt->len_ratio *= len_ratio;
  1458         }
  1964        } */
  1459         /* We may need a slow conversion here to finish up */
  1965     /* We may need a slow conversion here to finish up */
  1460         if ((lo_rate / 100) != (hi_rate / 100)) {
  1966     /*    if ((lo_rate / 100) != (hi_rate / 100)) {
  1461 #if 1
  1967        #if 1 */
  1462             /* The problem with this is that if the input buffer is
  1968     /* The problem with this is that if the input buffer is
  1463                say 1K, and the conversion rate is say 1.1, then the
  1969        say 1K, and the conversion rate is say 1.1, then the
  1464                output buffer is 1.1K, which may not be an acceptable
  1970        output buffer is 1.1K, which may not be an acceptable
  1465                buffer size for the audio driver (not a power of 2)
  1971        buffer size for the audio driver (not a power of 2)
  1466              */
  1972      */
  1467             /* For now, punt and hope the rate distortion isn't great.
  1973     /* For now, punt and hope the rate distortion isn't great.
  1468              */
  1974      */
  1469 #else
  1975 /*#else
  1470             if (src_rate < dst_rate) {
  1976             if (src_rate < dst_rate) {
  1471                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1977                 cvt->rate_incr = (double) lo_rate / hi_rate;
  1472                 cvt->len_mult *= 2;
  1978                 cvt->len_mult *= 2;
  1473                 cvt->len_ratio /= cvt->rate_incr;
  1979                 cvt->len_ratio /= cvt->rate_incr;
  1474             } else {
  1980             } else {
  1476                 cvt->len_ratio *= cvt->rate_incr;
  1982                 cvt->len_ratio *= cvt->rate_incr;
  1477             }
  1983             }
  1478             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1984             cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
  1479 #endif
  1985 #endif
  1480         }
  1986         }
  1481     }
  1987     }*/
  1482 
  1988 
  1483     /* Set up the filter information */
  1989     /* Set up the filter information */
  1484     if (cvt->filter_index != 0) {
  1990     if (cvt->filter_index != 0) {
  1485         cvt->needed = 1;
  1991         cvt->needed = 1;
  1486         cvt->src_format = src_fmt;
  1992         cvt->src_format = src_fmt;
  1490         cvt->filters[cvt->filter_index] = NULL;
  1996         cvt->filters[cvt->filter_index] = NULL;
  1491     }
  1997     }
  1492     return (cvt->needed);
  1998     return (cvt->needed);
  1493 }
  1999 }
  1494 
  2000 
       
  2001 #undef SDL_FixMpy8
       
  2002 #undef SDL_FixMpy16
       
  2003 #undef SDL_FixMpy32
       
  2004 #undef SDL_FloatMpy
       
  2005 #undef SDL_Make_1_7
       
  2006 #undef SDL_Make_1_15
       
  2007 #undef SDL_Make_1_31
       
  2008 #undef SDL_Make_2_6
       
  2009 #undef SDL_Make_2_14
       
  2010 #undef SDL_Make_2_30
       
  2011 
  1495 /* vi: set ts=4 sw=4 expandtab: */
  2012 /* vi: set ts=4 sw=4 expandtab: */