comparison src/audio/SDL_audiocvt.c @ 2658:de29a03cb108 gsoc2008_audio_resampling

IIR filtering now seems to work fine. Fixed point code also seems to be good.
author Aaron Wishnick <schnarf@gmail.com>
date Thu, 19 Jun 2008 20:11:06 +0000
parents 29306e52dab8
children 8da698bc1205
comparison
equal deleted inserted replaced
2657:29306e52dab8 2658:de29a03cb108
40 x = a * d + c * b; \ 40 x = a * d + c * b; \
41 y = (((b*d) >> 16) & 0xffff) + x; \ 41 y = (((b*d) >> 16) & 0xffff) + x; \
42 dest = ((y >> 16) & 0xffff) + (a * c); \ 42 dest = ((y >> 16) & 0xffff) + (a * c); \
43 }*/ 43 }*/
44 /* TODO: Check if 64-bit type exists. If not, see http://www.8052.com/mul16.phtml or http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html */ 44 /* TODO: Check if 64-bit type exists. If not, see http://www.8052.com/mul16.phtml or http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html */
45 45
46 #define SDL_FixMpy32(a, b) ((((long long)a * (long long)b) >> 32) & 0xffffffff) 46 /* We hope here that the right shift includes sign extension */
47 #ifdef DEBUG_CONVERT 47 #ifdef SDL_HAS_64BIT_Type
48 #define SDL_FixMpy16(a, b) ((((long)a * (long)b) >> 16) & 0xffff); printf("%f * %f = %f\n", (float)a / 16384.0f, (float)b / 16384.0f, (float)((((long)a * (long)b) >> 16) & 0xffff) / 16384.0f); 48 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
49 #else 49 #else
50 #define SDL_FixMpy16(a, b) ((((long)a * (long)b) >> 16) & 0xffff) 50 /* need to do something more complicated here */
51 #endif 51 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
52 #define SDL_FixMpy8(a, b) ((((short)a * (short)b) >> 8) & 0xff) 52 #endif
53 53 /* Confirmed that SDL_FixMpy16 works, need to check 8 and 32 */
54 #define SDL_Make_1_7(a) (Uint8)(a * 128.0f) 54 #define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
55 #define SDL_Make_1_15(a) (Uint16)(a * 32768.0f) 55 #define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
56 #define SDL_Make_1_31(a) (Uint32)(a * 2147483648.0f) 56 /* Everything is signed! */
57 #define SDL_Make_2_6(a) (Uint8)(a * 64.0f) 57 #define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
58 #define SDL_Make_2_14(a) (Uint16)(a * 16384.0f) 58 #define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
59 #define SDL_Make_2_30(a) (Uint32)(a * 1073741824.0f) 59 #define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
60 #define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
61 #define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
62 #define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
60 63
61 /* Effectively mix right and left channels into a single channel */ 64 /* Effectively mix right and left channels into a single channel */
62 static void SDLCALL 65 static void SDLCALL
63 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) 66 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
64 { 67 {
1438 #undef convert_fixed 1441 #undef convert_fixed
1439 } 1442 }
1440 1443
1441 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */ 1444 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
1442 static void SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) { 1445 static void SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
1443 int i, n; 1446 Uint32 i, n;
1444 1447
1445 n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4); 1448 /* TODO: Check that n is calculated right */
1446 1449 n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
1447 /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? */ 1450
1451 /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? The right shift temp = buf[n] >> 1 needs to depend on whether the type is signed or not for sign extension.*/
1452 /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
1448 #define iir_fix(type, mult) {\ 1453 #define iir_fix(type, mult) {\
1449 type *coeff = (type *)cvt->coeff; \ 1454 type *coeff = (type *)cvt->coeff; \
1450 type *state = (type *)cvt->state_buf; \ 1455 type *state = (type *)cvt->state_buf; \
1451 type *buf = (type *)cvt->buf; \ 1456 type *buf = (type *)cvt->buf; \
1452 type temp; \ 1457 type temp; \
1453 for(i = 0; i < n; ++i) { \ 1458 for(i = 0; i < n; ++i) { \
1454 temp = buf[n] >> 1; \ 1459 temp = buf[i] >> 1; \
1455 if(cvt->state_pos) { \ 1460 if(cvt->state_pos) { \
1456 buf[n] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \ 1461 buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
1457 state[1] = temp; \ 1462 state[1] = temp; \
1458 state[3] = buf[n]; \ 1463 state[3] = buf[i]; \
1459 cvt->state_pos = 0; \ 1464 cvt->state_pos = 0; \
1460 } else { \ 1465 } else { \
1461 buf[n] = mult(coeff[0], temp) + mult(coeff[1], state[1]) +mult(coeff[2], state[0]) - mult(coeff[4], state[3]) - mult(coeff[5], state[2]); \ 1466 buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[1]) + mult(coeff[2], state[0]) - mult(coeff[4], state[3]) - mult(coeff[5], state[2]); \
1462 state[0] = temp; \ 1467 state[0] = temp; \
1463 state[2] = buf[n]; \ 1468 state[2] = buf[i]; \
1464 cvt->state_pos = 0; \ 1469 cvt->state_pos = 1; \
1465 } \ 1470 } \
1466 } \ 1471 } \
1467 } 1472 }
1473 /* Need to test to see if the previous method or this one is faster */
1474 /*#define iir_fix(type, mult) {\
1475 type *coeff = (type *)cvt->coeff; \
1476 type *state = (type *)cvt->state_buf; \
1477 type *buf = (type *)cvt->buf; \
1478 type temp; \
1479 for(i = 0; i < n; ++i) { \
1480 temp = buf[i] >> 1; \
1481 buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
1482 state[1] = state[0]; \
1483 state[0] = temp; \
1484 state[3] = state[2]; \
1485 state[2] = buf[i]; \
1486 } \
1487 }*/
1468 1488
1469 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { 1489 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1470 float *coeff = (float *)cvt->coeff; 1490 float *coeff = (float *)cvt->coeff;
1471 float *state = (float *)cvt->state_buf; 1491 float *state = (float *)cvt->state_buf;
1472 float *buf = (float *)cvt->buf; 1492 float *buf = (float *)cvt->buf;
1473 float temp; 1493 float temp;
1474 1494
1475 for(i = 0; i < n; ++i) { 1495 for(i = 0; i < n; ++i) {
1476 /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */ 1496 /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
1477 temp = buf[n]; 1497 temp = buf[i];
1478 if(cvt->state_pos) { 1498 if(cvt->state_pos) {
1479 buf[n] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3]; 1499 buf[i] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3];
1480 state[1] = temp; 1500 state[1] = temp;
1481 state[3] = buf[n]; 1501 state[3] = buf[i];
1482 cvt->state_pos = 0; 1502 cvt->state_pos = 0;
1483 } else { 1503 } else {
1484 buf[n] = coeff[0] * buf[n] + coeff[1] * state[1] + coeff[2] * state[0] - coeff[4] * state[3] - coeff[5] * state[2]; 1504 buf[i] = coeff[0] * buf[n] + coeff[1] * state[1] + coeff[2] * state[0] - coeff[4] * state[3] - coeff[5] * state[2];
1485 state[0] = temp; 1505 state[0] = temp;
1486 state[2] = buf[n]; 1506 state[2] = buf[i];
1487 cvt->state_pos = 1; 1507 cvt->state_pos = 1;
1488 } 1508 }
1489 } 1509 }
1490 } else { 1510 } else {
1511 /* Treat everything as signed! */
1491 switch(SDL_AUDIO_BITSIZE(format)) { 1512 switch(SDL_AUDIO_BITSIZE(format)) {
1492 case 8: 1513 case 8:
1493 iir_fix(Uint8, SDL_FixMpy8); 1514 iir_fix(Sint8, SDL_FixMpy8);
1494 break; 1515 break;
1495 case 16: 1516 case 16:
1496 iir_fix(Uint16, SDL_FixMpy16); 1517 iir_fix(Sint16, SDL_FixMpy16);
1497 break; 1518 break;
1498 case 32: 1519 case 32:
1499 iir_fix(Uint32, SDL_FixMpy32); 1520 iir_fix(Sint32, SDL_FixMpy32);
1500 break; 1521 break;
1501 } 1522 }
1502 } 1523 }
1503 #undef iir_fix 1524 #undef iir_fix
1504 } 1525 }
1542 } 1563 }
1543 } 1564 }
1544 } else { 1565 } else {
1545 switch (SDL_AUDIO_BITSIZE(format)) { 1566 switch (SDL_AUDIO_BITSIZE(format)) {
1546 case 8: 1567 case 8:
1547 filter_sinc(Uint8, SDL_FixMpy8); 1568 filter_sinc(Sint8, SDL_FixMpy8);
1548 break; 1569 break;
1549 case 16: 1570 case 16:
1550 filter_sinc(Uint16, SDL_FixMpy16); 1571 filter_sinc(Sint16, SDL_FixMpy16);
1551 break; 1572 break;
1552 case 32: 1573 case 32:
1553 filter_sinc(Uint32, SDL_FixMpy32); 1574 filter_sinc(Sint32, SDL_FixMpy32);
1554 break; 1575 break;
1555 } 1576 }
1556 } 1577 }
1557 1578
1558 #undef filter_sinc 1579 #undef filter_sinc
1828 } 1849 }
1829 1850
1830 /* Do rate conversion */ 1851 /* Do rate conversion */
1831 int rate_gcd; 1852 int rate_gcd;
1832 rate_gcd = SDL_GCD(src_rate, dst_rate); 1853 rate_gcd = SDL_GCD(src_rate, dst_rate);
1833 cvt->len_mult = 2 * dst_rate / rate_gcd; 1854 cvt->len_mult = dst_rate / rate_gcd;
1834 cvt->len_div = 2 * src_rate / rate_gcd; 1855 cvt->len_div = src_rate / rate_gcd;
1835 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div; 1856 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div;
1836 cvt->filters[cvt->filter_index++] = SDL_Resample; 1857 cvt->filters[cvt->filter_index++] = SDL_Resample;
1837 SDL_BuildIIRLowpass(cvt, dst_fmt); 1858 SDL_BuildIIRLowpass(cvt, dst_fmt);
1838 1859
1839 /*cvt->rate_incr = 0.0; 1860 /*cvt->rate_incr = 0.0;