IIR filtering now seems to work fine. Fixed point code also seems to be good.
1.1 --- a/src/audio/SDL_audiocvt.c Wed Jun 18 22:42:27 2008 +0000
1.2 +++ b/src/audio/SDL_audiocvt.c Thu Jun 19 20:11:06 2008 +0000
1.3 @@ -42,21 +42,24 @@
1.4 dest = ((y >> 16) & 0xffff) + (a * c); \
1.5 }*/
1.6 /* 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 */
1.7 -
1.8 -#define SDL_FixMpy32(a, b) ((((long long)a * (long long)b) >> 32) & 0xffffffff)
1.9 -#ifdef DEBUG_CONVERT
1.10 -#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);
1.11 +
1.12 +/* We hope here that the right shift includes sign extension */
1.13 +#ifdef SDL_HAS_64BIT_Type
1.14 +#define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
1.15 #else
1.16 -#define SDL_FixMpy16(a, b) ((((long)a * (long)b) >> 16) & 0xffff)
1.17 +/* need to do something more complicated here */
1.18 +#define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
1.19 #endif
1.20 -#define SDL_FixMpy8(a, b) ((((short)a * (short)b) >> 8) & 0xff)
1.21 -
1.22 -#define SDL_Make_1_7(a) (Uint8)(a * 128.0f)
1.23 -#define SDL_Make_1_15(a) (Uint16)(a * 32768.0f)
1.24 -#define SDL_Make_1_31(a) (Uint32)(a * 2147483648.0f)
1.25 -#define SDL_Make_2_6(a) (Uint8)(a * 64.0f)
1.26 -#define SDL_Make_2_14(a) (Uint16)(a * 16384.0f)
1.27 -#define SDL_Make_2_30(a) (Uint32)(a * 1073741824.0f)
1.28 +/* Confirmed that SDL_FixMpy16 works, need to check 8 and 32 */
1.29 +#define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
1.30 +#define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
1.31 +/* Everything is signed! */
1.32 +#define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
1.33 +#define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
1.34 +#define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
1.35 +#define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
1.36 +#define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
1.37 +#define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
1.38
1.39 /* Effectively mix right and left channels into a single channel */
1.40 static void SDLCALL
1.41 @@ -1440,31 +1443,48 @@
1.42
1.43 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */
1.44 static void SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
1.45 - int i, n;
1.46 + Uint32 i, n;
1.47
1.48 - n = cvt->len_cvt / (SDL_AUDIO_BITSIZE(format) / 4);
1.49 + /* TODO: Check that n is calculated right */
1.50 + n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
1.51
1.52 - /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? */
1.53 + /* 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.*/
1.54 + /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */
1.55 #define iir_fix(type, mult) {\
1.56 type *coeff = (type *)cvt->coeff; \
1.57 type *state = (type *)cvt->state_buf; \
1.58 type *buf = (type *)cvt->buf; \
1.59 type temp; \
1.60 for(i = 0; i < n; ++i) { \
1.61 - temp = buf[n] >> 1; \
1.62 + temp = buf[i] >> 1; \
1.63 if(cvt->state_pos) { \
1.64 - 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]); \
1.65 + 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]); \
1.66 state[1] = temp; \
1.67 - state[3] = buf[n]; \
1.68 + state[3] = buf[i]; \
1.69 cvt->state_pos = 0; \
1.70 } else { \
1.71 - 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]); \
1.72 + 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]); \
1.73 state[0] = temp; \
1.74 - state[2] = buf[n]; \
1.75 - cvt->state_pos = 0; \
1.76 + state[2] = buf[i]; \
1.77 + cvt->state_pos = 1; \
1.78 } \
1.79 } \
1.80 }
1.81 +/* Need to test to see if the previous method or this one is faster */
1.82 +/*#define iir_fix(type, mult) {\
1.83 + type *coeff = (type *)cvt->coeff; \
1.84 + type *state = (type *)cvt->state_buf; \
1.85 + type *buf = (type *)cvt->buf; \
1.86 + type temp; \
1.87 + for(i = 0; i < n; ++i) { \
1.88 + temp = buf[i] >> 1; \
1.89 + 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]); \
1.90 + state[1] = state[0]; \
1.91 + state[0] = temp; \
1.92 + state[3] = state[2]; \
1.93 + state[2] = buf[i]; \
1.94 + } \
1.95 + }*/
1.96
1.97 if(SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1.98 float *coeff = (float *)cvt->coeff;
1.99 @@ -1474,29 +1494,30 @@
1.100
1.101 for(i = 0; i < n; ++i) {
1.102 /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
1.103 - temp = buf[n];
1.104 + temp = buf[i];
1.105 if(cvt->state_pos) {
1.106 - buf[n] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3];
1.107 + buf[i] = coeff[0] * buf[n] + coeff[1] * state[0] + coeff[2] * state[1] - coeff[4] * state[2] - coeff[5] * state[3];
1.108 state[1] = temp;
1.109 - state[3] = buf[n];
1.110 + state[3] = buf[i];
1.111 cvt->state_pos = 0;
1.112 } else {
1.113 - buf[n] = coeff[0] * buf[n] + coeff[1] * state[1] + coeff[2] * state[0] - coeff[4] * state[3] - coeff[5] * state[2];
1.114 + buf[i] = coeff[0] * buf[n] + coeff[1] * state[1] + coeff[2] * state[0] - coeff[4] * state[3] - coeff[5] * state[2];
1.115 state[0] = temp;
1.116 - state[2] = buf[n];
1.117 + state[2] = buf[i];
1.118 cvt->state_pos = 1;
1.119 }
1.120 }
1.121 } else {
1.122 + /* Treat everything as signed! */
1.123 switch(SDL_AUDIO_BITSIZE(format)) {
1.124 case 8:
1.125 - iir_fix(Uint8, SDL_FixMpy8);
1.126 + iir_fix(Sint8, SDL_FixMpy8);
1.127 break;
1.128 case 16:
1.129 - iir_fix(Uint16, SDL_FixMpy16);
1.130 + iir_fix(Sint16, SDL_FixMpy16);
1.131 break;
1.132 case 32:
1.133 - iir_fix(Uint32, SDL_FixMpy32);
1.134 + iir_fix(Sint32, SDL_FixMpy32);
1.135 break;
1.136 }
1.137 }
1.138 @@ -1544,13 +1565,13 @@
1.139 } else {
1.140 switch (SDL_AUDIO_BITSIZE(format)) {
1.141 case 8:
1.142 - filter_sinc(Uint8, SDL_FixMpy8);
1.143 + filter_sinc(Sint8, SDL_FixMpy8);
1.144 break;
1.145 case 16:
1.146 - filter_sinc(Uint16, SDL_FixMpy16);
1.147 + filter_sinc(Sint16, SDL_FixMpy16);
1.148 break;
1.149 case 32:
1.150 - filter_sinc(Uint32, SDL_FixMpy32);
1.151 + filter_sinc(Sint32, SDL_FixMpy32);
1.152 break;
1.153 }
1.154 }
1.155 @@ -1830,8 +1851,8 @@
1.156 /* Do rate conversion */
1.157 int rate_gcd;
1.158 rate_gcd = SDL_GCD(src_rate, dst_rate);
1.159 - cvt->len_mult = 2 * dst_rate / rate_gcd;
1.160 - cvt->len_div = 2 * src_rate / rate_gcd;
1.161 + cvt->len_mult = dst_rate / rate_gcd;
1.162 + cvt->len_div = src_rate / rate_gcd;
1.163 cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div;
1.164 cvt->filters[cvt->filter_index++] = SDL_Resample;
1.165 SDL_BuildIIRLowpass(cvt, dst_fmt);