diff src/modplug/fastmix.cxx @ 2337:107c1fed3d92

Port Schism modplug core.
author "Tony Vroon <chainsaw@gentoo.org>"
date Thu, 24 Jan 2008 12:05:59 +0000
parents 6907fc39b53f
children
line wrap: on
line diff
--- a/src/modplug/fastmix.cxx	Wed Jan 23 19:37:05 2008 +0100
+++ b/src/modplug/fastmix.cxx	Thu Jan 24 12:05:59 2008 +0000
@@ -12,10 +12,6 @@
 #include "sndfile.h"
 #include <math.h>
 
-#ifdef MSC_VER
-#pragma bss_seg(".modplug")
-#endif
-
 // Front Mix Buffer (Also room for interleaved rear mix)
 int MixSoundBuffer[MIXBUFFERSIZE*4];
 
@@ -25,14 +21,8 @@
 extern UINT gnReverbSend;
 #endif
 
-#ifndef MODPLUG_FASTSOUNDLIB
 int MixRearBuffer[MIXBUFFERSIZE*2];
 float MixFloatBuffer[MIXBUFFERSIZE*2];
-#endif
-
-#ifdef MSC_VER
-#pragma bss_seg()
-#endif
 
 
 extern LONG gnDryROfsVol;
@@ -530,37 +520,39 @@
 // Resonant Filters
 
 // Mono
-#define MIX_BEGIN_FILTER\
-	int fy1 = pChannel->nFilter_Y1;\
-	int fy2 = pChannel->nFilter_Y2;\
+#define MIX_BEGIN_FILTER \
+	double fy1 = pChannel->nFilter_Y1;\
+	double fy2 = pChannel->nFilter_Y2;\
+	double ta;
 
-#define MIX_END_FILTER\
+#define MIX_END_FILTER \
 	pChannel->nFilter_Y1 = fy1;\
 	pChannel->nFilter_Y2 = fy2;
 
-#define SNDMIX_PROCESSFILTER\
-	vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
-	fy2 = fy1;\
-	fy1 = vol;\
+#define SNDMIX_PROCESSFILTER \
+ta = ((double)vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\
+fy2 = fy1;\
+fy1 = ta;vol=(int)ta;
 
 // Stereo
-#define MIX_BEGIN_STEREO_FILTER\
-	int fy1 = pChannel->nFilter_Y1;\
-	int fy2 = pChannel->nFilter_Y2;\
-	int fy3 = pChannel->nFilter_Y3;\
-	int fy4 = pChannel->nFilter_Y4;\
+#define MIX_BEGIN_STEREO_FILTER \
+double fy1 = pChannel->nFilter_Y1;\
+double fy2 = pChannel->nFilter_Y2;\
+double fy3 = pChannel->nFilter_Y3;\
+double fy4 = pChannel->nFilter_Y4;\
+double ta, tb;
 
-#define MIX_END_STEREO_FILTER\
-	pChannel->nFilter_Y1 = fy1;\
-	pChannel->nFilter_Y2 = fy2;\
-	pChannel->nFilter_Y3 = fy3;\
-	pChannel->nFilter_Y4 = fy4;\
+#define MIX_END_STEREO_FILTER \
+pChannel->nFilter_Y1 = fy1;\
+pChannel->nFilter_Y2 = fy2;\
+pChannel->nFilter_Y3 = fy3;\
+pChannel->nFilter_Y4 = fy4;\
 
-#define SNDMIX_PROCESSSTEREOFILTER\
-	vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
-	vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\
-	fy2 = fy1; fy1 = vol_l;\
-	fy4 = fy3; fy3 = vol_r;\
+#define SNDMIX_PROCESSSTEREOFILTER \
+ta = ((double)vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\
+tb = ((double)vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1);\
+fy2 = fy1; fy1 = ta;vol_l=(int)ta;\
+fy4 = fy3; fy3 = tb;vol_r=(int)tb;
 
 //////////////////////////////////////////////////////////
 // Interfaces
@@ -659,11 +651,17 @@
 /////////////////////////////////////////////////////
 //
 
-void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples);
-void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
-void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
-void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount);
-void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
+extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount, const float _i2fc);
+extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount, const float _f2ic);
+extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount, const float _i2fc);
+extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount, const float _f2ic);
+
+void InitMixBuffer(int *pBuffer, UINT nSamples);
+void EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
+void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
+
+void StereoMixToFloat(const int *, float *, float *, UINT nCount);
+void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
 
 /////////////////////////////////////////////////////
 // Mono samples functions
