diff src/modplug/sndmix.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 b24eda79942b
line wrap: on
line diff
--- a/src/modplug/sndmix.cxx	Wed Jan 23 19:37:05 2008 +0100
+++ b/src/modplug/sndmix.cxx	Thu Jan 24 12:05:59 2008 +0000
@@ -7,18 +7,14 @@
 #include "stdafx.h"
 #include "sndfile.h"
 
-#ifdef MODPLUG_TRACKER
-#define ENABLE_STEREOVU
-#endif
 
 // Volume ramp length, in 1/10 ms
 #define VOLUMERAMPLEN	146	// 1.46ms = 64 samples at 44.1kHz
 
 // VU-Meter
-#define VUMETER_DECAY		4
+#define VUMETER_DECAY		16
 
 // SNDMIX: These are global flags for playback control
-UINT CSoundFile::m_nStereoSeparation = 128;
 LONG CSoundFile::m_nStreamVolume = 0x8000;
 UINT CSoundFile::m_nMaxMixChannels = 32;
 // Mixing Configuration (SetWaveConfig)
@@ -30,7 +26,8 @@
 // Mixing data initialized in
 UINT CSoundFile::gnAGC = AGC_UNITY;
 UINT CSoundFile::gnVolumeRampSamples = 64;
-UINT CSoundFile::gnVUMeter = 0;
+UINT CSoundFile::gnVULeft = 0;
+UINT CSoundFile::gnVURight = 0;
 UINT CSoundFile::gnCPUUsage = 0;
 LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL;
 PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL;
@@ -42,15 +39,15 @@
 
 typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG);
 
-extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC);
-extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits);
-extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
-extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
-extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples);
+extern DWORD MPPASMCALL Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+extern DWORD MPPASMCALL Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+extern DWORD MPPASMCALL Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+extern DWORD MPPASMCALL Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+extern UINT MPPASMCALL AGC(int *pBuffer, UINT nSamples, UINT nAGC);
+extern VOID MPPASMCALL Dither(int *pBuffer, UINT nSamples, UINT nBits);
+extern VOID MPPASMCALL InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
+extern VOID MPPASMCALL StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
+extern VOID MPPASMCALL MonoFromStereo(int *pMixBuf, UINT nSamples);
 
 extern short int ModSinusTable[64];
 extern short int ModRampDownTable[64];
@@ -85,104 +82,6 @@
 };
 
 
-// Return (a*b)/c - no divide error
-int _muldiv(long a, long b, long c)
-{
-#ifdef MSC_VER
-	int sign, result;
-	_asm {
-	mov eax, a
-	mov ebx, b
-	or eax, eax
-	mov edx, eax
-	jge aneg
-	neg eax
-aneg:
-	xor edx, ebx
-	or ebx, ebx
-	mov ecx, c
-	jge bneg
-	neg ebx
-bneg:
-	xor edx, ecx
-	or ecx, ecx
-	mov sign, edx
-	jge cneg
-	neg ecx
-cneg:
-	mul ebx
-	cmp edx, ecx
-	jae diverr
-	div ecx
-	jmp ok
-diverr:
-	mov eax, 0x7fffffff
-ok:
-	mov edx, sign
-	or edx, edx
-	jge rneg
-	neg eax
-rneg:
-	mov result, eax
-	}
-	return result;
-#else
-	return ((unsigned long long) a * (unsigned long long) b ) / c;
-#endif
-}
-
-
-// Return (a*b+c/2)/c - no divide error
-int _muldivr(long a, long b, long c)
-{
-#ifdef MSC_VER
-	int sign, result;
-	_asm {
-	mov eax, a
-	mov ebx, b
-	or eax, eax
-	mov edx, eax
-	jge aneg
-	neg eax
-aneg:
-	xor edx, ebx
-	or ebx, ebx
-	mov ecx, c
-	jge bneg
-	neg ebx
-bneg:
-	xor edx, ecx
-	or ecx, ecx
-	mov sign, edx
-	jge cneg
-	neg ecx
-cneg:
-	mul ebx
-	mov ebx, ecx
-	shr ebx, 1
-	add eax, ebx
-	adc edx, 0
-	cmp edx, ecx
-	jae diverr
-	div ecx
-	jmp ok
-diverr:
-	mov eax, 0x7fffffff
-ok:
-	mov edx, sign
-	or edx, edx
-	jge rneg
-	neg eax
-rneg:
-	mov result, eax
-	}
-	return result;
-#else
-	return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
-#endif
-}
-
-
 BOOL CSoundFile::InitPlayer(BOOL bReset)
 //--------------------------------------
 {
@@ -195,11 +94,13 @@
 	gnRvbROfsVol = gnRvbLOfsVol = 0;
 	if (bReset)
 	{
-		gnVUMeter = 0;
+		gnVULeft = 0;
+		gnVURight = 0;
 		gnCPUUsage = 0;
 	}
 	gbInitPlugins = (bReset) ? 3 : 1;
 	InitializeDSP(bReset);
+	InitializeEQ(bReset);
 	return TRUE;
 }
 
