[Scummvm-cvs-logs] CVS: scummvm/sound mixer.cpp,1.37,1.38

Max Horn fingolfin at users.sourceforge.net
Tue Jul 23 07:55:02 CEST 2002


Update of /cvsroot/scummvm/scummvm/sound
In directory usw-pr-cvs1:/tmp/cvs-serv6921/sound

Modified Files:
	mixer.cpp 
Log Message:
fixed Channel_MP3::mix to deal correctly with _silence_cut (this improves lip sync); put cubic interpolation code into a utility class, CubicInterpolator; now three mixers use this, converting the other ones should be simple

Index: mixer.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/mixer.cpp,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- mixer.cpp	22 Jul 2002 12:44:57 -0000	1.37
+++ mixer.cpp	23 Jul 2002 14:54:02 -0000	1.38
@@ -242,19 +242,95 @@
 		_size = _size >> 1;
 }
 
+
+/*
+ * Class that performs cubic interpolation on integer data.
+ * It is expected that the data is equidistant, i.e. all have the same
+ * horizontal distance. This is obviously the case for sampled audio.
+ */
+class CubicInterpolator {
+protected:
+	int x0, x1, x2, x3;
+	int a, b, c, d;
+	
+public:
+	CubicInterpolator(int a, int b, int c) : x0(2*a-b), x1(a), x2(b), x3(c)
+	{
+		// We use a simple linear interpolation for x0
+		updateCoefficients();
+	}
+	
+	inline void feedData()
+	{
+		x0 = x1;
+		x1 = x2;
+		x2 = x3;
+		x3 = 2*x2-x1;	// Simple linear interpolation
+		updateCoefficients();
+	}
+
+	inline void feedData(int xNew)
+	{
+		x0 = x1;
+		x1 = x2;
+		x2 = x3;
+		x3 = xNew;
+		updateCoefficients();
+	}
+	
+	/* t must be a 16.16 fixed point number between 0 and 1 */
+	inline int interpolate(uint32 fp_pos)
+	{
+		int result = 0;
+		int t = fp_pos >> 8;
+		result = (a*t + b) >> 8;
+		result = (result * t + c) >> 8;
+		result = (result * t + d) >> 8;
+		result = (result/3 + 1) >> 1;
+		
+		return result;
+	}
+		
+protected:
+	inline void updateCoefficients()
+	{
+		a = ((-x0*2)+(x1*5)-(x2*4)+x3);
+		b = ((x0+x2-(2*x1))*6) << 8;
+		c = ((-4*x0)+x1+(x2*4)-x3) << 8;
+		d = (x1*6) << 8;
+	}
+};
+
 static int16 *mix_signed_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
 																int fp_speed, const int16 *vol_tab, byte *s_end)
 {
 	uint32 fp_pos = *fp_pos_ptr;
 	byte *s = *s_ptr;
 	uint len = *len_ptr;
+	
+	int inc = 1, result;
+	CubicInterpolator	interp(vol_tab[*s], vol_tab[*(s+1)], vol_tab[*(s+2)]);
+
 	do {
-		fp_pos += fp_speed;
-		*data++ += vol_tab[*s];
-		*data++ += vol_tab[*s];
-		s += fp_pos >> 16;
-		fp_pos &= 0x0000FFFF;
-	} while ((--len) && (s < s_end));
+		do {
+			result = interp.interpolate(fp_pos);
+	
+			*data++ += result;
+			*data++ += result;
+	
+			fp_pos += fp_speed;
+			inc = fp_pos >> 16;
+			s += inc;
+			len--;
+			fp_pos &= 0x0000FFFF;
+		} while (!inc && len && (s < s_end));
+		
+		if (s+2 < s_end)
+			interp.feedData(vol_tab[*(s+2)]);
+		else
+			interp.feedData();
+
+	} while (len && (s < s_end));
 
 	*fp_pos_ptr = fp_pos;
 	*s_ptr = s;
@@ -286,23 +362,13 @@
 	uint32 fp_pos = *fp_pos_ptr;
 	byte *s = *s_ptr;
 	uint len = *len_ptr;
-	int x0, x1, x2, x3;
-	int a, b, c, d;
-	int inc = 1, result, t;
-	x0 = x1 = vol_tab[*s ^ 0x80];
-	x2 = vol_tab[*(s+1) ^ 0x80];
-	x3 = vol_tab[*(s+2) ^ 0x80];
+	
+	int inc = 1, result;
+	CubicInterpolator	interp(vol_tab[*s ^ 0x80], vol_tab[*(s+1) ^ 0x80], vol_tab[*(s+2) ^ 0x80]);
+
 	do {
-		a = ((-x0*2)+(x1*5)-(x2*4)+x3);
-		b = ((x0+x2-(2*x1))*6) << 8;
-		c = ((-4*x0)+x1+(x2*4)-x3) << 8;
-		d = (x1*6) << 8;
 		do {
-			t = fp_pos >> 8;
-			result = (a*t + b) >> 8;
-			result = (result * t + c) >> 8;
-			result = (result * t + d) >> 8;
-			result = (result/3 + 1) >> 1;
+			result = interp.interpolate(fp_pos);
 	
 			*data++ += result;
 			*data++ += result;
@@ -310,13 +376,15 @@
 			fp_pos += fp_speed;
 			inc = fp_pos >> 16;
 			s += inc;
+			len--;
 			fp_pos &= 0x0000FFFF;
-		} while ((--len) && !inc && (s < s_end));
-		x0 = x1;
-		x1 = x2;
-		x2 = x3;
+		} while (!inc && len && (s < s_end));
+
 		if (s+2 < s_end)