@@ -1466,9 +1464,7 @@
 	DWORD nchused, nchmixed;
 
 	if (!count) return 0;
-#ifndef MODPLUG_FASTSOUNDLIB
-	if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2);
-#endif
+	if (gnChannels > 2) InitMixBuffer(MixRearBuffer, count*2);
 	nchused = nchmixed = 0;
 	for (UINT nChn=0; nChn<m_nMixChannels; nChn++)
 	{
@@ -1489,15 +1485,16 @@
 	#ifndef NO_FILTER
 		if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER;
 	#endif
-		if (!(pChannel->dwFlags & CHN_NOIDO))
+		if (!(pChannel->dwFlags & CHN_NOIDO)
+		&& !(gdwSoundSetup & SNDMIX_NORESAMPLING))
 		{
 			// use hq-fir mixer?
 			if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
-				nFlags += MIXNDX_FIRSRC;
-			else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
-				nFlags += MIXNDX_SPLINESRC;
+				nFlags |= MIXNDX_FIRSRC;
+			else if( (gdwSoundSetup & SNDMIX_HQRESAMPLER))
+				nFlags |= MIXNDX_SPLINESRC;
 			else
-				nFlags += MIXNDX_LINEARSRC; // use
+				nFlags |= MIXNDX_LINEARSRC; // use
 		}
 		if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol)
 		 && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp)))
@@ -1536,7 +1533,7 @@
 			pChannel->nPos = 0;
 			pChannel->nPosLo = 0;
 			pChannel->nRampLength = 0;
-			X86_EndChannelOfs(pChannel, pbuffer, nsamples);
+			EndChannelOfs(pChannel, pbuffer, nsamples);
 			*pOfsR += pChannel->nROfs;
 			*pOfsL += pChannel->nLOfs;
 			pChannel->nROfs = pChannel->nLOfs = 0;
@@ -1557,6 +1554,10 @@
 		} else
 		// Do mixing
 		{
+			if (pChannel->nLength) {
+				pChannel->topnote_offset = ((pChannel->nPos << 16) | pChannel->nPosLo) % pChannel->nLength;
+			}
+
 			// Choose function for mixing
 			LPMIXINTERFACE pMixFunc;
 			pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags];
@@ -1593,81 +1594,59 @@
 	return nchused;
 }
 
+static float f2ic = (float)(1 << 28);
+static float i2fc = (float)(1.0 / (1 << 28));
 
-#ifdef MSC_VER
-#pragma warning (disable:4100)
-#endif
+VOID CSoundFile::StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount)
+//-----------------------------------------------------------------------------------------
+{
+	for (UINT i = 0; i < nCount; i++) {
+		*pOut1++ = *pSrc * i2fc; /*!*/
+		pSrc++;
+
+		*pOut2++ = *pSrc * i2fc; /*!*/
+		pSrc++;
+	}
+}
+
+
+VOID CSoundFile::FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount)
+//---------------------------------------------------------------------------------------------
+{
+	for (UINT i = 0; i < nCount; i++) {
+		*pOut++ = (int)(*pIn1 * f2ic);
+		*pOut++ = (int)(*pIn2 * f2ic);
+		pIn1++;
+		pIn2++;
+	}
+}
+
+
+VOID CSoundFile::MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount)
+//------------------------------------------------------------------------
+{
+	for (UINT i = 0; i < nCount; i++) {
+		*pOut++ = *pSrc * i2fc; /*!*/
+		pSrc++;
+	}
+}
+
+
+VOID CSoundFile::FloatToMonoMix(const float *pIn, int *pOut, UINT nCount)
+//-----------------------------------------------------------------------
+{
+	for (UINT i = 0; i < nCount; i++) {
+		*pOut++ = (int)(*pIn * f2ic); /*!*/
+		pIn++;
+	}
+}
+
 
 // Clip and convert to 8 bit
