Mercurial > sdl-ios-xcode
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; |