IIR filtering now seems to work fine. Fixed point code also seems to be good. gsoc2008_audio_resampling
authorAaron Wishnick <schnarf@gmail.com>
Thu, 19 Jun 2008 20:11:06 +0000
branchgsoc2008_audio_resampling
changeset 2658de29a03cb108
parent 2657 29306e52dab8
child 2659 8da698bc1205
IIR filtering now seems to work fine. Fixed point code also seems to be good.
src/audio/SDL_audiocvt.c
     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);