-#ifdef MSC_VER
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//----------------------------------------------------------------------------------------------------------------------------
-{
-    _asm {
-        push ebx
-	push esi
-	push edi
-	mov ebx, 16[esp]		// ebx = 8-bit buffer
-	mov esi, 20[esp]		// esi = pBuffer
-	mov edi, 24[esp]		// edi = lSampleCount
-	mov eax, 28[esp]
-	mov ecx, dword ptr [eax]	// ecx = clipmin
-	mov eax, 32[esp]
-	mov edx, dword ptr [eax]	// edx = clipmax
-cliploop:
-	mov eax, dword ptr [esi]
-	inc ebx
-	cdq
-	and edx, (1 << (24-MIXING_ATTENUATION)) - 1
-	add eax, edx
-	cmp eax, MIXING_CLIPMIN
-	jl cliplow
-	cmp eax, MIXING_CLIPMAX
-	jg cliphigh
-	cmp eax, ecx
-	jl updatemin
-	cmp eax, edx
-	jg updatemax
-cliprecover:
-	add esi, 4
-	sar eax, 24-MIXING_ATTENUATION
-	xor eax, 0x80
-	dec edi
-	mov byte ptr [ebx-1], al
-	jnz cliploop
-	mov eax, 28[esp]
-	mov dword ptr [eax], ecx
-	mov eax, 32[esp]
-	mov dword ptr [eax], edx
-	mov eax, 24[esp]
-	pop edi
-	pop esi
-	pop ebx
-	ret
-updatemin:
-	mov ecx, eax
-	jmp cliprecover
-updatemax:
-	mov edx, eax
-	jmp cliprecover
-cliplow:
-	mov ecx, MIXING_CLIPMIN
-	mov edx, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMIN
-	jmp cliprecover
-cliphigh:
-	mov ecx, MIXING_CLIPMIN
-	mov edx, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMAX
-	jmp cliprecover
-	}
-}
-#else //MSC_VER
 //---GCCFIX: Asm replaced with C function
 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
-DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+DWORD Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
 {
-	int vumin = *lpMin, vumax = *lpMax;
 	unsigned char *p = (unsigned char *)lp8;
 	for (UINT i=0; i<lSampleCount; i++)
 	{
@@ -1676,92 +1655,18 @@
 			n = MIXING_CLIPMIN;
 		else if (n > MIXING_CLIPMAX)
 			n = MIXING_CLIPMAX;
-		if (n < vumin)
-			vumin = n;
-		else if (n > vumax)
-			vumax = n;
+		if (n < mins[i&1])
+			mins[i&1]= n;
+		else if (n > maxs[i&1])
+			maxs[i&1] = n;
 		p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80;	// 8-bit unsigned
 	}
-	*lpMin = vumin;
-	*lpMax = vumax;
 	return lSampleCount;
 }
