Mercurial > sdl-ios-xcode
comparison src/audio/SDL_audiocvt.c @ 2657:29306e52dab8 gsoc2008_audio_resampling
Implemented a lot of fixed point code for the filters. The SDL_FixMpy functions currently don't work properly -- there are some issues with signed vs unsigned.
author | Aaron Wishnick <schnarf@gmail.com> |
---|---|
date | Wed, 18 Jun 2008 22:42:27 +0000 |
parents | dd74182b3c3c |
children | de29a03cb108 |
comparison
equal
deleted
inserted
replaced
2656:dd74182b3c3c | 2657:29306e52dab8 |
---|---|
26 | 26 |
27 #include "SDL_audio.h" | 27 #include "SDL_audio.h" |
28 #include "SDL_audio_c.h" | 28 #include "SDL_audio_c.h" |
29 | 29 |
30 #define DEBUG_CONVERT | 30 #define DEBUG_CONVERT |
31 | |
32 /* Perform fractional multiplication of two 32-bit integers to produce a 32-bit result. Assumes sizeof(long) = 4 */ | |
33 /*#define SDL_FixMpy32(v1, v2, dest) { \ | |
34 long a, b, c, d; \ | |
35 long x, y; \ | |
36 a = (v1 >> 16) & 0xffff; \ | |
37 b = v1 & 0xffff; \ | |
38 c = (v2 >> 16); \ | |
39 d = v2 & 0xffff; \ | |
40 x = a * d + c * b; \ | |
41 y = (((b*d) >> 16) & 0xffff) + x; \ | |
42 dest = ((y >> 16) & 0xffff) + (a * c); \ | |
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 */ | |
45 | |
46 #define SDL_FixMpy32(a, b) ((((long long)a * (long long)b) >> 32) & 0xffffffff) | |
47 #ifdef DEBUG_CONVERT | |
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); | |
49 #else | |
50 #define SDL_FixMpy16(a, b) ((((long)a * (long)b) >> 16) & 0xffff) | |
51 #endif | |
52 #define SDL_FixMpy8(a, b) ((((short)a * (short)b) >> 8) & 0xff) | |
53 | |
54 #define SDL_Make_1_7(a) (Uint8)(a * 128.0f) | |
55 #define SDL_Make_1_15(a) (Uint16)(a * 32768.0f) | |
56 #define SDL_Make_1_31(a) (Uint32)(a * 2147483648.0f) | |
57 #define SDL_Make_2_6(a) (Uint8)(a * 64.0f) | |
58 #define SDL_Make_2_14(a) (Uint16)(a * 16384.0f) | |
59 #define SDL_Make_2_30(a) (Uint32)(a * 1073741824.0f) | |
31 | 60 |
32 /* Effectively mix right and left channels into a single channel */ | 61 /* Effectively mix right and left channels into a single channel */ |
33 static void SDLCALL | 62 static void SDLCALL |
34 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) | 63 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) |
35 { | 64 { |
1230 if (cvt->filters[++cvt->filter_index]) { | 1259 if (cvt->filters[++cvt->filter_index]) { |
1231 cvt->filters[cvt->filter_index] (cvt, format); | 1260 cvt->filters[cvt->filter_index] (cvt, format); |
1232 } | 1261 } |
1233 } | 1262 } |
1234 | 1263 |
1235 /* Perform proper resampling */ | |
1236 static void SDLCALL | |
1237 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format) | |
1238 { | |
1239 int i, j; | |
1240 | |
1241 #ifdef DEBUG_CONVERT | |
1242 printf("Converting audio rate via proper resampling (mono)\n"); | |
1243 #endif | |
1244 | |
1245 #define zerostuff_mono(type) { \ | |
1246 const type *src = (const type *) (cvt->buf + cvt->len_cvt); \ | |
1247 type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \ | |
1248 for (i = cvt->len_cvt / sizeof (type); i; --i) { \ | |
1249 src--; \ | |
1250 dst[-1] = src[0]; \ | |
1251 for( j = -cvt->len_mult; j < -1; ++j ) { \ | |
1252 dst[j] = 0; \ | |
1253 } \ | |
1254 dst -= cvt->len_mult; \ | |
1255 } \ | |
1256 } | |
1257 | |
1258 #define discard_mono(type) { \ | |
1259 const type *src = (const type *) (cvt->buf); \ | |
1260 type *dst = (type *) (cvt->buf); \ | |
1261 for (i = 0; i < cvt->len_cvt / cvt->len_div / sizeof (type); ++i) { \ | |
1262 dst[0] = src[0]; \ | |
1263 src += cvt->len_div; \ | |
1264 ++dst; \ | |
1265 } \ | |
1266 } | |
1267 | |
1268 // Step 1: Zero stuff the conversion buffer | |
1269 #ifdef DEBUG_CONVERT | |
1270 printf("Zero-stuffing by a factor of %u\n", cvt->len_mult); | |
1271 #endif | |
1272 switch (SDL_AUDIO_BITSIZE(format)) { | |
1273 case 8: | |
1274 zerostuff_mono(Uint8); | |
1275 break; | |
1276 case 16: | |
1277 zerostuff_mono(Uint16); | |
1278 break; | |
1279 case 32: | |
1280 zerostuff_mono(Uint32); | |
1281 break; | |
1282 } | |
1283 | |
1284 cvt->len_cvt *= cvt->len_mult; | |
1285 | |
1286 // Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies | |
1287 | |
1288 // Step 3: Discard unnecessary samples | |
1289 #ifdef DEBUG_CONVERT | |
1290 printf("Discarding samples by a factor of %u\n", cvt->len_div); | |
1291 #endif | |
1292 switch (SDL_AUDIO_BITSIZE(format)) { | |
1293 case 8: | |
1294 discard_mono(Uint8); | |
1295 break; | |
1296 case 16: | |
1297 discard_mono(Uint16); | |
1298 break; | |
1299 case 32: | |
1300 discard_mono(Uint32); | |
1301 break; | |
1302 } | |
1303 | |
1304 #undef zerostuff_mono | |
1305 #undef discard_mono | |
1306 | |
1307 cvt->len_cvt /= cvt->len_div; | |
1308 | |
1309 if (cvt->filters[++cvt->filter_index]) { | |
1310 cvt->filters[cvt->filter_index] (cvt, format); | |
1311 } | |
1312 } | |
1313 | |
1314 int | 1264 int |
1315 SDL_ConvertAudio(SDL_AudioCVT * cvt) | 1265 SDL_ConvertAudio(SDL_AudioCVT * cvt) |
1316 { | 1266 { |
1317 /* Make sure there's data to convert */ | 1267 /* Make sure there's data to convert */ |
1318 if (cvt->buf == NULL) { | 1268 if (cvt->buf == NULL) { |
1402 int SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format) { | 1352 int SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format) { |
1403 float fc; /* cutoff frequency */ | 1353 float fc; /* cutoff frequency */ |
1404 float coeff[6]; /* floating point iir coefficients b0, b1, b2, a0, a1, a2 */ | 1354 float coeff[6]; /* floating point iir coefficients b0, b1, b2, a0, a1, a2 */ |
1405 float scale; | 1355 float scale; |
1406 float w0, alpha, cosw0; | 1356 float w0, alpha, cosw0; |
1357 int i; | |
1407 | 1358 |
1408 /* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */ | 1359 /* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */ |
1409 static const float Q = 5.0f; | 1360 static const float Q = 5.0f; |
1410 static const float CUTOFF = 0.4f; | 1361 static const float CUTOFF = 0.4f; |
1411 | 1362 |
1425 coeff[3] = 1.0f; /* a0 is normalized to 1 */ | 1376 coeff[3] = 1.0f; /* a0 is normalized to 1 */ |
1426 coeff[4] = -2.0f * cosw0 * scale; | 1377 coeff[4] = -2.0f * cosw0 * scale; |
1427 coeff[5] = (1.0f - alpha) * scale; | 1378 coeff[5] = (1.0f - alpha) * scale; |
1428 | 1379 |
1429 /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */ | 1380 /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */ |
1381 #define convert_fixed(type, fix) { \ | |
1382 type *cvt_coeff = (type *)cvt->coeff; \ | |
1383 for(i = 0; i < 6; ++i) { \ | |
1384 cvt_coeff[i] = fix(coeff[i]); \ | |
1385 } \ | |
1386 } | |
1387 | |
1430 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { | 1388 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { |
1431 float *cvt_coeff = (float *)cvt->coeff; | 1389 float *cvt_coeff = (float *)cvt->coeff; |
1432 int i; | |
1433 for(i = 0; i < 6; ++i) { | 1390 for(i = 0; i < 6; ++i) { |
1434 cvt_coeff[i] = coeff[i]; | 1391 cvt_coeff[i] = coeff[i]; |
1435 } | 1392 } |
1436 } else { | 1393 } else { |
1394 switch(SDL_AUDIO_BITSIZE(format)) { | |
1395 case 8: | |
1396 convert_fixed(Uint8, SDL_Make_2_6); | |
1397 break; | |
1398 case 16: | |
1399 convert_fixed(Uint16, SDL_Make_2_14); | |
1400 break; | |
1401 case 32: | |
1402 convert_fixed(Uint32, SDL_Make_2_30); | |
1403 break; | |
1404 } | |
1437 } | 1405 } |
1406 | |
1407 #ifdef DEBUG_CONVERT | |
1408 #define debug_iir(type) { \ | |
1409 type *cvt_coeff = (type *)cvt->coeff; \ | |
1410 for(i = 0; i < 6; ++i) { \ | |
1411 printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \ | |
1412 } \ | |
1413 } | |
1414 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { | |
1415 float *cvt_coeff = (float *)cvt->coeff; | |
1416 for(i = 0; i < 6; ++i) { \ | |
1417 printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]); \ | |
1418 } | |
1419 } else { | |
1420 switch(SDL_AUDIO_BITSIZE(format)) { | |
1421 case 8: | |
1422 debug_iir(Uint8); | |
1423 break; | |
1424 case 16: | |
1425 debug_iir(Uint16); | |
1426 break; | |
1427 case 32: | |
1428 debug_iir(Uint32); | |
1429 break; | |
1430 } | |
1431 } | |
1432 #undef debug_iir | |
1433 #endif | |
1438 | 1434 |
1439 /* Initialize the state buffer to all zeroes, and set initial position */ | 1435 /* Initialize the state buffer to all zeroes, and set initial position */ |
1440 memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4); | 1436 memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4); |
1441 cvt->state_pos = 0; | 1437 cvt->state_pos = 0; |
1438 #undef convert_fixed | |
1442 } | 1439 } |
1443 | 1440 |
1444 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */ | 1441 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */ |
1445 int SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) { | 1442 static void SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) { |
1446 int i, n; | 1443 int i, n; |
1447 | 1444 |
1448 n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4); | 1445 n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4); |
1449 | 1446 |
1447 /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? */ | |
1448 #define iir_fix(type, mult) {\ | |
1449 type *coeff = (type *)cvt->coeff; \ | |
1450 type *state = (type *)cvt->state_buf; \ | |
1451 type *buf = (type *)cvt->buf; \ | |
1452 type temp; \ | |
1453 for(i = 0; i < n; ++i) { \ | |
1454 temp = buf[n] >> 1; \ | |
1455 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]); \ | |
1457 state[1] = temp; \ | |
1458 state[3] = buf[n]; \ | |
1459 cvt->state_pos = 0; \ | |
1460 } 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]); \ | |
1462 state[0] = temp; \ | |
1463 state[2] = buf[n]; \ | |
1464 cvt->state_pos = 0; \ | |
1465 } \ | |
1466 } \ | |
1467 } | |
1468 | |
1450 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { | 1469 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { |
1451 float *coeff = (float *)cvt->coeff; | 1470 float *coeff = (float *)cvt->coeff; |
1452 float *state = (float *)cvt->state_buf; | 1471 float *state = (float *)cvt->state_buf; |
1453 float *buf = (float *)cvt->buf; | 1472 float *buf = (float *)cvt->buf; |
1454 float temp; | 1473 float temp; |
1455 | 1474 |
1456 | |
1457 for(i = 0; i < n; ++i) { | 1475 for(i = 0; i < n; ++i) { |
1458 /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */ | 1476 /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */ |
1459 temp = buf[n]; | 1477 temp = buf[n]; |
1460 if( cvt->state_pos ) { | 1478 if(cvt->state_pos) { |
1461 buf[n] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3]; | 1479 buf[n] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3]; |
1462 state[1] = temp; | 1480 state[1] = temp; |
1463 state[3] = buf[n]; | 1481 state[3] = buf[n]; |
1464 cvt->state_pos = 0; | 1482 cvt->state_pos = 0; |
1465 } else { | 1483 } else { |
1468 state[2] = buf[n]; | 1486 state[2] = buf[n]; |
1469 cvt->state_pos = 1; | 1487 cvt->state_pos = 1; |
1470 } | 1488 } |
1471 } | 1489 } |
1472 } else { | 1490 } else { |
1491 switch(SDL_AUDIO_BITSIZE(format)) { | |
1492 case 8: | |
1493 iir_fix(Uint8, SDL_FixMpy8); | |
1494 break; | |
1495 case 16: | |
1496 iir_fix(Uint16, SDL_FixMpy16); | |
1497 break; | |
1498 case 32: | |
1499 iir_fix(Uint32, SDL_FixMpy32); | |
1500 break; | |
1501 } | |
1473 } | 1502 } |
1503 #undef iir_fix | |
1474 } | 1504 } |
1475 | 1505 |
1476 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct */ | 1506 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct */ |
1477 int SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) { | 1507 static void SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) { |
1478 int n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4); | 1508 int n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4); |
1479 int m = cvt->len_sinc; | 1509 int m = cvt->len_sinc; |
1480 int i, j; | 1510 int i, j; |
1481 | 1511 |
1482 /* Note: this makes use of the symmetry of the sinc filter. | 1512 /* Note: this makes use of the symmetry of the sinc filter. |
1483 We can also make a big optimization here by taking advantage | 1513 We can also make a big optimization here by taking advantage |
1484 of the fact that the signal is zero stuffed, so we can do | 1514 of the fact that the signal is zero stuffed, so we can do |
1485 significantly fewer multiplications and additions. | 1515 significantly fewer multiplications and additions. |
1486 */ | 1516 */ |
1487 #define filter_sinc(type, shift_bits) { \ | 1517 #define filter_sinc(type, mult) { \ |
1488 type *sinc = (type *)cvt->coeff; \ | 1518 type *sinc = (type *)cvt->coeff; \ |
1489 type *state = (type *)cvt->state_buf; \ | 1519 type *state = (type *)cvt->state_buf; \ |
1490 type *buf = (type *)cvt->buf; \ | 1520 type *buf = (type *)cvt->buf; \ |
1491 for(i = 0; i < n; ++i) { \ | 1521 for(i = 0; i < n; ++i) { \ |
1492 state[cvt->state_pos++] = buf[i] >> shift_bits; \ | |
1493 if(cvt->state_pos == m) cvt->state_pos = 0; \ | 1522 if(cvt->state_pos == m) cvt->state_pos = 0; \ |
1494 buf[i] = 0; \ | 1523 buf[i] = 0; \ |
1495 for(j = 0; j < m; ++j) { \ | 1524 for(j = 0; j < m; ++j) { \ |
1496 buf[i] += state[j] * sinc[j]; \ | 1525 buf[i] += mult(state[j], sinc[j]); \ |
1497 } \ | 1526 } \ |
1498 } \ | 1527 } \ |
1499 } | 1528 } |
1500 | 1529 |
1501 /* If it's floating point, we don't need to do any shifting */ | 1530 /* If it's floating point, we don't need to do any shifting */ |
1513 } | 1542 } |
1514 } | 1543 } |
1515 } else { | 1544 } else { |
1516 switch (SDL_AUDIO_BITSIZE(format)) { | 1545 switch (SDL_AUDIO_BITSIZE(format)) { |
1517 case 8: | 1546 case 8: |
1518 filter_sinc(Uint8, 4); | 1547 filter_sinc(Uint8, SDL_FixMpy8); |
1519 break; | 1548 break; |
1520 case 16: | 1549 case 16: |
1521 filter_sinc(Uint16, 8); | 1550 filter_sinc(Uint16, SDL_FixMpy16); |
1522 break; | 1551 break; |
1523 case 32: | 1552 case 32: |
1524 filter_sinc(Uint32, 16); | 1553 filter_sinc(Uint32, SDL_FixMpy32); |
1525 break; | 1554 break; |
1526 } | 1555 } |
1527 } | 1556 } |
1528 | 1557 |
1529 #undef filter_sinc | 1558 #undef filter_sinc |
1579 } | 1608 } |
1580 | 1609 |
1581 /* Now normalize and convert to fixed point. We scale everything to half the precision | 1610 /* Now normalize and convert to fixed point. We scale everything to half the precision |
1582 of whatever datatype we're using, for example, 16 bit data means we use 8 bits */ | 1611 of whatever datatype we're using, for example, 16 bit data means we use 8 bits */ |
1583 | 1612 |
1584 #define convert_fixed(type, size) { \ | 1613 #define convert_fixed(type, fix) { \ |
1585 norm_fact = size / norm_sum; \ | 1614 norm_fact = 1.0f / norm_sum; \ |
1586 type *dst = (type *)cvt->coeff; \ | 1615 type *dst = (type *)cvt->coeff; \ |
1587 for( i = 0; i <= m; ++i ) { \ | 1616 for( i = 0; i <= m; ++i ) { \ |
1588 dst[i] = (type)(fSinc[i] * norm_fact); \ | 1617 dst[i] = fix(fSinc[i] * norm_fact); \ |
1589 } \ | 1618 } \ |
1590 } | 1619 } |
1591 | 1620 |
1592 /* If we're using floating point, we only need to normalize */ | 1621 /* If we're using floating point, we only need to normalize */ |
1593 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { | 1622 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) { |
1597 fDest[i] = fSinc[i] * norm_fact; | 1626 fDest[i] = fSinc[i] * norm_fact; |
1598 } | 1627 } |
1599 } else { | 1628 } else { |
1600 switch (SDL_AUDIO_BITSIZE(format)) { | 1629 switch (SDL_AUDIO_BITSIZE(format)) { |
1601 case 8: | 1630 case 8: |
1602 convert_fixed(Uint8, 0x0e); | 1631 convert_fixed(Uint8, SDL_Make_1_7); |
1603 break; | 1632 break; |
1604 case 16: | 1633 case 16: |
1605 convert_fixed(Uint16, 0xfe); | 1634 convert_fixed(Uint16, SDL_Make_1_15); |
1606 break; | 1635 break; |
1607 case 32: | 1636 case 32: |
1608 convert_fixed(Uint32, 0xfffe); | 1637 convert_fixed(Uint32, SDL_Make_1_31); |
1609 break; | 1638 break; |
1610 } | 1639 } |
1611 } | 1640 } |
1612 | 1641 |
1613 /* Initialize the state buffer to all zeroes, and set initial position */ | 1642 /* Initialize the state buffer to all zeroes, and set initial position */ |
1628 b = temp; | 1657 b = temp; |
1629 } | 1658 } |
1630 return a; | 1659 return a; |
1631 } | 1660 } |
1632 | 1661 |
1662 /* Perform proper resampling */ | |
1663 static void SDLCALL | |
1664 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format) | |
1665 { | |
1666 int i, j; | |
1667 | |
1668 #ifdef DEBUG_CONVERT | |
1669 printf("Converting audio rate via proper resampling (mono)\n"); | |
1670 #endif | |
1671 | |
1672 #define zerostuff_mono(type) { \ | |
1673 const type *src = (const type *) (cvt->buf + cvt->len_cvt); \ | |
1674 type *dst = (type *) (cvt->buf + (cvt->len_cvt * cvt->len_mult)); \ | |
1675 for (i = cvt->len_cvt / sizeof (type); i; --i) { \ | |
1676 src--; \ | |
1677 dst[-1] = src[0]; \ | |
1678 for( j = -cvt->len_mult; j < -1; ++j ) { \ | |
1679 dst[j] = 0; \ | |
1680 } \ | |
1681 dst -= cvt->len_mult; \ | |
1682 } \ | |
1683 } | |
1684 | |
1685 #define discard_mono(type) { \ | |
1686 const type *src = (const type *) (cvt->buf); \ | |
1687 type *dst = (type *) (cvt->buf); \ | |
1688 for (i = 0; i < cvt->len_cvt / cvt->len_div / sizeof (type); ++i) { \ | |
1689 dst[0] = src[0]; \ | |
1690 src += cvt->len_div; \ | |
1691 ++dst; \ | |
1692 } \ | |
1693 } | |
1694 | |
1695 // Step 1: Zero stuff the conversion buffer | |
1696 #ifdef DEBUG_CONVERT | |
1697 printf("Zero-stuffing by a factor of %u\n", cvt->len_mult); | |
1698 #endif | |
1699 switch (SDL_AUDIO_BITSIZE(format)) { | |
1700 case 8: | |
1701 zerostuff_mono(Uint8); | |
1702 break; | |
1703 case 16: | |
1704 zerostuff_mono(Uint16); | |
1705 break; | |
1706 case 32: | |
1707 zerostuff_mono(Uint32); | |
1708 break; | |
1709 } | |
1710 | |
1711 cvt->len_cvt *= cvt->len_mult; | |
1712 | |
1713 // Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies | |
1714 SDL_FilterIIR( cvt, format ); | |
1715 | |
1716 // Step 3: Discard unnecessary samples | |
1717 #ifdef DEBUG_CONVERT | |
1718 printf("Discarding samples by a factor of %u\n", cvt->len_div); | |
1719 #endif | |
1720 switch (SDL_AUDIO_BITSIZE(format)) { | |
1721 case 8: | |
1722 discard_mono(Uint8); | |
1723 break; | |
1724 case 16: | |
1725 discard_mono(Uint16); | |
1726 break; | |
1727 case 32: | |
1728 discard_mono(Uint32); | |
1729 break; | |
1730 } | |
1731 | |
1732 #undef zerostuff_mono | |
1733 #undef discard_mono | |
1734 | |
1735 cvt->len_cvt /= cvt->len_div; | |
1736 | |
1737 if (cvt->filters[++cvt->filter_index]) { | |
1738 cvt->filters[cvt->filter_index] (cvt, format); | |
1739 } | |
1740 } | |
1741 | |
1633 | 1742 |
1634 /* Creates a set of audio filters to convert from one format to another. | 1743 /* Creates a set of audio filters to convert from one format to another. |
1635 Returns -1 if the format conversion is not supported, 0 if there's | 1744 Returns -1 if the format conversion is not supported, 0 if there's |
1636 no conversion needed, or 1 if the audio filter is set up. | 1745 no conversion needed, or 1 if the audio filter is set up. |
1637 */ | 1746 */ |
1719 } | 1828 } |
1720 | 1829 |
1721 /* Do rate conversion */ | 1830 /* Do rate conversion */ |
1722 int rate_gcd; | 1831 int rate_gcd; |
1723 rate_gcd = SDL_GCD(src_rate, dst_rate); | 1832 rate_gcd = SDL_GCD(src_rate, dst_rate); |
1724 cvt->len_mult = dst_rate / rate_gcd; | 1833 cvt->len_mult = 2 * dst_rate / rate_gcd; |
1725 cvt->len_div = src_rate / rate_gcd; | 1834 cvt->len_div = 2 * src_rate / rate_gcd; |
1726 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div; | 1835 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div; |
1727 cvt->filters[cvt->filter_index++] = SDL_Resample; | 1836 cvt->filters[cvt->filter_index++] = SDL_Resample; |
1837 SDL_BuildIIRLowpass(cvt, dst_fmt); | |
1728 | 1838 |
1729 /*cvt->rate_incr = 0.0; | 1839 /*cvt->rate_incr = 0.0; |
1730 if ((src_rate / 100) != (dst_rate / 100)) { | 1840 if ((src_rate / 100) != (dst_rate / 100)) { |
1731 Uint32 hi_rate, lo_rate; | 1841 Uint32 hi_rate, lo_rate; |
1732 int len_mult; | 1842 int len_mult; |
1817 cvt->filters[cvt->filter_index] = NULL; | 1927 cvt->filters[cvt->filter_index] = NULL; |
1818 } | 1928 } |
1819 return (cvt->needed); | 1929 return (cvt->needed); |
1820 } | 1930 } |
1821 | 1931 |
1932 #undef SDL_FixMpy8 | |
1933 #undef SDL_FixMpy16 | |
1934 #undef SDL_FixMpy32 | |
1935 #undef SDL_Make_1_7 | |
1936 #undef SDL_Make_1_15 | |
1937 #undef SDL_Make_1_31 | |
1938 #undef SDL_Make_2_6 | |
1939 #undef SDL_Make_2_14 | |
1940 #undef SDL_Make_2_30 | |
1941 | |
1822 /* vi: set ts=4 sw=4 expandtab: */ | 1942 /* vi: set ts=4 sw=4 expandtab: */ |