Mercurial > sdl-ios-xcode
comparison src/audio/SDL_audiocvt.c @ 2662:5470680ca587 gsoc2008_audio_resampling
Made a very significant optimization to the FIR filter which I believe I can take a little further. Right now the FIR filter size is 768 and I get some free() bugs, so this is something I need to debug.
author | Aaron Wishnick <schnarf@gmail.com> |
---|---|
date | Thu, 10 Jul 2008 07:02:18 +0000 |
parents | d38309be5178 |
children | 0caed045d01b |
comparison
equal
deleted
inserted
replaced
2661:d38309be5178 | 2662:5470680ca587 |
---|---|
1534 Note: We can make a big optimization here by taking advantage | 1534 Note: We can make a big optimization here by taking advantage |
1535 of the fact that the signal is zero stuffed, so we can do | 1535 of the fact that the signal is zero stuffed, so we can do |
1536 significantly fewer multiplications and additions. However, this | 1536 significantly fewer multiplications and additions. However, this |
1537 depends on the zero stuffing ratio, so it may not pay off. | 1537 depends on the zero stuffing ratio, so it may not pay off. |
1538 */ | 1538 */ |
1539 /* We only calculate the values of samples which are 0 (mod len_div) because those are the only ones used */ | |
1539 #define filter_sinc(type, mult) { \ | 1540 #define filter_sinc(type, mult) { \ |
1540 type *sinc = (type *)cvt->coeff; \ | 1541 type *sinc = (type *)cvt->coeff; \ |
1541 type *state = (type *)cvt->state_buf; \ | 1542 type *state = (type *)cvt->state_buf; \ |
1542 type *buf = (type *)cvt->buf; \ | 1543 type *buf = (type *)cvt->buf; \ |
1543 for(i = 0; i < n; ++i) { \ | 1544 for(i = 0; i < n; ++i) { \ |
1544 state[cvt->state_pos] = buf[i]; \ | 1545 state[cvt->state_pos] = buf[i]; \ |
1545 buf[i] = 0; \ | 1546 buf[i] = 0; \ |
1546 for(j = 0; j < m; ++j) { \ | 1547 if( i % cvt->len_div == 0 ) { \ |
1547 buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \ | 1548 for(j = 0; j < m; ++j) { \ |
1548 } \ | 1549 buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \ |
1550 } \ | |
1551 }\ | |
1549 cvt->state_pos = (cvt->state_pos + 1) % m; \ | 1552 cvt->state_pos = (cvt->state_pos + 1) % m; \ |
1550 } \ | 1553 } \ |
1551 } | 1554 } |
1552 | 1555 |
1553 /* If it's floating point, do it normally, otherwise used fixed-point code */ | 1556 /* If it's floating point, do it normally, otherwise used fixed-point code */ |
1614 /* Set up the filter parameters */ | 1617 /* Set up the filter parameters */ |
1615 fc = (cvt->len_mult > cvt->len_div) ? 0.5f / (float)cvt->len_mult : 0.5f / (float)cvt->len_div; | 1618 fc = (cvt->len_mult > cvt->len_div) ? 0.5f / (float)cvt->len_mult : 0.5f / (float)cvt->len_div; |
1616 #ifdef DEBUG_CONVERT | 1619 #ifdef DEBUG_CONVERT |
1617 printf("Lowpass cutoff frequency = %f\n", fc); | 1620 printf("Lowpass cutoff frequency = %f\n", fc); |
1618 #endif | 1621 #endif |
1619 // fc = 0.02f; | |
1620 two_pi_fc = 2.0f * M_PI * fc; | 1622 two_pi_fc = 2.0f * M_PI * fc; |
1621 two_pi_over_m = 2.0f * M_PI / (float)m; | 1623 two_pi_over_m = 2.0f * M_PI / (float)m; |
1622 four_pi_over_m = 2.0f * two_pi_over_m; | 1624 four_pi_over_m = 2.0f * two_pi_over_m; |
1623 m_over_two = (float)m / 2.0f; | 1625 m_over_two = (float)m / 2.0f; |
1624 norm_sum = 0.0f; | 1626 norm_sum = 0.0f; |
1633 } | 1635 } |
1634 norm_sum += fabs(fSinc[i]); | 1636 norm_sum += fabs(fSinc[i]); |
1635 } | 1637 } |
1636 | 1638 |
1637 #define convert_fixed(type, fix) { \ | 1639 #define convert_fixed(type, fix) { \ |
1638 norm_fact = 0.7f / norm_sum; \ | 1640 norm_fact = 0.5f / norm_sum; \ |
1639 type *dst = (type *)cvt->coeff; \ | 1641 type *dst = (type *)cvt->coeff; \ |
1640 for( i = 0; i <= m; ++i ) { \ | 1642 for( i = 0; i <= m; ++i ) { \ |
1641 dst[i] = fix(fSinc[i] * norm_fact); \ | 1643 dst[i] = fix(fSinc[i] * norm_fact); \ |
1642 } \ | 1644 } \ |
1643 } | 1645 } |
1707 } | 1709 } |
1708 | 1710 |
1709 #define discard_mono(type) { \ | 1711 #define discard_mono(type) { \ |
1710 const type *src = (const type *) (cvt->buf); \ | 1712 const type *src = (const type *) (cvt->buf); \ |
1711 type *dst = (type *) (cvt->buf); \ | 1713 type *dst = (type *) (cvt->buf); \ |
1712 for (i = 0; i < cvt->len_cvt / cvt->len_div / sizeof (type); ++i) { \ | 1714 for (i = 0; i < (cvt->len_cvt / sizeof(type)) / cvt->len_div; ++i) { \ |
1713 dst[0] = src[0]; \ | 1715 dst[0] = src[0]; \ |
1714 src += cvt->len_div; \ | 1716 src += cvt->len_div; \ |
1715 ++dst; \ | 1717 ++dst; \ |
1716 } \ | 1718 } \ |
1717 } | 1719 } |
1733 } | 1735 } |
1734 | 1736 |
1735 cvt->len_cvt *= cvt->len_mult; | 1737 cvt->len_cvt *= cvt->len_mult; |
1736 | 1738 |
1737 // Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies | 1739 // Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies |
1738 SDL_FilterFIR( cvt, format ); | 1740 QSDL_FilterFIR( cvt, format ); |
1741 | |
1742 // OPTIMIZATION: we only need to calculate the non-discarded samples. This could be a big speedup! | |
1739 | 1743 |
1740 // Step 3: Discard unnecessary samples | 1744 // Step 3: Discard unnecessary samples |
1745 | |
1741 #ifdef DEBUG_CONVERT | 1746 #ifdef DEBUG_CONVERT |
1742 printf("Discarding samples by a factor of %u\n", cvt->len_div); | 1747 printf("Discarding samples by a factor of %u\n", cvt->len_div); |
1743 #endif | 1748 #endif |
1744 switch (SDL_AUDIO_BITSIZE(format)) { | 1749 switch (SDL_AUDIO_BITSIZE(format)) { |
1745 case 8: | 1750 case 8: |
1857 cvt->len_mult = dst_rate / rate_gcd; | 1862 cvt->len_mult = dst_rate / rate_gcd; |
1858 cvt->len_div = src_rate / rate_gcd; | 1863 cvt->len_div = src_rate / rate_gcd; |
1859 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div; | 1864 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div; |
1860 cvt->filters[cvt->filter_index++] = SDL_Resample; | 1865 cvt->filters[cvt->filter_index++] = SDL_Resample; |
1861 //SDL_BuildIIRLowpass(cvt, dst_fmt); | 1866 //SDL_BuildIIRLowpass(cvt, dst_fmt); |
1862 SDL_BuildWindowedSinc(cvt, dst_fmt, 20); | 1867 SDL_BuildWindowedSinc(cvt, dst_fmt, 768); |
1863 | 1868 |
1864 /*cvt->rate_incr = 0.0; | 1869 /*cvt->rate_incr = 0.0; |
1865 if ((src_rate / 100) != (dst_rate / 100)) { | 1870 if ((src_rate / 100) != (dst_rate / 100)) { |
1866 Uint32 hi_rate, lo_rate; | 1871 Uint32 hi_rate, lo_rate; |
1867 int len_mult; | 1872 int len_mult; |