-#endif //MSC_VER, else
-
-
-#ifdef MSC_VER
-// Clip and convert to 16 bit
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//-----------------------------------------------------------------------------------------------------------------------------
-{
-	_asm {
-	push ebx
-	push esi
-	push edi
-	mov ebx, 16[esp]		// ebx = 16-bit buffer
-	mov eax, 28[esp]
-	mov esi, 20[esp]		// esi = pBuffer
-	mov ecx, dword ptr [eax]	// ecx = clipmin
-	mov edi, 24[esp]		// edi = lSampleCount
-	mov eax, 32[esp]
-	push ebp
-	mov ebp, dword ptr [eax]	// edx = clipmax
-cliploop:
-	mov eax, dword ptr [esi]
-	add ebx, 2
-	cdq
-	and edx, (1 << (16-MIXING_ATTENUATION)) - 1
-	add esi, 4
-	add eax, edx
-	cmp eax, MIXING_CLIPMIN
-	jl cliplow
-	cmp eax, MIXING_CLIPMAX
-	jg cliphigh
-	cmp eax, ecx
-	jl updatemin
-	cmp eax, ebp
-	jg updatemax
-cliprecover:
-	sar eax, 16-MIXING_ATTENUATION
-	dec edi
-	mov word ptr [ebx-2], ax
-	jnz cliploop
-	mov edx, ebp
-	pop ebp
-	mov eax, 28[esp]
-	mov dword ptr [eax], ecx
-	mov eax, 32[esp]
-	mov dword ptr [eax], edx
-	mov eax, 24[esp]
-	pop edi
-	shl eax, 1
-	pop esi
-	pop ebx
-	ret
-updatemin:
-	mov ecx, eax
-	jmp cliprecover
-updatemax:
-	mov ebp, eax
-	jmp cliprecover
-cliplow:
-	mov ecx, MIXING_CLIPMIN
-	mov ebp, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMIN
-	jmp cliprecover
-cliphigh:
-	mov ecx, MIXING_CLIPMIN
-	mov ebp, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMAX
-	jmp cliprecover
-	}
-}
-#else //MSC_VER
 //---GCCFIX: Asm replaced with C function
 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
-DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+DWORD Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
 {
-	int vumin = *lpMin, vumax = *lpMax;
 	signed short *p = (signed short *)lp16;
 	for (UINT i=0; i<lSampleCount; i++)
 	{
@@ -1770,323 +1675,78 @@
 			n = MIXING_CLIPMIN;
 		else if (n > MIXING_CLIPMAX)
 			n = MIXING_CLIPMAX;
-		if (n < vumin)
-			vumin = n;
-		else if (n > vumax)
-			vumax = n;
+		if (n < mins[i&1])
+			mins[i&1]= n;
+		else if (n > maxs[i&1])
+			maxs[i&1] = n;
 		p[i] = n >> (16-MIXING_ATTENUATION);	// 16-bit signed
 	}
-	*lpMin = vumin;
-	*lpMax = vumax;
 	return lSampleCount * 2;
 }
-#endif //MSC_VER, else
-
-#ifdef MSC_VER
-// Clip and convert to 24 bit
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//-----------------------------------------------------------------------------------------------------------------------------
-{
-	_asm {
-	push ebx
-	push esi
-	push edi
-	mov ebx, 16[esp]		// ebx = 8-bit buffer
-	mov esi, 20[esp]		// esi = pBuffer
-	mov edi, 24[esp]		// edi = lSampleCount
-	mov eax, 28[esp]
-	mov ecx, dword ptr [eax]	// ecx = clipmin
-	mov eax, 32[esp]
-	push ebp
-	mov edx, dword ptr [eax]	// edx = clipmax
-cliploop:
-	mov eax, dword ptr [esi]
-	mov ebp, eax
-	sar ebp, 31
-	and ebp, (1 << (8-MIXING_ATTENUATION)) - 1
-	add eax, ebp
-	cmp eax, MIXING_CLIPMIN
-	jl cliplow
-	cmp eax, MIXING_CLIPMAX
-	jg cliphigh
-	cmp eax, ecx
-	jl updatemin
-	cmp eax, edx
-	jg updatemax
-cliprecover:
-	add ebx, 3
-	sar eax, 8-MIXING_ATTENUATION
-	add esi, 4
-	mov word ptr [ebx-3], ax
-	shr eax, 16
-	dec edi
-	mov byte ptr [ebx-1], al
-	jnz cliploop
-	pop ebp
-	mov eax, 28[esp]
-	mov dword ptr [eax], ecx
-	mov eax, 32[esp]
-	mov dword ptr [eax], edx
-	mov edx, 24[esp]
-	mov eax, edx
-	pop edi
-	shl eax, 1
-	pop esi
-	add eax, edx
-	pop ebx
-	ret
-updatemin:
-	mov ecx, eax
-	jmp cliprecover
-updatemax:
-	mov edx, eax
-	jmp cliprecover
-cliplow:
-	mov ecx, MIXING_CLIPMIN
-	mov edx, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMIN
-	jmp cliprecover
-cliphigh:
-	mov ecx, MIXING_CLIPMIN
-	mov edx, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMAX
-	jmp cliprecover
-	}
-}
-#else //MSC_VER
 //---GCCFIX: Asm replaced with C function
-DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+// 24-bit might not work...
+DWORD Convert32To24(LPVOID lp24, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
 {
-	UINT i ;
-	int vumin = *lpMin, vumax = *lpMax;
-	int n,p ;
-	unsigned char* buf = (unsigned char*)lp16 ;
-	
-	for ( i=0; i<lSampleCount; i++)
-	{
-		n = pBuffer[i];
-		if (n < MIXING_CLIPMIN)
-			n = MIXING_CLIPMIN;
-		else if (n > MIXING_CLIPMAX)
-			n = MIXING_CLIPMAX;
-		if (n < vumin)
-			vumin = n;
-		else if (n > vumax)
-			vumax = n;
-		p = n >> (8-MIXING_ATTENUATION) ; // 24-bit signed
-//		buf[i*3]   = p & 0xFF0000 ; //XXX
-//		buf[i*3+1] = p & 0x00FF00 ;
-//		buf[i*3+2] = p & 0x0000FF ;
-		buf[i*3]   = (p & 0xFF0000) >> 16 ;
-		buf[i*3+1] = (p & 0x00FF00) >> 8 ;
-		buf[i*3+2] = p & 0x0000FF ;
-	}
-	*lpMin = vumin;
-	*lpMax = vumax;
-	return lSampleCount * 3;
-}
-#endif
-
-#ifdef MSC_VER
-// Clip and convert to 32 bit
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//-----------------------------------------------------------------------------------------------------------------------------
-{
-	_asm {
-	push ebx
-	push esi
-	push edi
-	mov ebx, 16[esp]			// ebx = 32-bit buffer
-	mov esi, 20[esp]			// esi = pBuffer
-	mov edi, 24[esp]			// edi = lSampleCount
-	mov eax, 28[esp]
-	mov ecx, dword ptr [eax]	// ecx = clipmin
-	mov eax, 32[esp]
-	mov edx, dword ptr [eax]	// edx = clipmax
-cliploop:
-	mov eax, dword ptr [esi]
-	add ebx, 4
-	add esi, 4
-	cmp eax, MIXING_CLIPMIN
-	jl cliplow
-	cmp eax, MIXING_CLIPMAX
-	jg cliphigh
-	cmp eax, ecx
-	jl updatemin
-	cmp eax, edx
-	jg updatemax
-cliprecover:
-	shl eax, MIXING_ATTENUATION
-	dec edi
-	mov dword ptr [ebx-4], eax
-	jnz cliploop
-	mov eax, 28[esp]
-	mov dword ptr [eax], ecx
-	mov eax, 32[esp]
-	mov dword ptr [eax], edx
-	mov edx, 24[esp]
-	pop edi
-	mov eax, edx
-	pop esi
-	shl eax, 2
-	pop ebx
-	ret
-updatemin:
-	mov ecx, eax
-	jmp cliprecover
-updatemax:
-	mov edx, eax
-	jmp cliprecover
-cliplow:
-	mov ecx, MIXING_CLIPMIN
-	mov edx, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMIN
-	jmp cliprecover
-cliphigh:
-	mov ecx, MIXING_CLIPMIN
-	mov edx, MIXING_CLIPMAX
-	mov eax, MIXING_CLIPMAX
-	jmp cliprecover
-	}
-}
-#else
-//---GCCFIX: Asm replaced with C function
-DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-{
-	UINT i ;
-	int vumin = *lpMin, vumax = *lpMax;
-	signed long *p = (signed long *)lp16;
-	
-	for ( i=0; i<lSampleCount; i++)
+	/* the inventor of 24bit anything should be shot */
+	unsigned char *p = (unsigned char *)lp24;
+	for (UINT i=0; i<lSampleCount; i++)
 	{
 		int n = pBuffer[i];
 		if (n < MIXING_CLIPMIN)
 			n = MIXING_CLIPMIN;
 		else if (n > MIXING_CLIPMAX)
 			n = MIXING_CLIPMAX;
-		if (n < vumin)
-			vumin = n;
-		else if (n > vumax)
-			vumax = n;
-		p[i] = n << MIXING_ATTENUATION;	// 32-bit signed
+		if (n < mins[i&1])
+			mins[i&1]= n;
+		else if (n > maxs[i&1])
+			maxs[i&1] = n;
+		n = n >> (8-MIXING_ATTENUATION);	// 24-bit signed
+		/* err, assume same endian */
+		memcpy(p, &n, 3);
+		p += 3;
 	}
-	*lpMin = vumin;
-	*lpMax = vumax;
-	return lSampleCount * 4;
+	return lSampleCount * 2;
 }
-#endif
-
-
-#ifdef MSC_VER
-void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
-//------------------------------------------------------------
+//---GCCFIX: Asm replaced with C function
+// 32-bit might not work...
+DWORD Convert32To32(LPVOID lp32, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
 {
-	_asm {
-	mov ecx, nSamples
-	mov esi, pBuffer
-	xor eax, eax
-	mov edx, ecx
-	shr ecx, 2
-	and edx, 3
-	jz unroll4x
-loop1x:
-	add esi, 4
-	dec edx
-	mov dword ptr [esi-4], eax
-	jnz loop1x
-unroll4x:
-	or ecx, ecx
-	jnz loop4x
-	jmp done
-loop4x:
-	add esi, 16
-	dec ecx
-	mov dword ptr [esi-16], eax
-	mov dword ptr [esi-12], eax
-	mov dword ptr [esi-8], eax
-	mov dword ptr [esi-4], eax
-	jnz loop4x
-done:;
+	signed int *p = (signed int *)lp32;
+	for (UINT i=0; i<lSampleCount; i++)
+	{
+		int n = pBuffer[i];
+		if (n < MIXING_CLIPMIN)
+			n = MIXING_CLIPMIN;
+		else if (n > MIXING_CLIPMAX)
+			n = MIXING_CLIPMAX;
+		if (n < mins[i&1])
+			mins[i&1]= n;
+		else if (n > maxs[i&1])
+			maxs[i&1] = n;
+		p[i] = (n >> MIXING_ATTENUATION);	// 32-bit signed
 	}
+	return lSampleCount * 2;
 }
-#else
 //---GCCFIX: Asm replaced with C function
 // Will fill in later.
-void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
+void InitMixBuffer(int *pBuffer, UINT nSamples)
 {
 	memset(pBuffer, 0, nSamples * sizeof(int));
 }
-#endif
 
-
-#ifdef MSC_VER
-__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
-//------------------------------------------------------------------------------------------------------
+//---GCCFIX: Asm replaced with C function
+void InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
 {
-	_asm {
-	push ebx
-	push ebp
-	push esi
-	push edi
-	mov ecx, 28[esp] // ecx = samplecount
-	mov esi, 20[esp] // esi = front buffer
-	mov edi, 24[esp] // edi = rear buffer
-	lea esi, [esi+ecx*4]	// esi = &front[N]
-	lea edi, [edi+ecx*4]	// edi = &rear[N]
-	lea ebx, [esi+ecx*4]	// ebx = &front[N*2]
-interleaveloop:
-	mov eax, dword ptr [esi-8]
-	mov edx, dword ptr [esi-4]
-	sub ebx, 16
-	mov ebp, dword ptr [edi-8]
-	mov dword ptr [ebx], eax
-	mov dword ptr [ebx+4], edx
-	mov eax, dword ptr [edi-4]
-	sub esi, 8
-	sub edi, 8
-	dec ecx
-	mov dword ptr [ebx+8], ebp
-	mov dword ptr [ebx+12], eax
-	jnz interleaveloop
-	pop edi
-	pop esi
-	pop ebp
-	pop ebx
-	ret
+	DWORD i=0;
+
+	pRearBuf[i] = pFrontBuf[1];
+	for (i = 1; i < nSamples; i++) {
+		pRearBuf[i] = pFrontBuf[(i*2)+1];
+		pFrontBuf[i] = pFrontBuf[i*2];
 	}
 }
-#else
 //---GCCFIX: Asm replaced with C function
-// Multichannel not supported.
-void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
-{
-}
-#endif
-
-
-#ifdef MSC_VER
-VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
-//-------------------------------------------------------------
-{
-	_asm {
-	mov ecx, nSamples
-	mov esi, pMixBuf
-	mov edi, esi
-stloop:
-	mov eax, dword ptr [esi]
-	mov edx, dword ptr [esi+4]
-	add edi, 4
-	add esi, 8
-	add eax, edx
-	sar eax, 1
-	dec ecx
-	mov dword ptr [edi-4], eax
-	jnz stloop
-	}
-}
-#else
-//---GCCFIX: Asm replaced with C function
-VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
+VOID MonoFromStereo(int *pMixBuf, UINT nSamples)
 {
 	UINT j;
 	for(UINT i = 0; i < nSamples; i++)
@@ -2095,89 +1755,11 @@
 		pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1;
 	}
 }
-#endif
 
-#define OFSDECAYSHIFT	8
-#define OFSDECAYMASK	0xFF
-
-
-#ifdef MSC_VER
-void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
-//---------------------------------------------------------------------------------------
-{
-	_asm {
-	mov edi, pBuffer
-	mov ecx, nSamples
-	mov eax, lpROfs
-	mov edx, lpLOfs
-	mov eax, [eax]
-	mov edx, [edx]
-	or ecx, ecx
-	jz fill_loop
-	mov ebx, eax
-	or ebx, edx
-	jz fill_loop
-ofsloop:
-	mov ebx, eax
-	mov esi, edx
-	neg ebx
-	neg esi
-	sar ebx, 31
-	sar esi, 31
-	and ebx, OFSDECAYMASK
-	and esi, OFSDECAYMASK
-	add ebx, eax
-	add esi, edx
-	sar ebx, OFSDECAYSHIFT
-	sar esi, OFSDECAYSHIFT
-	sub eax, ebx
-	sub edx, esi
-	mov ebx, eax
-	or ebx, edx
-	jz fill_loop
-	add edi, 8
-	dec ecx
-	mov [edi-8], eax
-	mov [edi-4], edx
-	jnz ofsloop
-fill_loop:
-	mov ebx, ecx
-	and ebx, 3
-	jz fill4x
-fill1x:
-	mov [edi], eax
-	mov [edi+4], edx
-	add edi, 8
-	dec ebx
-	jnz fill1x
-fill4x:
-	shr ecx, 2
-	or ecx, ecx
-	jz done
-fill4xloop:
-	mov [edi], eax
-	mov [edi+4], edx
-	mov [edi+8], eax
-	mov [edi+12], edx
-	add edi, 8*4
-	dec ecx
-	mov [edi-16], eax
-	mov [edi-12], edx
-	mov [edi-8], eax
-	mov [edi-4], edx
-	jnz fill4xloop
-done:
-	mov esi, lpROfs
-	mov edi, lpLOfs
-	mov [esi], eax
-	mov [edi], edx
-	}
-}
-#else
 //---GCCFIX: Asm replaced with C function
 #define OFSDECAYSHIFT    8
 #define OFSDECAYMASK     0xFF
-void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
+void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
 //---------------------------------------------------------------------------------------------------------
 {
 	int rofs = *lpROfs;
@@ -2185,7 +1767,7 @@
 
 	if ((!rofs) && (!lofs))
 	{
-		X86_InitMixBuffer(pBuffer, nSamples*2);
+		InitMixBuffer(pBuffer, nSamples*2);
 		return;
 	}
 	for (UINT i=0; i<nSamples; i++)
@@ -2200,53 +1782,9 @@
 	*lpROfs = rofs;
 	*lpLOfs = lofs;
 }
-#endif
-
-#ifdef MSC_VER
-void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
-//----------------------------------------------------------------------------------
-{
-	_asm {
-	mov esi, pChannel
-	mov edi, pBuffer
-	mov ecx, nSamples
-	mov eax, dword ptr [esi+MODCHANNEL.nROfs]
-	mov edx, dword ptr [esi+MODCHANNEL.nLOfs]
-	or ecx, ecx
-	jz brkloop
-ofsloop:
-	mov ebx, eax
-	mov esi, edx
-	neg ebx
-	neg esi
-	sar ebx, 31
-	sar esi, 31
-	and ebx, OFSDECAYMASK
-	and esi, OFSDECAYMASK
-	add ebx, eax
-	add esi, edx
-	sar ebx, OFSDECAYSHIFT
-	sar esi, OFSDECAYSHIFT
-	sub eax, ebx
-	sub edx, esi
-	mov ebx, eax
-	add dword ptr [edi], eax
-	add dword ptr [edi+4], edx
-	or ebx, edx
-	jz brkloop
-	add edi, 8
-	dec ecx
-	jnz ofsloop
-brkloop:
-	mov esi, pChannel
-	mov dword ptr [esi+MODCHANNEL.nROfs], eax
-	mov dword ptr [esi+MODCHANNEL.nLOfs], edx
-	}
-}
-#else
 //---GCCFIX: Asm replaced with C function
 // Will fill in later.
-void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
+void EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
 {
 	int rofs = pChannel->nROfs;
 	int lofs = pChannel->nLOfs;
@@ -2264,7 +1802,9 @@
 	pChannel->nROfs = rofs;
 	pChannel->nLOfs = lofs;
 }
-#endif
+
+
+
 
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -2276,72 +1816,11 @@
 #define MIXING_LIMITMAX		(0x08100000)
 #define MIXING_LIMITMIN		(-MIXING_LIMITMAX)
 
-#ifdef MSC_VER
-__declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
-//-------------------------------------------------------------------------------
-{
-	__asm {
-	push ebx
-	push ebp
-	push esi
-	push edi
-	mov esi, 20[esp]	// esi = pBuffer+i
-	mov ecx, 24[esp]	// ecx = i
-	mov edi, 28[esp]	// edi = AGC (0..256)
-agcloop:
-	mov eax, dword ptr [esi]
-	imul edi
-	shrd eax, edx, AGC_PRECISION
-	add esi, 4
-	cmp eax, MIXING_LIMITMIN
-	jl agcupdate
-	cmp eax, MIXING_LIMITMAX
-	jg agcupdate
-agcrecover:
-	dec ecx
-	mov dword ptr [esi-4], eax
-	jnz agcloop
-	mov eax, edi
-	pop edi
-	pop esi
-	pop ebp
-	pop ebx
-	ret
-agcupdate:
-	dec edi
-	jmp agcrecover
-	}
-}
-
-#pragma warning (default:4100)
-#else
-// Version for GCC
-UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
-{
-	int x;
-
-	while(nSamples)
-	{
-		x = ((long long int)(*pBuffer) * nAGC) >> AGC_PRECISION;
-
-		if((x < MIXING_LIMITMIN) || (x > MIXING_LIMITMAX))
-		nAGC--;
-
-		*pBuffer = x;
-
-		pBuffer++;
-		nSamples--;
-	}
-
-	return nAGC;
-}
-#endif
-
 void CSoundFile::ProcessAGC(int count)
 //------------------------------------
 {
 	static DWORD gAGCRecoverCount = 0;
-	UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC);
+	UINT agc = AGC(MixSoundBuffer, count, gnAGC);
 	// Some kind custom law, so that the AGC stays quite stable, but slowly
 	// goes back up if the sound level stays below a level inversely proportional
 	// to the AGC level. (J'me comprends)
@@ -2371,3 +1850,4 @@
 }
 
 #endif // NO_AGC
+