@@ -245,22 +146,28 @@
 //-------------------------------------------------------
 {
 	LPBYTE lpBuffer = (LPBYTE)lpDestBuffer;
-	LPCONVERTPROC pCvt = X86_Convert32To8;
+	LPCONVERTPROC pCvt = Convert32To8;
+	LONG vu_min[2];
+	LONG vu_max[2];
 	UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0;
-	LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF;
+#if 0
 	UINT nMaxPlugins;
+#endif
 
+	vu_min[0] = vu_min[1] = 0x7FFFFFFF;
+	vu_max[0] = vu_max[1] = -0x7FFFFFFF;
+
+#if 0
 	{
 		nMaxPlugins = MAX_MIXPLUGINS;
 		while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--;
 	}
+#endif
 	m_nMixStat = 0;
 	lSampleSize = gnChannels;
-	if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; }
-#ifndef MODPLUG_FASTSOUNDLIB
-	else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; }
-	else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; }
-#endif
+	if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; }
+	else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; }
+	else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; }
 	lMax = cbBuffer / lSampleSize;
 	if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0;
 	lRead = lMax;
@@ -268,26 +175,18 @@
 	while (lRead > 0)
 	{
 		// Update Channel Data
+		UINT lTotalSampleCount;
 		if (!m_nBufferCount)
 		{
-#ifndef MODPLUG_FASTSOUNDLIB
-			if (m_dwSongFlags & SONG_FADINGSONG)
-			{
-				m_dwSongFlags |= SONG_ENDREACHED;
+			if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))
 				m_nBufferCount = lRead;
-			} else
-#endif
-			if (!ReadNote())
-			{
-#ifndef MODPLUG_FASTSOUNDLIB
-				if (!FadeSong(FADESONGDELAY))
-#endif
-				{
-					m_dwSongFlags |= SONG_ENDREACHED;
-					if (lRead == lMax) goto MixDone;
+			if (!ReadNote()) {
+				m_dwSongFlags |= SONG_ENDREACHED;
+				if (lRead == lMax) goto MixDone;
+				if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))
 					m_nBufferCount = lRead;
-				}
 			}
+			if (!m_nBufferCount) goto MixDone;
 		}
 		lCount = m_nBufferCount;
 		if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE;
@@ -297,30 +196,46 @@
 #ifndef MODPLUG_NO_REVERB
 		gnReverbSend = 0;
 #endif
+
 		// Resetting sound buffer
-		X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
+		StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
 		if (gnChannels >= 2)
 		{
 			lSampleCount *= 2;
 			m_nMixStat += CreateStereoMix(lCount);
+#if 0
+			if (nMaxPlugins) ProcessPlugins(lCount);
+#endif
 			ProcessStereoDSP(lCount);
 		} else
 		{
 			m_nMixStat += CreateStereoMix(lCount);
-			ProcessStereoDSP(lCount);
-			X86_MonoFromStereo(MixSoundBuffer, lCount);
+#if 0
+			if (nMaxPlugins) ProcessPlugins(lCount);
+#endif
+			MonoFromStereo(MixSoundBuffer, lCount);
+			ProcessMonoDSP(lCount);
 		}
+
+		if (gdwSoundSetup & SNDMIX_EQ)
+		{
+			if (gnChannels >= 2)
+				EQStereo(MixSoundBuffer, lCount);
+			else
+				EQMono(MixSoundBuffer, lCount);
+		}
+
+
 		nStat++;
 #ifndef NO_AGC
 		// Automatic Gain Control
 		if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount);
 #endif
-		UINT lTotalSampleCount = lSampleCount;
-#ifndef MODPLUG_FASTSOUNDLIB
+		lTotalSampleCount = lSampleCount;
 		// Multichannel
 		if (gnChannels > 2)
 		{
-			X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
+			InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
 			lTotalSampleCount *= 2;
 		}
 		// Hook Function
