Mercurial > sdl-ios-xcode
comparison src/audio/SDL_audiocvt.c @ 2716:f8f68f47285a
Final merge of Google Summer of Code 2008 work...
Audio Ideas - Resampling and Pitch Shifting
by Aaron Wishnick, mentored by Ryan C. Gordon
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 25 Aug 2008 15:08:59 +0000 |
parents | 3ee59c43d784 |
children | 2768bd7281e0 |
comparison
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: */ |