-			x3 = vol_tab[*(s+2) ^ 0x80];
+			interp.feedData(vol_tab[*(s+2) ^ 0x80]);
+		else
+			interp.feedData();
+
 	} while (len && (s < s_end));
 
 	*fp_pos_ptr = fp_pos;
@@ -336,6 +404,7 @@
 static int16 *mix_unsigned_stereo_8(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
 																		int fp_speed, const int16 *vol_tab, byte *s_end)
 {
+#if OLD
 	uint32 fp_pos = *fp_pos_ptr;
 	byte *s = *s_ptr;
 	uint len = *len_ptr;
@@ -352,10 +421,48 @@
 	*len_ptr = len;
 
 	return data;
+#else
+	uint32 fp_pos = *fp_pos_ptr;
+	byte *s = *s_ptr;
+	uint len = *len_ptr;
+	
+	int inc = 1;
+	CubicInterpolator	left(vol_tab[*s ^ 0x80], vol_tab[*(s+2) ^ 0x80], vol_tab[*(s+4) ^ 0x80]);
+	CubicInterpolator	right(vol_tab[*(s+1) ^ 0x80], vol_tab[*(s+3) ^ 0x80], vol_tab[*(s+5) ^ 0x80]);
+
+	do {
+		do {
+			*data++ += left.interpolate(fp_pos);
+			*data++ += right.interpolate(fp_pos);
+	
+			fp_pos += fp_speed;
+			inc = (fp_pos >> 16) << 1;
+			s += inc;
+			len--;
+			fp_pos &= 0x0000FFFF;
+		} while (!inc && len && (s < s_end));
+
+		if (s+5 < s_end) {
+			left.feedData(vol_tab[*(s+4) ^ 0x80]);
+			right.feedData(vol_tab[*(s+5) ^ 0x80]);
+		} else {
+			left.feedData();
+			right.feedData();
+		}
+
+	} while (len && (s < s_end));
+
+	*fp_pos_ptr = fp_pos;
+	*s_ptr = s;
+	*len_ptr = len;
+
+	return data;
+#endif
 }
 static int16 *mix_signed_mono_16(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
 																 int fp_speed, const int16 *vol_tab, byte *s_end)
 {
+	printf("mix_signed_mono_16\n");
 	uint32 fp_pos = *fp_pos_ptr;
 	unsigned char volume = ((int)vol_tab[1]) * 32 / 255;
 	byte *s = *s_ptr;
@@ -385,6 +492,7 @@
 static int16 *mix_signed_stereo_16(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
 																	 int fp_speed, const int16 *vol_tab, byte *s_end)
 {
+	printf("mix_signed_stereo_16\n");
 	uint32 fp_pos = *fp_pos_ptr;
 	unsigned char volume = ((int)vol_tab[1]) * 32 / 255;
 	byte *s = *s_ptr;
@@ -604,9 +712,9 @@
 	   .SO3 file, you may have to change this value.
 
 	   When using Lame, it seems that the sound starts to have some volume about 50 ms
-	   from the start of the sound => we skip about 1024 samples.
+	   from the start of the sound => we skip about 2 frames (at 22.05 khz).
 	 */
-	_silence_cut = 1024;
+	_silence_cut = 576 * 2;
 }
 
 static inline int scale_sample(mad_fixed_t sample)
@@ -634,18 +742,27 @@
 		real_destroy();
 		return;
 	}
-
+	
 	while (1) {
 		ch = _synth.pcm.samples[0] + _pos_in_frame;
+
+		/* Skip _silence_cut a the start */
+		if ((_pos_in_frame < _synth.pcm.length) && (_silence_cut > 0)) {
+			int diff = _synth.pcm.length - _pos_in_frame;
+			
+			if (diff > _silence_cut)
+				diff = _silence_cut;
+			_silence_cut -= diff;
+			ch += diff;
+			_pos_in_frame += diff;
+		}
+
 		while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) {
-			if (_silence_cut > 0) {
-				_silence_cut--;
-			} else {
-				int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
-				*data++ += sample;
-				*data++ += sample;
-				len--;
-			}
+			int16 sample = (int16)((scale_sample(*ch) * volume) / 32);
+			*data++ += sample;
+			*data++ += sample;
+			len--;
+			ch++;
 			_pos_in_frame++;
 		}
 		if (len == 0)





More information about the Scummvm-git-logs mailing list