@@ -328,9 +243,8 @@
 		{
 			gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels);
 		}
-#endif
 		// Perform clipping + VU-Meter
-		lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax);
+		lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max);
 		// Buffer ready
 		lRead -= lCount;
 		m_nBufferCount -= lCount;
@@ -338,10 +252,16 @@
 MixDone:
 	if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize);
 	// VU-Meter
-	nVUMeterMin >>= (24-MIXING_ATTENUATION);
-	nVUMeterMax >>= (24-MIXING_ATTENUATION);
-	if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin;
-	if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF;
+	vu_min[0] >>= 18;
+	vu_min[1] >>= 18;
+	vu_max[0] >>= 18;
+	vu_max[1] >>= 18;
+	if (vu_max[0] < vu_min[0]) vu_max[0] = vu_min[0];
+	if (vu_max[1] < vu_min[1]) vu_max[1] = vu_min[1];
+	if ((gnVULeft = (UINT)(vu_max[0] - vu_min[0])) > 0xFF)
+		gnVULeft = 0xFF;
+	if ((gnVURight = (UINT)(vu_max[1] - vu_min[1])) > 0xFF)
+		gnVURight = 0xFF;
 	if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; }
 	return lMax - lRead;
 }
@@ -355,77 +275,75 @@
 //---------------------------
 {
 	if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay)
-	{
+        {
 		m_nPatternDelay = 0;
 		m_nFrameDelay = 0;
 		m_nTickCount = 0;
 		m_nRow = m_nNextRow;
+		
 		// Reset Pattern Loop Effect
-		if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern;
-		// Check if pattern is valid
-		if (!(m_dwSongFlags & SONG_PATTERNLOOP))
-		{
-			m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
-			if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
-			while (m_nPattern >= MAX_PATTERNS)
+		if (m_nCurrentPattern != m_nNextPattern) {
+			if (m_nLockedPattern < MAX_ORDERS) {
+				m_nCurrentPattern = m_nLockedPattern;
+				if (!(m_dwSongFlags & SONG_ORDERLOCKED))
+					m_nLockedPattern = MAX_ORDERS;
+			} else {
+				m_nCurrentPattern = m_nNextPattern;
+			}
+
+			// Check if pattern is valid
+			if (!(m_dwSongFlags & SONG_PATTERNLOOP))
 			{
-				// End of song ?
-				if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
-				{
-					//if (!m_nRepeatCount)
-						return FALSE;     //never repeat entire song
-					if (!m_nRestartPos)
-					{
-						m_nMusicSpeed = m_nDefaultSpeed;
-						m_nMusicTempo = m_nDefaultTempo;
-						m_nGlobalVolume = m_nDefaultGlobalVolume;
-						for (UINT i=0; i<MAX_CHANNELS; i++)
-						{
-							Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF;
-							Chn[i].nFadeOutVol = 0;
-							if (i < m_nChannels)
-							{
-								Chn[i].nGlobalVol = ChnSettings[i].nVolume;
-								Chn[i].nVolume = ChnSettings[i].nVolume;
-								Chn[i].nPan = ChnSettings[i].nPan;
-								Chn[i].nPanSwing = Chn[i].nVolSwing = 0;
-								Chn[i].nOldVolParam = 0;
-								Chn[i].nOldOffset = 0;
-								Chn[i].nOldHiOffset = 0;
-								Chn[i].nPortamentoDest = 0;
-								if (!Chn[i].nLength)
-								{
-									Chn[i].dwFlags = ChnSettings[i].dwFlags;
-									Chn[i].nLoopStart = 0;
-									Chn[i].nLoopEnd = 0;
-									Chn[i].pHeader = NULL;
-									Chn[i].pSample = NULL;
-									Chn[i].pInstrument = NULL;
-								}
-							}
-						}
-					}
-//					if (m_nRepeatCount > 0) m_nRepeatCount--;
-					m_nCurrentPattern = m_nRestartPos;
-					m_nRow = 0;
-					if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE;
-				} else
-				{
-					m_nCurrentPattern++;
-				}
 				m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
 				if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
+				while (m_nPattern >= MAX_PATTERNS)
+				{
+					// End of song ?
+					if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
+					{
+						if (m_nRepeatCount > 0) m_nRepeatCount--;
+						if (!m_nRepeatCount) return FALSE;
+						m_nCurrentPattern = m_nRestartPos;
+						if ((Order[m_nCurrentPattern] >= MAX_PATTERNS)
+						    || (!Patterns[Order[m_nCurrentPattern]]))
+							return FALSE;
+					} else {
+						m_nCurrentPattern++;
+					}
+					m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
+					if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
+				}
+				m_nNextPattern = m_nCurrentPattern;
+			} else if (m_nCurrentPattern < 255) {
+				if (m_nRepeatCount > 0) m_nRepeatCount--;
+				if (!m_nRepeatCount) return FALSE;
 			}
-			m_nNextPattern = m_nCurrentPattern;
+		}
+#ifdef MODPLUG_TRACKER
+		if (m_dwSongFlags & SONG_STEP)
+		{
+			m_dwSongFlags &= ~SONG_STEP;
+			m_dwSongFlags |= SONG_PAUSED;
+		}
+#endif // MODPLUG_TRACKER
+		if (!PatternSize[m_nPattern] || !Patterns[m_nPattern]) {
+			/* okay, this is wrong. allocate the pattern _NOW_ */
+			Patterns[m_nPattern] = AllocatePattern(64,64);
+			PatternSize[m_nPattern] = 64;
+			PatternAllocSize[m_nPattern] = 64;
 		}
 		// Weird stuff?
-		if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE;
+		if (m_nPattern >= MAX_PATTERNS) return FALSE;
 		// Should never happen
+		// ... sure it should: suppose there's a C70 effect before a 64-row pattern.
+		// It's in fact very easy to make this happen ;)
+		//       - chisel
 		if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0;
-		m_nNextRow = m_nRow + 1;
+                m_nNextRow = m_nRow + 1;
 		if (m_nNextRow >= PatternSize[m_nPattern])
 		{
 			if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1;
+			else if (m_nRepeatCount > 0) return FALSE;
 			m_nNextRow = 0;
 		}
 		// Reset channel values
@@ -433,7 +351,18 @@
 		MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels;
 		for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++)
 		{
+			/* skip realtime copyin */
+			if (pChn->nRealtime) continue;
+
+			// this is where we're going to spit out our midi
+			// commands... ALL WE DO is dump raw midi data to
+			// our super-secret "midi buffer"
+			// -mrsb
+			if (_midi_out_note)
+				_midi_out_note(nChn, m);
+
 			pChn->nRowNote = m->note;
+			if (m->instr) pChn->nLastInstr = m->instr;
 			pChn->nRowInstr = m->instr;
 			pChn->nRowVolCmd = m->volcmd;
 			pChn->nRowVolume = m->vol;
@@ -445,6 +374,14 @@
 			pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO);
 			pChn->nCommand = 0;
 		}
+				
+	} else if (_midi_out_note) {
+		MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels;
+		for (UINT nChn=0; nChn<m_nChannels; nChn++, m++)
+		{
+			/* m==NULL allows schism to receive notification of SDx and Scx commands */
+			_midi_out_note(nChn, 0);
+		}
 	}
 	// Should we process tick0 effects?
 	if (!m_nMusicSpeed) m_nMusicSpeed = 1;
@@ -469,33 +406,93 @@
 BOOL CSoundFile::ReadNote()
 //-------------------------
 {
-	if (!ProcessRow()) return FALSE;
+	// Checking end of row ?
+	if (m_dwSongFlags & SONG_PAUSED)
+	{
+		/*m_nTickCount = 0;*/
+		if (!m_nMusicSpeed) m_nMusicSpeed = 6;
+		if (!m_nMusicTempo) m_nMusicTempo = 125;
+		m_nPatternDelay = 0;
+		m_nFrameDelay = 0;
+
+		m_dwSongFlags |= SONG_FIRSTTICK;
+		if (m_nTickCount) {
+			m_dwSongFlags &= ~SONG_FIRSTTICK;
+		}
+
+		ProcessEffects();
+		m_nTickCount++;
+		if (m_nTickCount >= m_nMusicSpeed) {
+			m_nTickCount = 0;
+		}
+		if (!ProcessEffects()) return FALSE;
+	} else
+	{
+		if (!ProcessRow()) return FALSE;
+	}
+
+	{ /* handle realtime closures */
+		MODCHANNEL *pChn = Chn;
+		for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++) {
+			/* reset end of "row" */
+			if (pChn->nRealtime && pChn->nRowNote && (pChn->nTickStart % m_nMusicSpeed) == (m_nTickCount % m_nMusicSpeed)) {
+				pChn->nRealtime = 0;
+				pChn->nRowNote = 0;
+				pChn->nRowInstr = 0;
+				//pChn->nMaster
+				pChn->nRowVolCmd = 0;
+				pChn->nRowVolume = 0;
+				pChn->nRowCommand = 0;
+				pChn->nRowParam = 0;
+				pChn->nTickStart = 0;
+			}
+		}
+	};
+
 	////////////////////////////////////////////////////////////////////////////////////
 	m_nTotalCount++;
 	if (!m_nMusicTempo) return FALSE;
 	m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8);
+#ifdef MODPLUG_TRACKER
+	if (m_dwSongFlags & SONG_PAUSED)
+	{
+		m_nBufferCount = gdwMixingFreq / 64; // 1/64 seconds
+	}
+#endif
+
 	// Master Volume + Pre-Amplification / Attenuation setup
 	DWORD nMasterVol;
 	{
-		int nchn32 = (m_nChannels < 32) ? m_nChannels : 31;
-		if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6;
+		int nchn32 = 0;
+		MODCHANNEL *pChn = Chn;	
+		for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++) {
+			nchn32++;
+		}
+		if (nchn32 < 1) nchn32 = 1;
+		if (nchn32 > 31) nchn32 = 31;
+
 		int realmastervol = m_nMasterVolume;
 		if (realmastervol > 0x80)
 		{
 			realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16;
 		}
-		UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
-		DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6;
-		if (mastervol > 0x200) mastervol = 0x200;
+
+		DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 6;
+//		if (mastervol > 0x200) mastervol = 0x200;
 		if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples))
 		{
 			mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples);
 		}
+
+		UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
+		if (attenuation < 1) attenuation = 1;
+
 		nMasterVol = (mastervol << 7) / attenuation;
 		if (nMasterVol > 0x180) nMasterVol = 0x180;
 	}
 	////////////////////////////////////////////////////////////////////////////////////
 	// Update channels data
+	if (CSoundFile::gdwSoundSetup & SNDMIX_NOMIXING) return TRUE;
 	m_nMixChannels = 0;
 	MODCHANNEL *pChn = Chn;
 	for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++)
@@ -506,12 +503,9 @@
 			pChn->nROfs = pChn->nLOfs = 0;
 		}
 		// Check for unused channel
-		if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength)))
+		if ((nChn >= m_nChannels) && (!pChn->nLength))
 		{
-			pChn->nVUMeter = 0;
-#ifdef ENABLE_STEREOVU
 			pChn->nLeftVU = pChn->nRightVU = 0;
-#endif
 			continue;
 		}
 		// Reset channel data
@@ -575,33 +569,33 @@
 			if (vol > 0x100) vol = 0x100;
 			vol <<= 6;
 			// Process Envelopes
-			if (pChn->pHeader)
+			if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
 			{
 				INSTRUMENTHEADER *penv = pChn->pHeader;
 				// Volume Envelope
-				if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv))
+				if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes))
 				{
 					int envpos = pChn->nVolEnvPosition;
-					UINT pt = penv->nVolEnv - 1;
-					for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++)
+					UINT pt = penv->VolEnv.nNodes - 1;
+					for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++)
 					{
-						if (envpos <= penv->VolPoints[i])
+						if (envpos <= penv->VolEnv.Ticks[i])
 						{
 							pt = i;
 							break;
 						}
 					}
-					int x2 = penv->VolPoints[pt];
+					int x2 = penv->VolEnv.Ticks[pt];
 					int x1, envvol;
 					if (envpos >= x2)
 					{
-						envvol = penv->VolEnv[pt] << 2;
+						envvol = penv->VolEnv.Values[pt] << 2;
 						x1 = x2;
 					} else
 					if (pt)
 					{
-						envvol = penv->VolEnv[pt-1] << 2;
-						x1 = penv->VolPoints[pt-1];
+						envvol = penv->VolEnv.Values[pt-1] << 2;
+						x1 = penv->VolEnv.Ticks[pt-1];
 					} else
 					{
 						envvol = 0;
@@ -610,26 +604,26 @@
 					if (envpos > x2) envpos = x2;
 					if ((x2 > x1) && (envpos > x1))
 					{
-						envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1);
+						envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[pt]<<2) - envvol)) / (x2 - x1);
 					}
 					if (envvol < 0) envvol = 0;
 					if (envvol > 256) envvol = 256;
 					vol = (vol * envvol) >> 8;
 				}
 				// Panning Envelope
-				if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv))
+				if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes))
 				{
 					int envpos = pChn->nPanEnvPosition;
-					UINT pt = penv->nPanEnv - 1;
-					for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++)
+					UINT pt = penv->PanEnv.nNodes - 1;
+					for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++)
 					{
-						if (envpos <= penv->PanPoints[i])
+						if (envpos <= penv->PanEnv.Ticks[i])
 						{
 							pt = i;
 							break;
 						}
 					}
-					int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt];
+					int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt];
 					int x1, envpan;
 					if (envpos >= x2)
 					{
@@ -638,8 +632,8 @@
 					} else
 					if (pt)
 					{
-						envpan = penv->PanEnv[pt-1];
-						x1 = penv->PanPoints[pt-1];
+						envpan = penv->PanEnv.Values[pt-1];
+						x1 = penv->PanEnv.Ticks[pt-1];
 					} else
 					{
 						envpan = 128;
@@ -714,8 +708,13 @@
 			{
 				switch(m_nTickCount % 3)
 				{
+#if 0
 				case 1:	period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
 				case 2:	period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
+#else
+				case 1:	period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
+				case 2:	period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
+#endif
 				}
 			}
 
@@ -726,30 +725,32 @@
 			}
 
 			// Pitch/Filter Envelope
-			if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv))
+			int envpitch = 0;
+			if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader)
+			    && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes))
 			{
 				INSTRUMENTHEADER *penv = pChn->pHeader;
 				int envpos = pChn->nPitchEnvPosition;
-				UINT pt = penv->nPitchEnv - 1;
-				for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++)
+				UINT pt = penv->PitchEnv.nNodes - 1;
+				for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++)
 				{
-					if (envpos <= penv->PitchPoints[i])
+					if (envpos <= penv->PitchEnv.Ticks[i])
 					{
 						pt = i;
 						break;
 					}
 				}
-				int x2 = penv->PitchPoints[pt];
-				int x1, envpitch;
+				int x2 = penv->PitchEnv.Ticks[pt];
+				int x1;
 				if (envpos >= x2)
 				{
-					envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8;
+					envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8;
 					x1 = x2;
 				} else
 				if (pt)
 				{
-					envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8;
-					x1 = penv->PitchPoints[pt-1];
+					envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8;
+					x1 = penv->PitchEnv.Ticks[pt-1];
 				} else
 				{
 					envpitch = 0;
@@ -758,19 +759,13 @@
 				if (envpos > x2) envpos = x2;
 				if ((x2 > x1) && (envpos > x1))
 				{
-					int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8;
+					int envpitchdest = (((int)penv->PitchEnv.Values[pt]) - 32) * 8;
 					envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1);
 				}
 				if (envpitch < -256) envpitch = -256;
 				if (envpitch > 256) envpitch = 256;
-				// Filter Envelope: controls cutoff frequency
-				if (penv->dwFlags & ENV_FILTER)
-				{
-#ifndef NO_FILTER
-					SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
-#endif // NO_FILTER
-				} else
 				// Pitch Envelope
+				if (!(penv->dwFlags & ENV_FILTER))
 				{
 					int l = envpitch;
 					if (l < 0)
@@ -860,6 +855,16 @@
 			if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth))
 			{
 				MODINSTRUMENT *pins = pChn->pInstrument;
+				/* this isn't correct, but its better... */
+
+				if (pins->nVibSweep == 0) {
+					pChn->nAutoVibDepth = pins->nVibDepth << 8;
+				} else {
+					pChn->nAutoVibDepth += pins->nVibSweep;
+					if ((pChn->nAutoVibDepth >> 8) > (int)pins->nVibDepth)
+						pChn->nAutoVibDepth = pins->nVibDepth << 8;
+				}
+#if 0
 				if (pins->nVibSweep == 0)
 				{
 					pChn->nAutoVibDepth = pins->nVibDepth << 8;
@@ -867,7 +872,7 @@
 				{
 					if (m_nType & MOD_TYPE_IT)
 					{
-						pChn->nAutoVibDepth += pins->nVibSweep << 3;
+						pChn->nAutoVibDepth += pins->nVibSweep;
 					} else
 					if (!(pChn->dwFlags & CHN_KEYOFF))
 					{
@@ -876,7 +881,8 @@
 					if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth)
 						pChn->nAutoVibDepth = pins->nVibDepth << 8;
 				}
-				pChn->nAutoVibPos += pins->nVibRate;
+#endif
+				pChn->nAutoVibPos += ((int)pins->nVibRate);
 				int val;
 				switch(pins->nVibType)
 				{
@@ -897,6 +903,10 @@
 					val = ft2VibratoTable[pChn->nAutoVibPos & 255];
 				}
 				int n =	((val * pChn->nAutoVibDepth) >> 8);
+				// is this right? -mrsb
+				if (!(m_dwSongFlags & SONG_ITOLDEFFECTS))
+					n >>= 1;
+
 				if (m_nType & MOD_TYPE_IT)
 				{
 					int df1, df2;
@@ -939,12 +949,25 @@
 				nPeriodFrac = 0;
 			}
 			UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac);
+
+			// Filter Envelope: controls cutoff frequency
+			if (pChn && pChn->pHeader && pChn->pHeader->dwFlags & ENV_FILTER)
+			{
+#ifndef NO_FILTER
+				SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
+#endif // NO_FILTER
+			}
+
+#if 0
 			if ((m_nType & MOD_TYPE_IT) && (freq < 256))
 			{
 				pChn->nFadeOutVol = 0;
 				pChn->dwFlags |= CHN_NOTEFADE;
 				pChn->nRealVolume = 0;
 			}
+#endif
+			pChn->sample_freq = freq;
+
 			UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq);
 			if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000;
 			if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7;
@@ -953,7 +976,7 @@
 		}
 
 		// Increment envelope position
-		if (pChn->pHeader)
+		if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
 		{
 			INSTRUMENTHEADER *penv = pChn->pHeader;
 			// Volume Envelope
@@ -964,13 +987,13 @@
 				// Volume Loop ?
 				if (penv->dwFlags & ENV_VOLLOOP)
 				{
-					UINT volloopend = penv->VolPoints[penv->nVolLoopEnd];
+					int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd];
 					if (m_nType != MOD_TYPE_XM) volloopend++;
 					if (pChn->nVolEnvPosition == volloopend)
 					{
-						pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart];
-						if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart])
-						 && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv)))
+						pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nLoopStart];
+						if ((penv->VolEnv.nLoopEnd == penv->VolEnv.nLoopStart) && (!penv->VolEnv.Values[penv->VolEnv.nLoopStart])
+						 && ((!(m_nType & MOD_TYPE_XM)) || (penv->VolEnv.nLoopEnd+1 == penv->VolEnv.nNodes)))
 						{
 							pChn->dwFlags |= CHN_NOTEFADE;
 							pChn->nFadeOutVol = 0;
@@ -980,15 +1003,15 @@
 				// Volume Sustain ?
 				if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
 				{
-					if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1)
-						pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin];
+					if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1)
+						pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart];
 				} else
 				// End of Envelope ?
-				if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1])
+				if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1])
 				{
 					if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE;
-					pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1];
-					if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT)))
+					pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1];
+					if ((!penv->VolEnv.Values[penv->VolEnv.nNodes-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT)))
 					{
 						pChn->dwFlags |= CHN_NOTEFADE;
 						pChn->nFadeOutVol = 0;
@@ -1003,21 +1026,21 @@
 				pChn->nPanEnvPosition++;
 				if (penv->dwFlags & ENV_PANLOOP)
 				{
-					UINT panloopend = penv->PanPoints[penv->nPanLoopEnd];
+					int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd];
 					if (m_nType != MOD_TYPE_XM) panloopend++;
 					if (pChn->nPanEnvPosition == panloopend)
-						pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart];
+						pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart];
 				}
 				// Panning Sustain ?
-				if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1)
+				if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1)
 				 && (!(pChn->dwFlags & CHN_KEYOFF)))
 				{
 					// Panning sustained
-					pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin];
+					pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart];
 				} else
 				{
-					if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1])
-						pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1];
+					if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1])
+						pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1];
 				}
 			}
 			// Pitch Envelope
@@ -1028,22 +1051,22 @@
 				// Pitch Loop ?
 				if (penv->dwFlags & ENV_PITCHLOOP)
 				{
-					if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd])
-						pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart];
+					if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd])
+						pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart];
 				}
 				// Pitch Sustain ?
 				if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
 				{
-					if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1)
-						pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin];
+					if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1)
+						pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart];
 				} else
 				{
-					if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1])
-						pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1];
+					if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1])
+						pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1];
 				}
 			}
 		}
-#ifdef MODPLUG_PLAYER
+#if 0
 		// Limit CPU -> > 80% -> don't ramp
 		if ((gnCPUUsage >= 80) && (!pChn->nRealVolume))
 		{
@@ -1054,14 +1077,10 @@
 		pChn->dwFlags &= ~CHN_VOLUMERAMP;
 		if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol))
 			pChn->dwFlags |= CHN_VOLUMERAMP;
-#ifdef MODPLUG_PLAYER
 		// Decrease VU-Meter
 		if (pChn->nVUMeter > VUMETER_DECAY)	pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0;
-#endif // MODPLUG_PLAYER
-#ifdef ENABLE_STEREOVU
 		if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0;
 		if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0;
-#endif
 		// Check for too big nInc
 		if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP;
 		pChn->nNewRightVol = pChn->nNewLeftVol = 0;
@@ -1069,14 +1088,11 @@
 		if (pChn->pCurrentSample)
 		{
 			// Update VU-Meter (nRealVolume is 14-bit)
-#ifdef MODPLUG_PLAYER
 			UINT vutmp = pChn->nRealVolume >> (14 - 8);
 			if (vutmp > 0xFF) vutmp = 0xFF;
 			if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp;
 			vutmp >>= 1;
 			if (pChn->nVUMeter < vutmp)	pChn->nVUMeter = vutmp;
-#endif // MODPLUG_PLAYER
-#ifdef ENABLE_STEREOVU
 			UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14;
 			if (vul > 127) vul = 127;
 			if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul;
@@ -1087,7 +1103,6 @@
 			if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur;
 			vur >>= 1;
 			if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur;
-#endif
 #ifdef MODPLUG_TRACKER
 			UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol;
 #else
@@ -1103,9 +1118,8 @@
 
 				if (pan < 0) pan = 0;
 				if (pan > 256) pan = 256;
-#ifndef MODPLUG_FASTSOUNDLIB
 				if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan;
-#endif
+				if (m_dwSongFlags & SONG_NOSTEREO) pan = 128;
 				LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1);
 				if (gdwSoundSetup & SNDMIX_SOFTPANNING)
 				{
@@ -1134,6 +1148,7 @@
 			// Check IDO
 			if (gdwSoundSetup & SNDMIX_NORESAMPLING)
 			{
+				pChn->dwFlags &= ~(CHN_HQSRC);
 				pChn->dwFlags |= CHN_NOIDO;
 			} else
 			{
@@ -1151,21 +1166,26 @@
 			pChn->nNewLeftVol >>= MIXING_ATTENUATION;
 			pChn->nRightRamp = pChn->nLeftRamp = 0;
 			// Dolby Pro-Logic Surround
-			if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol;
+			if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0)
+				pChn->nNewLeftVol = -pChn->nNewLeftVol;
 			// Checking Ping-Pong Loops
 			if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc;
 			// Setting up volume ramp
-			if ((pChn->dwFlags & CHN_VOLUMERAMP)
+			if (!(gdwSoundSetup & SNDMIX_NORAMPING)
+			 && (pChn->dwFlags & CHN_VOLUMERAMP)
 			 && ((pChn->nRightVol != pChn->nNewRightVol)
 			  || (pChn->nLeftVol != pChn->nNewLeftVol)))
 			{
 				LONG nRampLength = gnVolumeRampSamples;
 				LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION);
 				LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION);
-#ifndef MODPLUG_FASTSOUNDLIB
+#if 0
 				if ((gdwSoundSetup & SNDMIX_DIRECTTODISK)
 				 || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU))
 				  && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20)))
+#else
+				if (gdwSoundSetup & SNDMIX_HQRESAMPLER)
+#endif
 				{
 					if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP)))
 					{
@@ -1174,7 +1194,6 @@
 						if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples;
 					}
 				}
-#endif
 				pChn->nRightRamp = nRightDelta / nRampLength;
 				pChn->nLeftRamp = nLeftDelta / nRampLength;
 				pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION);
@@ -1197,15 +1216,15 @@
 			pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION;
 			pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION;
 			// Adding the channel in the channel list
-			ChnMix[m_nMixChannels++] = nChn;
-			if (m_nMixChannels >= MAX_CHANNELS) break;
+			if (!(pChn->dwFlags & CHN_MUTE)) {
+				ChnMix[m_nMixChannels++] = nChn;
+				if (m_nMixChannels >= MAX_CHANNELS) break;
+			}
 		} else
 		{
-#ifdef ENABLE_STEREOVU
 			// Note change but no sample
 			if (pChn->nLeftVU > 128) pChn->nLeftVU = 0;
 			if (pChn->nRightVU > 128) pChn->nRightVU = 0;
-#endif
 			if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0;
 			pChn->nLeftVol = pChn->nRightVol = 0;
 			pChn->nLength = 0;