shithub: ft2-clone

Download patch

ref: c8ca07133c9fcb92cc2d9242538764f0f4bbc386
parent: c0d8c8d6057aaf54f72a72c632fd0b94f33710e4
author: Olav Sørensen <olav.sorensen@live.no>
date: Thu Oct 29 12:01:09 EDT 2020

Pushed v1.37 code

- The 4-tap cubic spline resampling interpolation has now been replaced with 8-tap windowed-sinc (polyphase) for better audio quality
- The mixer is now using 64-bit float precision instead of 32-bit float precision. We only mix up to 32 channels anyway, which is not very CPU intensive
- Volume/panning envelope interpolation is now using floating point precision instead of 8.8 fixed-point precision
- Fixed a bug where the scopes would not shut down if you triggered an instrument that is not allocated (empty)
- Small code cleanup

--- a/src/ft2_about.c
+++ b/src/ft2_about.c
@@ -110,19 +110,22 @@
 		*/
 
 		const float z = (matrix.x.z * star->x) + (matrix.y.z * star->y) + (matrix.z.z * star->z) + 0.5f;
-		if (z <= 0.0f) continue;
+		if (z <= 0.0f)
+			continue;
 
 		float y = (((matrix.x.y * star->x) + (matrix.y.y * star->y) + (matrix.z.y * star->z)) / z) * 400.0f;
 		y += 2.0f + (ABOUT_SCREEN_H/2.0f);
 
 		const int32_t outY = (int32_t)(y + 0.5f); // rounded
-		if ((uint32_t)outY > 2+ABOUT_SCREEN_H) continue;
+		if ((uint32_t)outY > 2+ABOUT_SCREEN_H)
+			continue;
 
 		float x = (((matrix.x.x * star->x) + (matrix.y.x * star->y) + (matrix.z.x * star->z)) / z) * 400.0f;
 		x += 2.0f + (ABOUT_SCREEN_W/2.0f);
 
 		const int32_t outX = (int32_t)(x + 0.5f); // rounded
-		if ((uint32_t)outX > 2+ABOUT_SCREEN_W) continue;
+		if ((uint32_t)outX > 2+ABOUT_SCREEN_W)
+			continue;
 
 		// render star pixel if the pixel under it is the background key
 		screenBufferPos = ((uint32_t)outY * SCREEN_W) + (uint32_t)outX;
@@ -131,17 +134,23 @@
 			int32_t d = (int32_t)((255.0f - (z * 235.0f)) + 0.5f);
 
 			d = (d * starfieldFade) >> 8;
-			if (d <= 0) continue;
-			if (d > 255) d = 255;
+			if (d <= 0)
+				continue;
 
-			int32_t r = d - 40;
-			if (r < 0) r = 0;
+			if (d > 255)
+				d = 255;
 
+			int32_t r = d - 48;
+			if (r < 0)
+				r = 0;
+
 			int32_t g = d - 14;
-			if (g < 0) g = 0;
+			if (g < 0)
+				g = 0;
 
-			int32_t b = d + 69; // nice
-			if (b > 255) b = 255;
+			int32_t b = d + 72;
+			if (b > 255)
+				b = 255;
 
 			video.frameBuffer[screenBufferPos] = RGB32(r, g, b);
 			lastStarScreenPos[i] = screenBufferPos;
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -26,14 +26,10 @@
 static uint16_t smpBuffSize;
 static int32_t randSeed = INITIAL_DITHER_SEED;
 static uint32_t oldAudioFreq, tickTimeLen, tickTimeLenFrac;
-static float fAudioNormalizeMul, fPrngStateL, fPrngStateR, fPanningTab[256+1];
+static double dAudioNormalizeMul, dPrngStateL, dPrngStateR, dPanningTab[256+1];
 static voice_t voice[MAX_VOICES * 2];
 static void (*sendAudSamplesFunc)(uint8_t *, uint32_t, uint8_t); // "send mixed samples" routines
 
-static int32_t oldPeriod;
-static uint32_t oldRevDelta;
-static uint64_t oldDelta;
-
 // globalized
 audio_t audio;
 pattSyncData_t *pattSyncEntry;
@@ -44,9 +40,16 @@
 
 void resetCachedMixerVars(void)
 {
-	oldPeriod = -1;
-	oldDelta = 0;
-	oldRevDelta = UINT32_MAX;
+	stmTyp *ch = stm;
+	for (int32_t i = 0; i < MAX_VOICES; i++, ch++)
+		ch->oldFinalPeriod = -1;
+
+	voice_t *v = voice;
+	for (int32_t i = 0; i < MAX_VOICES*2; i++, v++)
+	{
+		v->oldDelta = 0;
+		v->oldRevDelta = UINT32_MAX;
+	}
 }
 
 void stopVoice(int32_t i)
@@ -122,11 +125,11 @@
 	amp = CLAMP(amp, 1, 32);
 	masterVol = CLAMP(masterVol, 0, 256);
 
-	float fAmp = (amp * masterVol) / (32.0f * 256.0f);
+	double dAmp = (amp * masterVol) / (32.0 * 256.0);
 	if (!bitDepth32Flag)
-		fAmp *= 32768.0f;
+		dAmp *= 32768.0;
 
-	fAudioNormalizeMul = fAmp;
+	dAudioNormalizeMul = dAmp;
 }
 
 void setNewAudioFreq(uint32_t freq) // for song-to-WAV rendering
@@ -176,7 +179,7 @@
 	tickTimeLenFrac = tickTimeLen64 & UINT32_MAX;
 
 	// used for calculating volume ramp length for "ticks" ramps
-	audio.fRampTickMul = audio.fRampTickMulTab[bpm];
+	audio.dRampTickMul = audio.dRampTickMulTab[bpm];
 }
 
 void audioSetVolRamp(bool volRamp)
@@ -197,29 +200,29 @@
 {
 	// same formula as FT2's panning table (with 0.0f..1.0f range)
 	for (int32_t i = 0; i <= 256; i++)
-		fPanningTab[i] = sqrtf(i / 256.0f);
+		dPanningTab[i] = sqrt(i / 256.0);
 }
 
 static void voiceUpdateVolumes(int32_t i, uint8_t status)
 {
-	float fDestVolL, fDestVolR;
+	double dDestVolL, dDestVolR;
 
 	voice_t *v = &voice[i];
 
-	const float fVolL = v->fVol * fPanningTab[256-v->pan];
-	const float fVolR = v->fVol * fPanningTab[    v->pan];
+	const double dVolL = v->dVol * dPanningTab[256-v->pan];
+	const double dVolR = v->dVol * dPanningTab[    v->pan];
 
 	if (!audio.volumeRampingFlag)
 	{
 		// volume ramping is disabled
-		v->fVolL = fVolL;
-		v->fVolR = fVolR;
+		v->dVolL = dVolL;
+		v->dVolR = dVolR;
 		v->volRampSamples = 0;
 		return;
 	}
 
-	v->fDestVolL = fVolL;
-	v->fDestVolR = fVolR;
+	v->dDestVolL = dVolL;
+	v->dDestVolR = dVolR;
 
 	if (status & IS_NyTon)
 	{
@@ -226,7 +229,7 @@
 		// sample is about to start, ramp out/in at the same time
 
 		// setup "fade out" voice (only if current voice volume > 0)
-		if (v->fVolL > 0.0f || v->fVolR > 0.0f)
+		if (v->dVolL > 0.0 || v->dVolR > 0.0)
 		{
 			voice_t *f = &voice[MAX_VOICES+i];
 
@@ -234,18 +237,18 @@
 
 			f->volRampSamples = audio.quickVolRampSamples;
 
-			fDestVolL = -f->fVolL;
-			fDestVolR = -f->fVolR;
+			dDestVolL = -f->dVolL;
+			dDestVolR = -f->dVolR;
 
-			f->fVolDeltaL = fDestVolL * audio.fRampQuickVolMul;
-			f->fVolDeltaR = fDestVolR * audio.fRampQuickVolMul;
+			f->dVolDeltaL = dDestVolL * audio.dRampQuickVolMul;
+			f->dVolDeltaR = dDestVolR * audio.dRampQuickVolMul;
 
 			f->isFadeOutVoice = true;
 		}
 
 		// make current voice fade in from zero when it starts
-		v->fVolL = 0.0f;
-		v->fVolR = 0.0f;
+		v->dVolL = 0.0;
+		v->dVolR = 0.0;
 	}
 
 	// ramp volume changes
@@ -256,7 +259,7 @@
 	*/
 
 	// if destination volume and current volume is the same (and we have no sample trigger), don't do ramp
-	if (fVolL == v->fVolL && fVolR == v->fVolR && !(status & IS_NyTon))
+	if (dVolL == v->dVolL && dVolR == v->dVolR && !(status & IS_NyTon))
 	{
 		// there is no volume change
 		v->volRampSamples = 0;
@@ -263,31 +266,31 @@
 	}
 	else
 	{
-		fDestVolL = fVolL - v->fVolL;
-		fDestVolR = fVolR - v->fVolR;
+		dDestVolL = dVolL - v->dVolL;
+		dDestVolR = dVolR - v->dVolR;
 
 		if (status & IS_QuickVol)
 		{
 			v->volRampSamples = audio.quickVolRampSamples;
-			v->fVolDeltaL = fDestVolL * audio.fRampQuickVolMul;
-			v->fVolDeltaR = fDestVolR * audio.fRampQuickVolMul;
+			v->dVolDeltaL = dDestVolL * audio.dRampQuickVolMul;
+			v->dVolDeltaR = dDestVolR * audio.dRampQuickVolMul;
 		}
 		else
 		{
 			v->volRampSamples = audio.samplesPerTick;
-			v->fVolDeltaL = fDestVolL * audio.fRampTickMul;
-			v->fVolDeltaR = fDestVolR * audio.fRampTickMul;
+			v->dVolDeltaL = dDestVolL * audio.dRampTickMul;
+			v->dVolDeltaR = dDestVolR * audio.dRampTickMul;
 		}
 	}
 }
 
-static void voiceTrigger(int32_t i, sampleTyp *s, int32_t position)
+static void voiceTrigger(int32_t ch, sampleTyp *s, int32_t position)
 {
 	bool sampleIs16Bit;
 	uint8_t loopType;
 	int32_t length, loopStart, loopLength, loopEnd;
 
-	voice_t *v = &voice[i];
+	voice_t *v = &voice[ch];
 	length = s->len;
 	loopStart = s->repS;
 	loopLength = s->repL;
@@ -321,26 +324,15 @@
 	{
 		v->base16 = (const int16_t *)s->pek;
 		v->revBase16 = &v->base16[loopStart + loopEnd]; // for pingpong loops
-
-		// first tap [-1] sample for special case: if (hasLooped && pos == loopStart)
-		if (loopType == 1)
-			v->fTapFixSample = v->base16[loopEnd-1];
-		else if (loopType == 2)
-			v->fTapFixSample = v->base16[loopStart];
 	}
 	else
 	{
 		v->base8 = s->pek;
 		v->revBase8 = &v->base8[loopStart + loopEnd]; // for pingpong loops
-
-		// first tap [-1] sample for special case: if (hasLooped && pos == loopStart)
-		if (loopType == 1)
-			v->fTapFixSample = v->base8[loopEnd-1];
-		else if (loopType == 2)
-			v->fTapFixSample = v->base8[loopStart];
 	}
 
-	v->hasLooped = false; // for cubic interpolation special case (read fTapFixSample comment above)
+	v->dLeftEdgeTaps = s->dLeftEdgeTapSamples + 3;
+	v->hasLooped = false; // for sinc interpolation special case
 
 	v->backwards = false;
 	v->loopType = loopType;
@@ -366,8 +358,8 @@
 	voice_t *v = voice;
 	for (int32_t i = 0; i < song.antChn; i++, v++)
 	{
-		v->fVolL = v->fDestVolL;
-		v->fVolR = v->fDestVolR;
+		v->dVolL = v->dDestVolL;
+		v->dVolR = v->dDestVolR;
 		v->volRampSamples = 0;
 	}
 }
@@ -388,7 +380,7 @@
 		ch->status = 0;
 
 		if (status & IS_Vol)
-			v->fVol = ch->fFinalVol;
+			v->dVol = ch->dFinalVol;
 
 		if (status & IS_Pan)
 			v->pan = ch->finalPan;
@@ -399,16 +391,33 @@
 		if (status & IS_Period)
 		{
 			// use cached values if possible
-			const uint16_t period = ch->finalPeriod;
-			if (period != oldPeriod)
+			if (ch->finalPeriod != ch->oldFinalPeriod)
 			{
-				oldPeriod = period;
-				oldDelta = getMixerDelta(period);
-				oldRevDelta = getRevMixerDelta(period);
+				ch->oldFinalPeriod = ch->finalPeriod;
+
+				if (ch->finalPeriod == 0) // in FT2, period 0 -> delta 0
+				{
+					v->oldDelta = 0;
+					v->oldRevDelta = UINT32_MAX;
+					v->dSincLUT = gKaiserSinc;
+				}
+				else
+				{
+					v->oldDelta = getMixerDelta(ch->finalPeriod);
+					v->oldRevDelta = getRevMixerDelta(ch->finalPeriod); // for calc'ing max samples in inner mix loop before sample end/loop end
+
+					// decide which sinc LUT to use according to resampling ratio
+					if (v->oldDelta <= 0x130000000) // 1.1875 (32.32 fixed-point)
+						v->dSincLUT = gKaiserSinc;
+					else if (v->oldDelta <= 0x180000000) // 1.5 (32.32 fixed-point)
+						v->dSincLUT = gDownSample1;
+					else
+						v->dSincLUT = gDownSample2;
+				}
 			}
 
-			v->delta = oldDelta;
-			v->revDelta = oldRevDelta;
+			v->delta = v->oldDelta;
+			v->revDelta = v->oldRevDelta;
 		}
 
 		if (status & IS_NyTon)
@@ -419,8 +428,8 @@
 void resetAudioDither(void)
 {
 	randSeed = INITIAL_DITHER_SEED;
-	fPrngStateL = 0.0f;
-	fPrngStateR = 0.0f;
+	dPrngStateL = 0.0;
+	dPrngStateR = 0.0;
 }
 
 static inline int32_t random32(void)
@@ -435,24 +444,24 @@
 static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
 {
 	int32_t out32;
-	float fOut, fPrng;
+	double dOut, dPrng;
 
 	int16_t *streamPointer16 = (int16_t *)stream;
 	for (uint32_t i = 0; i < sampleBlockLength; i++)
 	{
 		// left channel - 1-bit triangular dithering
-		fPrng = random32() * (0.5f / INT32_MAX); // -0.5f .. 0.5f
-		fOut = ((audio.fMixBufferL[i] * fAudioNormalizeMul) + fPrng) - fPrngStateL;
-		fPrngStateL = fPrng;
-		out32 = (int32_t)fOut;
+		dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
+		dOut = ((audio.dMixBufferL[i] * dAudioNormalizeMul) + dPrng) - dPrngStateL;
+		dPrngStateL = dPrng;
+		out32 = (int32_t)dOut;
 		CLAMP16(out32);
 		*streamPointer16++ = (int16_t)out32;
 
 		// right channel - 1-bit triangular dithering
-		fPrng = random32() * (0.5f / INT32_MAX); // -0.5f .. 0.5f
-		fOut = ((audio.fMixBufferR[i] * fAudioNormalizeMul) + fPrng) - fPrngStateR;
-		fPrngStateR = fPrng;
-		out32 = (int32_t)fOut;
+		dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
+		dOut = ((audio.dMixBufferR[i] * dAudioNormalizeMul) + dPrng) - dPrngStateR;
+		dPrngStateR = dPrng;
+		out32 = (int32_t)dOut;
 		CLAMP16(out32);
 		*streamPointer16++ = (int16_t)out32;
 	}
@@ -463,24 +472,24 @@
 static void sendSamples16BitDitherMultiChan(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
 {
 	int32_t out32;
-	float fOut, fPrng;
+	double dOut, dPrng;
 
 	int16_t *streamPointer16 = (int16_t *)stream;
 	for (uint32_t i = 0; i < sampleBlockLength; i++)
 	{
 		// left channel - 1-bit triangular dithering
-		fPrng = random32() * (0.5f / INT32_MAX); // -0.5f..0.5f
-		fOut = ((audio.fMixBufferL[i] * fAudioNormalizeMul) + fPrng) - fPrngStateL;
-		fPrngStateL = fPrng;
-		out32 = (int32_t)fOut;
+		dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
+		dOut = ((audio.dMixBufferL[i] * dAudioNormalizeMul) + dPrng) - dPrngStateL;
+		dPrngStateL = dPrng;
+		out32 = (int32_t)dOut;
 		CLAMP16(out32);
 		*streamPointer16++ = (int16_t)out32;
 
 		// right channel - 1-bit triangular dithering
-		fPrng = random32() * (0.5f / INT32_MAX); // -0.5f..0.5f
-		fOut = ((audio.fMixBufferR[i] * fAudioNormalizeMul) + fPrng) - fPrngStateR;
-		fPrngStateR = fPrng;
-		out32 = (int32_t)fOut;
+		dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
+		dOut = ((audio.dMixBufferR[i] * dAudioNormalizeMul) + dPrng) - dPrngStateR;
+		dPrngStateR = dPrng;
+		out32 = (int32_t)dOut;
 		CLAMP16(out32);
 		*streamPointer16++ = (int16_t)out32;
 
@@ -492,20 +501,20 @@
 
 static void sendSamples32BitStereo(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
 {
-	float fOut;
+	double dOut;
 
 	float *fStreamPointer32 = (float *)stream;
 	for (uint32_t i = 0; i < sampleBlockLength; i++)
 	{
 		// left channel
-		fOut = audio.fMixBufferL[i] * fAudioNormalizeMul;
-		fOut = CLAMP(fOut, -1.0f, 1.0f);
-		*fStreamPointer32++ = fOut;
+		dOut = audio.dMixBufferL[i] * dAudioNormalizeMul;
+		dOut = CLAMP(dOut, -1.0, 1.0);
+		*fStreamPointer32++ = (float)dOut;
 
 		// right channel
-		fOut = audio.fMixBufferR[i] * fAudioNormalizeMul;
-		fOut = CLAMP(fOut, -1.0f, 1.0f);
-		*fStreamPointer32++ = fOut;
+		dOut = audio.dMixBufferR[i] * dAudioNormalizeMul;
+		dOut = CLAMP(dOut, -1.0, 1.0);
+		*fStreamPointer32++ = (float)dOut;
 	}
 
 	(void)numAudioChannels;
@@ -513,20 +522,20 @@
 
 static void sendSamples32BitMultiChan(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
 {
-	float fOut;
+	double dOut;
 
 	float *fStreamPointer32 = (float *)stream;
 	for (uint32_t i = 0; i < sampleBlockLength; i++)
 	{
 		// left channel
-		fOut = audio.fMixBufferL[i] * fAudioNormalizeMul;
-		fOut = CLAMP(fOut, -1.0f, 1.0f);
-		*fStreamPointer32++ = fOut;
+		dOut = audio.dMixBufferL[i] * dAudioNormalizeMul;
+		dOut = CLAMP(dOut, -1.0, 1.0);
+		*fStreamPointer32++ = (float)dOut;
 
 		// right channel
-		fOut = audio.fMixBufferR[i] * fAudioNormalizeMul;
-		fOut = CLAMP(fOut, -1.0f, 1.0f);
-		*fStreamPointer32++ = fOut;
+		dOut = audio.dMixBufferR[i] * dAudioNormalizeMul;
+		dOut = CLAMP(dOut, -1.0, 1.0);
+		*fStreamPointer32++ = (float)dOut;
 
 		// send zeroes to the rest of the channels
 		for (uint32_t j = 2; j < numAudioChannels; j++)
@@ -548,17 +557,17 @@
 			const bool volRampFlag = v->volRampSamples > 0;
 			if (volRampFlag)
 			{
-				centerMixFlag = (v->fDestVolL == v->fDestVolR) && (v->fVolDeltaL == v->fVolDeltaR);
+				centerMixFlag = (v->dDestVolL == v->dDestVolR) && (v->dVolDeltaL == v->dVolDeltaR);
 			}
-			else
+			else // no volume ramping active
 			{
-				if (v->fVolL == 0.0f && v->fVolR == 0.0f)
-				{ 
+				if (v->dVolL == 0.0 && v->dVolR == 0.0)
+				{
 					silenceMixRoutine(v, samplesToMix);
 					continue;
 				}
 
-				centerMixFlag = v->fVolL == v->fVolR;
+				centerMixFlag = v->dVolL == v->dVolR;
 			}
 
 			mixFuncTab[(centerMixFlag * 36) + (volRampFlag * 18) + v->mixFuncOffset](v, samplesToMix);
@@ -566,7 +575,7 @@
 
 		if (r->active) // volume ramp fadeout-voice
 		{
-			const bool centerMixFlag = (r->fDestVolL == r->fDestVolR) && (r->fVolDeltaL == r->fVolDeltaR);
+			const bool centerMixFlag = (r->dDestVolL == r->dDestVolR) && (r->dVolDeltaL == r->dVolDeltaR);
 			mixFuncTab[(centerMixFlag * 36) + 18 + r->mixFuncOffset](r, samplesToMix);
 		}
 	}
@@ -575,8 +584,8 @@
 static void mixAudio(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
 {
 	assert(sampleBlockLength <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
-	memset(audio.fMixBufferL, 0, sampleBlockLength * sizeof (int32_t));
-	memset(audio.fMixBufferR, 0, sampleBlockLength * sizeof (int32_t));
+	memset(audio.dMixBufferL, 0, sampleBlockLength * sizeof (double));
+	memset(audio.dMixBufferR, 0, sampleBlockLength * sizeof (double));
 
 	doChannelMixing(sampleBlockLength);
 
@@ -588,8 +597,8 @@
 void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth)
 {
 	assert(samplesToMix <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
-	memset(audio.fMixBufferL, 0, samplesToMix * sizeof (int32_t));
-	memset(audio.fMixBufferR, 0, samplesToMix * sizeof (int32_t));
+	memset(audio.dMixBufferL, 0, samplesToMix * sizeof (double));
+	memset(audio.dMixBufferR, 0, samplesToMix * sizeof (double));
 
 	doChannelMixing(samplesToMix);
 
@@ -900,7 +909,7 @@
 		c->sampleNr = s->sampleNr;
 		c->envSustainActive = s->envSustainActive;
 		c->status = s->tmpStatus;
-		c->fFinalVol = s->fFinalVol;
+		c->dFinalVol = s->dFinalVol;
 		c->smpStartPos = s->smpStartPos;
 	}
 
@@ -963,17 +972,17 @@
 
 static bool setupAudioBuffers(void)
 {
-	const uint32_t sampleSize = sizeof (int32_t);
+	const uint32_t sampleSize = sizeof (double);
 
-	audio.fMixBufferLUnaligned = (float *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
-	audio.fMixBufferRUnaligned = (float *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
+	audio.dMixBufferLUnaligned = (double *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
+	audio.dMixBufferRUnaligned = (double *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
 
-	if (audio.fMixBufferLUnaligned == NULL || audio.fMixBufferRUnaligned == NULL)
+	if (audio.dMixBufferLUnaligned == NULL || audio.dMixBufferRUnaligned == NULL)
 		return false;
 
 	// make aligned main pointers
-	audio.fMixBufferL = (float *)ALIGN_PTR(audio.fMixBufferLUnaligned, 256);
-	audio.fMixBufferR = (float *)ALIGN_PTR(audio.fMixBufferRUnaligned, 256);
+	audio.dMixBufferL = (double *)ALIGN_PTR(audio.dMixBufferLUnaligned, 256);
+	audio.dMixBufferR = (double *)ALIGN_PTR(audio.dMixBufferRUnaligned, 256);
 
 	return true;
 }
@@ -980,20 +989,20 @@
 
 static void freeAudioBuffers(void)
 {
-	if (audio.fMixBufferLUnaligned != NULL)
+	if (audio.dMixBufferLUnaligned != NULL)
 	{
-		free(audio.fMixBufferLUnaligned);
-		audio.fMixBufferLUnaligned = NULL;
+		free(audio.dMixBufferLUnaligned);
+		audio.dMixBufferLUnaligned = NULL;
 	}
 
-	if (audio.fMixBufferRUnaligned != NULL)
+	if (audio.dMixBufferRUnaligned != NULL)
 	{
-		free(audio.fMixBufferRUnaligned);
-		audio.fMixBufferRUnaligned = NULL;
+		free(audio.dMixBufferRUnaligned);
+		audio.dMixBufferRUnaligned = NULL;
 	}
 
-	audio.fMixBufferL = NULL;
-	audio.fMixBufferR = NULL;
+	audio.dMixBufferL = NULL;
+	audio.dMixBufferR = NULL;
 }
 
 void updateSendAudSamplesRoutine(bool lockMixer)
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -11,8 +11,6 @@
 	FREQ_TABLE_AMIGA = 1,
 };
 
-#define NUM_FIXED_TAP_SAMPLES 2
-
 #define MIN_AUDIO_FREQ 44100
 #define MAX_AUDIO_FREQ 192000
 
@@ -35,8 +33,8 @@
 	int32_t quickVolRampSamples, inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;
 	uint32_t freq, audLatencyPerfValInt, audLatencyPerfValFrac, samplesPerTick, musicTimeSpeedVal;
 	uint64_t tickTime64, tickTime64Frac, tickTimeTab[MAX_BPM+1];
-	float fRampQuickVolMul, fRampTickMul, fRampTickMulTab[MAX_BPM+1];
-	float *fMixBufferL, *fMixBufferR, *fMixBufferLUnaligned, *fMixBufferRUnaligned;
+	double dRampQuickVolMul, dRampTickMul, dRampTickMulTab[MAX_BPM+1];
+	double *dMixBufferL, *dMixBufferR, *dMixBufferLUnaligned, *dMixBufferRUnaligned;
 	double dAudioLatencyMs, dSamplesPerTick, dTickSampleCounter, dSamplesPerTickTab[MAX_BPM+1];
 
 	SDL_AudioDeviceID dev;
@@ -50,10 +48,11 @@
 	bool active, backwards, isFadeOutVoice, hasLooped;
 	uint8_t mixFuncOffset, pan, loopType;
 	int32_t pos, end, loopStart, loopLength;
-	uint32_t volRampSamples, revDelta;
-	uint64_t posFrac, delta;
-	float fTapFixSample; // if (loopStart > 0 && pos == loopStart) useThisForFirstTap();
-	float fVol, fDestVolL, fDestVolR, fVolL, fVolR, fVolDeltaL, fVolDeltaR;
+	uint32_t volRampSamples, revDelta, oldRevDelta;
+	uint64_t posFrac, delta, oldDelta;
+	const double *dSincLUT;
+	double *dLeftEdgeTaps; // if (loopStart > 0 && pos <= loopStart+3) useTheseTaps();
+	double dVol, dDestVolL, dDestVolR, dVolL, dVolR, dVolDeltaL, dVolDeltaR;
 } voice_t;
 
 typedef struct pattSyncData_t
--- a/src/ft2_bmp.c
+++ b/src/ft2_bmp.c
@@ -94,9 +94,8 @@
 	bmp.checkboxGfx = loadBMPTo4BitPal(checkboxGfxBMP);
 
 	if (bmp.ft2AboutLogo == NULL || bmp.font1 == NULL || bmp.font2 == NULL ||
-		bmp.font3 == NULL || bmp.font4 == NULL || bmp.font6 == NULL ||
-		bmp.font6 == NULL || bmp.font7 == NULL || bmp.font8 == NULL ||
-		bmp.ft2LogoBadges == NULL || bmp.ft2ByBadges == NULL ||
+		bmp.font3 == NULL || bmp.font4 == NULL || bmp.font6 == NULL || bmp.font7 == NULL ||
+		bmp.font8 == NULL || bmp.ft2LogoBadges == NULL || bmp.ft2ByBadges == NULL ||
 		bmp.midiLogo == NULL || bmp.nibblesLogo == NULL || bmp.nibblesStages == NULL ||
 		bmp.loopPins == NULL || bmp.mouseCursors == NULL || bmp.mouseCursorBusyClock == NULL ||
 		bmp.mouseCursorBusyGlass == NULL || bmp.whitePianoKeys == NULL || bmp.blackPianoKeys == NULL ||
--- a/src/ft2_config.c
+++ b/src/ft2_config.c
@@ -141,7 +141,7 @@
 	config.recMIDIVolSens = CLAMP(config.recMIDIVolSens, 0, 200);
 	config.recMIDIChn  = CLAMP(config.recMIDIChn, 1, 16);
 
-	config.interpolation &= 3; // one extra bit used in FT2 clone (off, cubic, linear)
+	config.interpolation &= 3; // one extra bit used in FT2 clone (off, sinc, linear)
 
 	if (config.recTrueInsert > 1)
 		config.recTrueInsert = 1;
@@ -837,7 +837,7 @@
 	else if (config.interpolation == INTERPOLATION_LINEAR)
 		tmpID = RB_CONFIG_AUDIO_INTRP_LINEAR;
 	else
-		tmpID = RB_CONFIG_AUDIO_INTRP_CUBIC;
+		tmpID = RB_CONFIG_AUDIO_INTRP_SINC;
 
 	radioButtons[tmpID].state = RADIOBUTTON_CHECKED;
 
@@ -1168,7 +1168,7 @@
 			textOutShadow(390, 105, PAL_FORGRND, PAL_DSKTOP2, "Interpolation:");
 			textOutShadow(406, 118, PAL_FORGRND, PAL_DSKTOP2, "None");
 			textOutShadow(406, 132, PAL_FORGRND, PAL_DSKTOP2, "Linear (FT2)");
-			textOutShadow(406, 146, PAL_FORGRND, PAL_DSKTOP2, "Cubic spline");
+			textOutShadow(406, 146, PAL_FORGRND, PAL_DSKTOP2, "Windowed-sinc");
 			textOutShadow(406, 161, PAL_FORGRND, PAL_DSKTOP2, "Volume ramping");
 
 			textOutShadow(509,   3, PAL_FORGRND, PAL_DSKTOP2, "Mixing frequency:");
@@ -1619,11 +1619,11 @@
 	checkRadioButton(RB_CONFIG_AUDIO_INTRP_LINEAR);
 }
 
-void rbConfigAudioIntrpCubic(void)
+void rbConfigAudioIntrpSinc(void)
 {
-	config.interpolation = INTERPOLATION_CUBIC;
+	config.interpolation = INTERPOLATION_SINC;
 	audioSetInterpolationType(config.interpolation);
-	checkRadioButton(RB_CONFIG_AUDIO_INTRP_CUBIC);
+	checkRadioButton(RB_CONFIG_AUDIO_INTRP_SINC);
 }
 
 void rbConfigAudio44kHz(void)
--- a/src/ft2_config.h
+++ b/src/ft2_config.h
@@ -19,7 +19,7 @@
 	CONFIG_SHOW_ERRORS = 1,
 
 	INTERPOLATION_NONE = 0,
-	INTERPOLATION_CUBIC = 1,
+	INTERPOLATION_SINC = 1,
 	INTERPOLATION_LINEAR = 2,
 
 	MOUSE_IDLE_SHAPE_NICE = 0,
@@ -211,7 +211,7 @@
 void rbConfigAudio24bit(void);
 void rbConfigAudioIntrpNone(void);
 void rbConfigAudioIntrpLinear(void);
-void rbConfigAudioIntrpCubic(void);
+void rbConfigAudioIntrpSinc(void);
 void rbConfigAudio44kHz(void);
 void rbConfigAudio48kHz(void);
 void rbConfigAudio96kHz(void);
--- a/src/ft2_edit.c
+++ b/src/ft2_edit.c
@@ -963,7 +963,7 @@
 	countOverflowingNotes(lastInsMode, lastTranspMode, lastTranspVal);
 	if (transpDelNotes > 0)
 	{
-		sprintf(text, "%d note(s) will be erased! Proceed?", transpDelNotes);
+		sprintf(text, "%d note(s) will be erased! Proceed?", (int32_t)transpDelNotes);
 		if (okBox(2, "System request", text) != 1)
 			return;
 	}
--- a/src/ft2_events.c
+++ b/src/ft2_events.c
@@ -311,7 +311,7 @@
 			// find a free filename
 			for (i = 1; i < 1000; i++)
 			{
-				sprintf(fileName, "backup%03d.xm", i);
+				sprintf(fileName, "backup%03d.xm", (int32_t)i);
 				if (stat(fileName, &statBuffer) != 0)
 					break; // filename OK
 			}
--- a/src/ft2_header.h
+++ b/src/ft2_header.h
@@ -12,7 +12,7 @@
 #endif
 #include "ft2_replayer.h"
 
-#define PROG_VER_STR "1.36"
+#define PROG_VER_STR "1.37"
 
 // do NOT change these! It will only mess things up...
 
@@ -33,8 +33,8 @@
 ** branchless in the inner channel mixer loop.
 ** Warning: Do not change this!
 */
-#define LOOP_FIX_LEN 8
-#define SMP_DAT_OFFSET 4
+#define LOOP_FIX_LEN 32
+#define SMP_DAT_OFFSET 8
 
 #ifndef _WIN32
 #define _stricmp strcasecmp
--- a/src/ft2_nibbles.c
+++ b/src/ft2_nibbles.c
@@ -362,7 +362,14 @@
 		x = rand() % 51;
 		y = rand() % 23;
 
-		if (NI_Screen[x][y] == 0 && NI_Screen[x][y+1] == 0)
+		bool blockIsSuitable;
+
+		if (y < 22)
+			blockIsSuitable = NI_Screen[x][y] == 0 && NI_Screen[x][y+1] == 0;
+		else
+			blockIsSuitable = NI_Screen[x][y] == 0; // FT2 bugfix: prevent look-up overflow
+
+		if (blockIsSuitable)
 		{
 			NI_Number++;
 			NI_Screen[x][y] = (uint8_t)(16 + NI_Number);
--- a/src/ft2_radiobuttons.c
+++ b/src/ft2_radiobuttons.c
@@ -74,21 +74,21 @@
 	// ------ CONFIG AUDIO ------
 
 	// audio buffer size
-	//x,   y,   w,   group,                           funcOnUp
+	//x,   y,   w,  group,                           funcOnUp
 	{ 390, 16,  46, RB_GROUP_CONFIG_SOUND_BUFF_SIZE, rbConfigSbs512  },
 	{ 390, 30, 113, RB_GROUP_CONFIG_SOUND_BUFF_SIZE, rbConfigSbs1024 },
 	{ 390, 44,  50, RB_GROUP_CONFIG_SOUND_BUFF_SIZE, rbConfigSbs2048 },
 
 	// audio bit depth
-	//x,   y,   w,   group,                           funcOnUp
+	//x,   y,   w,  group,                           funcOnUp
 	{ 390, 74, 107, RB_GROUP_CONFIG_AUDIO_BIT_DEPTH, rbConfigAudio16bit },
 	{ 390, 88,  83, RB_GROUP_CONFIG_AUDIO_BIT_DEPTH, rbConfigAudio24bit },
 
 	// audio interpolation
-	//x,   y,   w,   group,                              funcOnUp
-	{ 390, 117, 46, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpNone },
-	{ 390, 131, 91, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpLinear },
-	{ 390, 145, 86, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpCubic },
+	//x,   y,   w,   group,                               funcOnUp
+	{ 390, 117,  46, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpNone },
+	{ 390, 131,  91, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpLinear },
+	{ 390, 145, 103, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpSinc },
 
 	// audio output frequency
 	//x,   y,   w,  group,                      funcOnUp
--- a/src/ft2_radiobuttons.h
+++ b/src/ft2_radiobuttons.h
@@ -57,7 +57,7 @@
 	// AUDIO INTERPOLATION
 	RB_CONFIG_AUDIO_INTRP_NONE,
 	RB_CONFIG_AUDIO_INTRP_LINEAR,
-	RB_CONFIG_AUDIO_INTRP_CUBIC,
+	RB_CONFIG_AUDIO_INTRP_SINC,
 
 	// AUDIO FREQUENCY
 	RB_CONFIG_AUDIO_44KHZ,
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -20,7 +20,7 @@
 #include "ft2_sample_loader.h"
 #include "ft2_tables.h"
 #include "ft2_structs.h"
-#include "mixer/ft2_cubicspline.h"
+#include "mixer/ft2_windowed_sinc.h"
 
 /* This is a mess, directly ported from the original FT2 code (with some modifications).
 ** You will experience a lot of headaches if you dig into it...
@@ -101,7 +101,7 @@
 	{
 		stmTyp *ch = &stm[i];
 
-		ch->instrSeg = instr[0];
+		ch->instrPtr = instr[0];
 		ch->status = IS_Vol;
 		ch->oldPan = 128;
 		ch->outPan = 128;
@@ -293,8 +293,6 @@
 
 static void retrigEnvelopeVibrato(stmTyp *ch)
 {
-	instrTyp *ins;
-
 	if (!(ch->waveCtrl & 0x04)) ch->vibPos = 0;
 	if (!(ch->waveCtrl & 0x40)) ch->tremPos = 0;
 
@@ -303,7 +301,7 @@
 
 	ch->envSustainActive = true;
 
-	ins = ch->instrSeg;
+	instrTyp *ins = ch->instrPtr;
 	assert(ins != NULL);
 
 	if (ins->envVTyp & 1)
@@ -340,22 +338,20 @@
 
 void keyOff(stmTyp *ch)
 {
-	instrTyp *ins;
-
 	ch->envSustainActive = false;
 
-	ins = ch->instrSeg;
+	instrTyp *ins = ch->instrPtr;
 	assert(ins != NULL);
 
 	if (!(ins->envPTyp & 1)) // yes, FT2 does this (!). Most likely a bug?
 	{
-		if (ch->envPCnt >= ins->envPP[ch->envPPos][0])
+		if (ch->envPCnt >= (uint16_t)ins->envPP[ch->envPPos][0])
 			ch->envPCnt = ins->envPP[ch->envPPos][0] - 1;
 	}
 
 	if (ins->envVTyp & 1)
 	{
-		if (ch->envVCnt >= ins->envVP[ch->envVPos][0])
+		if (ch->envVCnt >= (uint16_t)ins->envVP[ch->envVPos][0])
 			ch->envVCnt = ins->envVP[ch->envVPos][0] - 1;
 	}
 	else
@@ -379,11 +375,11 @@
 
 	dHz2MixDeltaMul = (double)MIXER_FRAC_SCALE / audioFreq;
 	audio.quickVolRampSamples = (int32_t)((audioFreq / 200.0) + 0.5); // rounded
-	audio.fRampQuickVolMul = 1.0f / audio.quickVolRampSamples;
+	audio.dRampQuickVolMul = 1.0 / audio.quickVolRampSamples;
 
 	audio.dSamplesPerTickTab[0] = 0.0;
 	audio.tickTimeTab[0] = UINT64_MAX;
-	audio.fRampTickMulTab[0] = 0.0f;
+	audio.dRampTickMulTab[0] = 0.0;
 
 	for (int32_t i = MIN_BPM; i <= MAX_BPM; i++)
 	{
@@ -402,7 +398,7 @@
 
 		// for calculating volume ramp length for tick-lenghted ramps
 		const int32_t samplesPerTick = (int32_t)(dSamplesPerTick + 0.5); // this has to be rounded first
-		audio.fRampTickMulTab[i] = 1.0f / samplesPerTick;
+		audio.dRampTickMulTab[i] = 1.0 / samplesPerTick;
 	}
 }
 
@@ -415,11 +411,12 @@
 {
 	/* Precision has been tested for most extreme case (Amiga period 1, 44100Hz),
 	** and there is no precision loss using 64-bit double-precision here, even
-	** though we can get very big numbers.
+	** though we can get VERY big numbers.
 	*/
 	return (int64_t)((dPeriod2Hz(period) * dHz2MixDeltaMul) + 0.5); // Hz -> rounded 32.32 fixed-point mixer delta
 }
 
+// used for calculating the max safe amount of samples to mix before entering inner mix loop
 uint32_t getRevMixerDelta(uint16_t period)
 {
 	return revMixDeltaTab[period];
@@ -467,7 +464,7 @@
 	if (ins == NULL)
 		ins = instr[0];
 
-	ch->instrSeg = ins;
+	ch->instrPtr = ins;
 	ch->mute = ins->mute;
 
 	if (ton > 96) // non-FT2 security (should never happen because I clamp in the patt. loader now)
@@ -742,7 +739,7 @@
 	bool envUpdate;
 	int16_t newEnvPos;
 
-	instrTyp *ins = ch->instrSeg;
+	instrTyp *ins = ch->instrPtr;
 	assert(ins != NULL);
 
 	// *** VOLUME ENVELOPE ***
@@ -776,11 +773,9 @@
 						break;
 					}
 
-					ch->envVIPValue = ((ins->envVP[envPos+1][1] - ins->envVP[envPos][1]) & 0xFF) << 8;
-					ch->envVIPValue /= (ins->envVP[envPos+1][0] - ins->envVP[envPos][0]);
+					ch->dEnvVIPValue = (double)(ins->envVP[envPos+1][1] - ins->envVP[envPos][1]) / (ins->envVP[envPos+1][0] - ins->envVP[envPos][0]);
+					ch->dEnvVAmp = (ch->dEnvVIPValue * (newEnvPos - 1)) + (ins->envVP[envPos][1] & 0xFF);
 
-					ch->envVAmp = (ch->envVIPValue * (newEnvPos - 1)) + ((ins->envVP[envPos][1] & 0xFF) << 8);
-
 					envPos++;
 
 					envUpdate = false;
@@ -796,8 +791,8 @@
 
 		if (envUpdate)
 		{
-			ch->envVIPValue = 0;
-			ch->envVAmp = (ins->envVP[envPos][1] & 0xFF) << 8;
+			ch->dEnvVIPValue = 0.0;
+			ch->dEnvVAmp = (double)(ins->envVP[envPos][1] & 0xFF);
 		}
 
 		if (envPos >= ins->envVPAnt)
@@ -841,11 +836,9 @@
 						break;
 					}
 
-					ch->envPIPValue = ((ins->envPP[envPos+1][1] - ins->envPP[envPos][1]) & 0xFF) << 8;
-					ch->envPIPValue /= (ins->envPP[envPos+1][0] - ins->envPP[envPos][0]);
+					ch->dEnvPIPValue = (double)(ins->envPP[envPos+1][1] - ins->envPP[envPos][1]) / (ins->envPP[envPos+1][0] - ins->envPP[envPos][0]);
+					ch->dEnvPAmp = (ch->dEnvPIPValue * (newEnvPos - 1)) + (ins->envPP[envPos][1] & 0xFF);
 
-					ch->envPAmp = (ch->envPIPValue * (newEnvPos - 1)) + ((ins->envPP[envPos][1] & 0xFF) << 8);
-
 					envPos++;
 
 					envUpdate = false;
@@ -861,8 +854,8 @@
 
 		if (envUpdate)
 		{
-			ch->envPIPValue = 0;
-			ch->envPAmp = (ins->envPP[envPos][1] & 0xFF) << 8;
+			ch->dEnvPIPValue = 0.0;
+			ch->dEnvPAmp = (double)(ins->envPP[envPos][1] & 0xFF);
 		}
 
 		if (envPos >= ins->envPPAnt)
@@ -1354,11 +1347,10 @@
 	bool envInterpolateFlag, envDidInterpolate;
 	uint8_t envPos;
 	int16_t autoVibVal;
-	uint16_t tmpPeriod, autoVibAmp, envVal;
-	float fVol;
-	instrTyp *ins;
+	uint16_t tmpPeriod, autoVibAmp;
+	double dVol, dEnvVal;
 
-	ins = ch->instrSeg;
+	instrTyp *ins = ch->instrPtr;
 	assert(ins != NULL);
 
 	// *** FADEOUT ***
@@ -1381,7 +1373,7 @@
 	if (!ch->mute)
 	{
 		// *** VOLUME ENVELOPE ***
-		envVal = 0;
+		dEnvVal = 0.0;
 		if (ins->envVTyp & 1)
 		{
 			envDidInterpolate = false;
@@ -1389,7 +1381,7 @@
 
 			if (++ch->envVCnt == ins->envVP[envPos][0])
 			{
-				ch->envVAmp = ins->envVP[envPos][1] << 8;
+				ch->dEnvVAmp = ins->envVP[envPos][1];
 
 				envPos++;
 				if (ins->envVTyp & 4)
@@ -1402,7 +1394,7 @@
 						{
 							envPos = ins->envVRepS;
 							ch->envVCnt = ins->envVP[envPos][0];
-							ch->envVAmp = ins->envVP[envPos][1] << 8;
+							ch->dEnvVAmp = ins->envVP[envPos][1];
 						}
 					}
 
@@ -1417,7 +1409,7 @@
 						if (envPos-1 == ins->envVSust)
 						{
 							envPos--;
-							ch->envVIPValue = 0;
+							ch->dEnvVIPValue = 0.0;
 							envInterpolateFlag = false;
 						}
 					}
@@ -1426,13 +1418,12 @@
 					{
 						ch->envVPos = envPos;
 
-						ch->envVIPValue = 0;
+						ch->dEnvVIPValue = 0.0;
 						if (ins->envVP[envPos][0] > ins->envVP[envPos-1][0])
 						{
-							ch->envVIPValue = (ins->envVP[envPos][1] - ins->envVP[envPos-1][1]) << 8;
-							ch->envVIPValue /= (ins->envVP[envPos][0] - ins->envVP[envPos-1][0]);
+							ch->dEnvVIPValue = (double)(ins->envVP[envPos][1] - ins->envVP[envPos-1][1]) / (ins->envVP[envPos][0] - ins->envVP[envPos-1][0]);
 
-							envVal = ch->envVAmp;
+							dEnvVal = ch->dEnvVAmp;
 							envDidInterpolate = true;
 						}
 					}
@@ -1439,53 +1430,53 @@
 				}
 				else
 				{
-					ch->envVIPValue = 0;
+					ch->dEnvVIPValue = 0.0;
 				}
 			}
 
 			if (!envDidInterpolate)
 			{
-				ch->envVAmp += ch->envVIPValue;
+				ch->dEnvVAmp += ch->dEnvVIPValue;
 
-				envVal = ch->envVAmp;
-				if (envVal > 64*256)
+				dEnvVal = ch->dEnvVAmp;
+				if (dEnvVal > 64.0)
 				{
-					if (envVal > 128*256)
-						envVal = 64*256;
+					if (dEnvVal > 128.0)
+						dEnvVal = 64.0;
 					else
-						envVal = 0;
+						dEnvVal = 0.0;
 
-					ch->envVIPValue = 0;
+					ch->dEnvVIPValue = 0.0;
 				}
 			}
 
-			fVol  = song.globVol   * (1.0f / 64.0f);
-			fVol *= ch->outVol     * (1.0f / 64.0f);
-			fVol *= ch->fadeOutAmp * (1.0f / 32768.0f);
-			fVol *= envVal         * (1.0f / 16384.0f);
+			dVol  = song.globVol   * (1.0 / 64.0);
+			dVol *= ch->outVol     * (1.0 / 64.0);
+			dVol *= ch->fadeOutAmp * (1.0 / 32768.0);
+			dVol *= dEnvVal        * (1.0 / 64.0);
 
 			ch->status |= IS_Vol; // update vol every tick because vol envelope is enabled
 		}
 		else
 		{
-			fVol  = song.globVol   * (1.0f / 64.0f);
-			fVol *= ch->outVol     * (1.0f / 64.0f);
-			fVol *= ch->fadeOutAmp * (1.0f / 32768.0f);
+			dVol  = song.globVol   * (1.0 / 64.0);
+			dVol *= ch->outVol     * (1.0 / 64.0);
+			dVol *= ch->fadeOutAmp * (1.0 / 32768.0);
 		}
 
-		if (fVol > 1.0f) // shouldn't happen, but just in case...
-			fVol = 1.0f;
+		if (dVol > 1.0) // shouldn't happen, but just in case...
+			dVol = 1.0;
 
-		ch->fFinalVol = fVol;
+		ch->dFinalVol = dVol;
 	}
 	else
 	{
-		ch->fFinalVol = 0.0f;
+		ch->dFinalVol = 0.0;
 	}
 
 	// *** PANNING ENVELOPE ***
 
-	envVal = 0;
+	dEnvVal = 0.0;
 	if (ins->envPTyp & 1)
 	{
 		envDidInterpolate = false;
@@ -1493,7 +1484,7 @@
 
 		if (++ch->envPCnt == ins->envPP[envPos][0])
 		{
-			ch->envPAmp = ins->envPP[envPos][1] << 8;
+			ch->dEnvPAmp = ins->envPP[envPos][1];
 
 			envPos++;
 			if (ins->envPTyp & 4)
@@ -1507,7 +1498,7 @@
 						envPos = ins->envPRepS;
 
 						ch->envPCnt = ins->envPP[envPos][0];
-						ch->envPAmp = ins->envPP[envPos][1] << 8;
+						ch->dEnvPAmp = ins->envPP[envPos][1];
 					}
 				}
 
@@ -1522,7 +1513,7 @@
 					if (envPos-1 == ins->envPSust)
 					{
 						envPos--;
-						ch->envPIPValue = 0;
+						ch->dEnvPIPValue = 0.0;
 						envInterpolateFlag = false;
 					}
 				}
@@ -1531,13 +1522,12 @@
 				{
 					ch->envPPos = envPos;
 
-					ch->envPIPValue = 0;
+					ch->dEnvPIPValue = 0.0;
 					if (ins->envPP[envPos][0] > ins->envPP[envPos-1][0])
 					{
-						ch->envPIPValue = (ins->envPP[envPos][1] - ins->envPP[envPos-1][1]) << 8;
-						ch->envPIPValue /= (ins->envPP[envPos][0] - ins->envPP[envPos-1][0]);
+						ch->dEnvPIPValue = (double)(ins->envPP[envPos][1] - ins->envPP[envPos-1][1]) / (ins->envPP[envPos][0] - ins->envPP[envPos-1][0]);
 
-						envVal = ch->envPAmp;
+						dEnvVal = ch->dEnvPAmp;
 						envDidInterpolate = true;
 					}
 				}
@@ -1544,29 +1534,29 @@
 			}
 			else
 			{
-				ch->envPIPValue = 0;
+				ch->dEnvPIPValue = 0.0;
 			}
 		}
 
 		if (!envDidInterpolate)
 		{
-			ch->envPAmp += ch->envPIPValue;
+			ch->dEnvPAmp += ch->dEnvPIPValue;
 
-			envVal = ch->envPAmp;
-			if (envVal > 64*256)
+			dEnvVal = ch->dEnvPAmp;
+			if (dEnvVal > 64.0)
 			{
-				if (envVal > 128*256)
-					envVal = 64*256;
+				if (dEnvVal > 128.0)
+					dEnvVal = 64.0;
 				else
-					envVal = 0;
+					dEnvVal = 0.0;
 
-				ch->envPIPValue = 0;
+				ch->dEnvPIPValue = 0.0;
 			}
 		}
 
 		const int32_t panTmp = 128 - ABS(ch->outPan - 128);
-		const int32_t panEnv = (int32_t)envVal - (32*256); // -8192..7936
-		const int32_t panAdd = (int32_t)roundf((panTmp * panEnv) * (1.0f / 8192.0f)); // -128..124
+		const double dPanEnv = dEnvVal - 32.0;
+		const int32_t panAdd = (int32_t)round((panTmp * dPanEnv) * (1.0 / 32.0)); // -128..124
 		ch->finalPan = (uint8_t)CLAMP(ch->outPan + panAdd, 0, 255);
 
 		ch->status |= IS_Pan; // update pan every tick because pan envelope is enabled
@@ -2809,7 +2799,7 @@
 		instr[131] = NULL;
 	}
 
-	freeCubicTable();
+	freeWindowedSincTables();
 }
 
 bool setupReplayer(void)
@@ -2839,7 +2829,7 @@
 	audio.linearFreqTable = true;
 	note2Period = linearPeriods;
 
-	calcCubicTable();
+	calcWindowedSincTables();
 	calcPeriod2HzTable();
 	calcRevMixDeltaTable();
 	calcPanningTable();
@@ -2916,10 +2906,6 @@
 		// safely kills all voices
 		lockMixerCallback();
 		unlockMixerCallback();
-
-		// prevent getFrequenceValue() from calculating the rates forever
-		for (i = 0; i < MAX_VOICES; i++)
-			stm[i].outPeriod = 0;
 	}
 	else
 	{
@@ -3154,12 +3140,12 @@
 		ch->tonTyp = 0;
 		ch->relTonNr = 0;
 		ch->instrNr = 0;
-		ch->instrSeg = instr[0]; // important: set instrument pointer to instr 0 (placeholder instrument)
+		ch->instrPtr = instr[0]; // important: set instrument pointer to instr 0 (placeholder instrument)
 		ch->status = IS_Vol;
 		ch->realVol = 0;
 		ch->outVol = 0;
 		ch->oldVol = 0;
-		ch->fFinalVol = 0.0f;
+		ch->dFinalVol = 0.0;
 		ch->oldPan = 128;
 		ch->outPan = 128;
 		ch->finalPan = 128;
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -3,10 +3,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "ft2_unicode.h"
+#include "mixer/ft2_windowed_sinc.h"
 
-// cubic spline requires 2 extra samples in the future to be read
-#define NUM_FIXED_TAP_SAMPLES 2
-
 enum
 {
 	// voice flags
@@ -175,7 +173,8 @@
 	bool fixed;
 	int8_t fine, relTon, *pek, *origPek;
 	uint8_t vol, typ, pan;
-	int16_t fixedSmp[NUM_FIXED_TAP_SAMPLES];
+	double dLeftEdgeTapSamples[8+3];
+	int16_t fixedSmp[SINC_RIGHT_TAPS];
 	int32_t fixedPos, len, repS, repL;
 } sampleTyp;
 
@@ -207,14 +206,14 @@
 	uint8_t portaUpSpeed, portaDownSpeed, retrigSpeed, retrigCnt, retrigVol;
 	uint8_t volKolVol, tonNr, envPPos, eVibPos, envVPos, realVol, oldVol, outVol;
 	uint8_t oldPan, outPan, finalPan;
-	int16_t midiPitch, envVIPValue, envPIPValue;
+	int16_t midiPitch;
 	uint16_t outPeriod, realPeriod, finalPeriod, tonTyp, wantPeriod, portaSpeed;
-	uint16_t envVCnt, envVAmp, envPCnt, envPAmp, eVibAmp, eVibSweep;
+	uint16_t envVCnt, envPCnt, eVibAmp, eVibSweep;
 	uint16_t fadeOutAmp, fadeOutSpeed, midiVibDepth;
-	float fFinalVol;
-	int32_t smpStartPos;
+	double dEnvVIPValue, dEnvPIPValue, dEnvVAmp, dEnvPAmp, dFinalVol;
+	int32_t oldFinalPeriod, smpStartPos;
 	sampleTyp *smpPtr;
-	instrTyp *instrSeg;
+	instrTyp *instrPtr;
 } stmTyp;
 
 typedef struct songTyp_t
@@ -241,7 +240,7 @@
 	uint8_t status, sampleNr, instrNr;
 	uint16_t finalPeriod;
 	int32_t smpStartPos;
-	float fFinalVol;
+	double dFinalVol;
 } syncedChannel_t;
 
 void setNewSongPos(int32_t pos);
--- a/src/ft2_sample_ed.c
+++ b/src/ft2_sample_ed.c
@@ -27,6 +27,7 @@
 #include "ft2_diskop.h"
 #include "ft2_keyboard.h"
 #include "ft2_structs.h"
+#include "mixer/ft2_windowed_sinc.h" // SINC_TAPS, SINC_NEGATIVE_TAPS
 
 static const char sharpNote1Char[12] = { 'C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B' };
 static const char sharpNote2Char[12] = { '-', '#', '-', '#', '-', '-', '#', '-', '#', '-', '#', '-' };
@@ -57,6 +58,9 @@
 // modifies samples before index 0, and after loop/end (for branchless mixer interpolation (kinda))
 void fixSample(sampleTyp *s)
 {
+	int32_t pos;
+	bool backwards;
+
 	assert(s != NULL);
 	if (s->origPek == NULL || s->pek == NULL)
 	{
@@ -88,37 +92,46 @@
 		return; // empty sample
 	}
 
-	// disable loop if loopLen == 0 (FT2 does this)
-	if (loopType != 0 && loopLen == 0)
+	// treat loop as disabled if loopLen == 0 (FT2 does this)
+	if (loopType != 0 && loopLen <= 0)
 	{
 		loopType = 0;
 		loopStart = loopLen = loopEnd = 0;
 	}
 
-	/* The first and second tap (-1, 0) should be the same at sampling position #0
-	** (at sample trigger), until an eventual loop cycle, where the -1 tap has a
-	** special case in the mixer.
+	/* All negative taps should be equal to the first sample point when at sampling
+	** position #0 (on sample trigger), until an eventual loop cycle, where we do
+	** a special left edge case with replaced tap data.
+	** The sample pointer is offset and has allocated data before it, so this is
+	** safe.
 	*/
 	if (sample16Bit)
-		ptr16[-1] = ptr16[0];
+	{
+		for (int32_t i = 0; i < SINC_LEFT_TAPS; i++)
+			ptr16[i-SINC_LEFT_TAPS] = ptr16[0];
+	}
 	else
-		s->pek[-1] = s->pek[0];
+	{
+		for (int32_t i = 0; i < SINC_LEFT_TAPS; i++)
+			s->pek[i-SINC_LEFT_TAPS] = s->pek[0];
+	}
 
+	// no loop
 	if (loopType == 0)
 	{
-		// no loop
 		if (sample16Bit)
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
 				ptr16[len+i] = ptr16[len-1];
 		}
 		else
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
 				s->pek[len+i] = s->pek[len-1];
 		}
 
-		s->fixedPos = 0;
+		s->fixedPos = 0; // this value is not used for non-looping samples, set to zero
+
 		s->fixed = false; // no fixed samples inside actual sample data
 		return;
 	}
@@ -126,13 +139,18 @@
 	if (s->fixed)
 		return; // already fixed
 
-	s->fixedPos = loopStart + loopLen;
+	s->fixedPos = loopEnd;
+	s->fixed = true;
 
-	if (loopLen == 1) // too short for interpolation kernel size, fix in a different way
+	// special-case for loop-lengt of 1
+	if (loopLen == 1)
 	{
 		if (sample16Bit)
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			for (int32_t i = 0; i < SINC_TAPS+SINC_LEFT_TAPS; i++)
+				s->dLeftEdgeTapSamples[i] = ptr16[loopStart];
+
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
 			{
 				s->fixedSmp[i] = ptr16[loopEnd+i];
 				ptr16[loopEnd+i] = ptr16[loopStart];
@@ -140,7 +158,10 @@
 		}
 		else
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			for (int32_t i = 0; i < SINC_TAPS+SINC_LEFT_TAPS; i++)
+				s->dLeftEdgeTapSamples[i] = s->pek[loopStart];
+
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
 			{
 				s->fixedSmp[i] = s->pek[loopEnd+i];
 				s->pek[loopEnd+i] = s->pek[loopStart];
@@ -147,7 +168,6 @@
 			}
 		}
 
-		s->fixed = true;
 		return;
 	}
 
@@ -156,18 +176,54 @@
 		// forward loop
 		if (sample16Bit)
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			// left edge (we need SINC_LEFT_TAPS amount of extra unrolled samples)
+			for (int32_t i = 0; i < SINC_TAPS+SINC_LEFT_TAPS; i++)
 			{
+				if (i < SINC_LEFT_TAPS) // negative taps
+				{
+					pos = loopEnd-i;
+					if (pos <= loopStart) // XXX: Correct?
+						pos += loopLen;
+				}
+				else // positive taps
+				{
+					pos = loopStart + ((i-SINC_LEFT_TAPS) % loopLen);
+				}
+
+				s->dLeftEdgeTapSamples[i] = ptr16[pos];
+			}
+
+			// right edge (change actual sample data since data after loop is never used)
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
+			{
 				s->fixedSmp[i] = ptr16[loopEnd+i];
-				ptr16[loopEnd+i] = ptr16[loopStart+i];
+				ptr16[loopEnd+i] = ptr16[loopStart + (i % loopLen)];
 			}
 		}
 		else
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			// left edge (we need SINC_LEFT_TAPS amount of extra unrolled samples)
+			for (int32_t i = 0; i < SINC_TAPS+SINC_LEFT_TAPS; i++)
 			{
+				if (i < SINC_LEFT_TAPS) // negative taps
+				{
+					pos = loopEnd-i;
+					if (pos <= loopStart) // XXX: Correct?
+						pos += loopLen;
+				}
+				else // positive taps
+				{
+					pos = loopStart + ((i-SINC_LEFT_TAPS) % loopLen);
+				}
+
+				s->dLeftEdgeTapSamples[i] = s->pek[pos];
+			}
+
+			// right edge (change actual sample data since data after loop is never used)
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
+			{
 				s->fixedSmp[i] = s->pek[loopEnd+i];
-				s->pek[loopEnd+i] = s->pek[loopStart+i];
+				s->pek[loopEnd+i] = s->pek[loopStart + (i % loopLen)];
 			}
 		}
 	}
@@ -176,25 +232,159 @@
 		// pingpong loop
 		if (sample16Bit)
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			// left edge (we need SINC_LEFT_TAPS amount of extra unrolled samples)
+			pos = loopStart;
+			backwards = false;
+			for (int32_t i = 0; i < SINC_LEFT_TAPS; i++)
 			{
+				if (backwards)
+				{
+					if (--pos < loopStart)
+					{
+						pos = loopStart;
+						backwards = false;
+					}
+				}
+				else
+				{
+					if (++pos >= loopEnd)
+					{
+						pos = loopEnd-1;
+						backwards = true;
+					}
+				}
+
+				s->dLeftEdgeTapSamples[3-i] = ptr16[pos];
+			}
+
+			pos = loopStart;
+			backwards = true;
+			for (int32_t i = 3; i < SINC_TAPS+SINC_LEFT_TAPS; i++)
+			{
+				if (backwards)
+				{
+					if (--pos < loopStart)
+					{
+						pos = loopStart;
+						backwards = false;
+					}
+				}
+				else
+				{
+					if (++pos >= loopEnd)
+					{
+						pos = loopEnd-1;
+						backwards = true;
+					}
+				}
+				
+				s->dLeftEdgeTapSamples[i] = ptr16[pos];
+			}
+
+			// right edge (change actual sample data since data after loop is never used)
+			pos = loopEnd-1;
+			backwards = true;
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
+			{
 				s->fixedSmp[i] = ptr16[loopEnd+i];
-				ptr16[loopEnd+i] = ptr16[loopEnd-1-i];
+
+				ptr16[loopEnd+i] = ptr16[pos];
+				if (backwards)
+				{
+					if (--pos < loopStart)
+					{
+						pos = loopStart;
+						backwards = false;
+					}
+				}
+				else
+				{
+					if (++pos >= loopEnd)
+					{
+						pos = loopEnd-1;
+						backwards = true;
+					}
+				}
 			}
 		}
 		else
 		{
-			for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+			// left edge (we need SINC_LEFT_TAPS amount of extra unrolled samples)
+			pos = loopStart;
+			backwards = false;
+			for (int32_t i = 0; i < SINC_LEFT_TAPS; i++)
 			{
+				if (backwards)
+				{
+					if (--pos < loopStart)
+					{
+						pos = loopStart;
+						backwards = false;
+					}
+				}
+				else
+				{
+					if (++pos >= loopEnd)
+					{
+						pos = loopEnd-1;
+						backwards = true;
+					}
+				}
+
+				s->dLeftEdgeTapSamples[3-i] = s->pek[pos];
+			}
+
+			pos = loopStart;
+			backwards = true;
+			for (int32_t i = 3; i < SINC_TAPS+SINC_LEFT_TAPS; i++)
+			{
+				if (backwards)
+				{
+					if (--pos < loopStart)
+					{
+						pos = loopStart;
+						backwards = false;
+					}
+				}
+				else
+				{
+					if (++pos >= loopEnd)
+					{
+						pos = loopEnd-1;
+						backwards = true;
+					}
+				}
+				
+				s->dLeftEdgeTapSamples[i] = s->pek[pos];
+			}
+
+			// right edge (change actual sample data since data after loop is never used)
+			pos = loopEnd-1;
+			backwards = true;
+			for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
+			{
 				s->fixedSmp[i] = s->pek[loopEnd+i];
-				s->pek[loopEnd+i] = s->pek[loopEnd-1-i];
+
+				s->pek[loopEnd+i] = s->pek[pos];
+				if (backwards)
+				{
+					if (--pos < loopStart)
+					{
+						pos = loopStart;
+						backwards = false;
+					}
+				}
+				else
+				{
+					if (++pos >= loopEnd)
+					{
+						pos = loopEnd-1;
+						backwards = true;
+					}
+				}
 			}
 		}
 	}
-
-	// -1 tap (right before loopStart) on forward/pingpong loops are handled in the mixer
-
-	s->fixed = true;
 }
 
 // restores interpolation tap samples after loop/end
@@ -208,7 +398,7 @@
 	{
 		// 16-bit sample
 		int16_t *ptr16 = (int16_t *)s->pek + s->fixedPos;
-		for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+		for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
 			ptr16[i] = s->fixedSmp[i];
 	}
 	else
@@ -215,7 +405,7 @@
 	{
 		// 8-bit sample
 		int8_t *ptr8 = s->pek + s->fixedPos;
-		for (int32_t i = 0; i < NUM_FIXED_TAP_SAMPLES; i++)
+		for (int32_t i = 0; i < SINC_RIGHT_TAPS; i++)
 			ptr8[i] = (int8_t)s->fixedSmp[i];
 	}
 
@@ -594,7 +784,7 @@
 		ptr16 = (int16_t *)s->pek;
 
 		// don't read fixed mixer interpolation samples, read the prestine ones instead
-		if (index >= s->fixedPos && index < s->fixedPos+NUM_FIXED_TAP_SAMPLES && s->len > loopEnd && s->fixed)
+		if (index >= s->fixedPos && index < s->fixedPos+SINC_RIGHT_TAPS && s->len > loopEnd && s->fixed)
 			tmp32 = s->fixedSmp[index-s->fixedPos];
 		else
 			tmp32 = ptr16[index];
@@ -604,7 +794,7 @@
 	else
 	{
 		// don't read fixed mixer interpolation samples, read the prestine ones instead
-		if (index >= s->fixedPos && index < s->fixedPos+NUM_FIXED_TAP_SAMPLES && s->len > loopEnd && s->fixed)
+		if (index >= s->fixedPos && index < s->fixedPos+SINC_RIGHT_TAPS && s->len > loopEnd && s->fixed)
 			tmp32 = s->fixedSmp[index-s->fixedPos];
 		else
 			tmp32 = s->pek[index];
@@ -897,7 +1087,7 @@
 	}
 
 	// read fixed samples
-	int32_t tmpScanEnd = index+NUM_FIXED_TAP_SAMPLES;
+	int32_t tmpScanEnd = index+SINC_RIGHT_TAPS;
 	if (tmpScanEnd > scanEnd)
 		tmpScanEnd = scanEnd;
 
@@ -939,7 +1129,7 @@
 	}
 
 	// read fixed samples
-	int32_t tmpScanEnd = index+NUM_FIXED_TAP_SAMPLES;
+	int32_t tmpScanEnd = index+SINC_RIGHT_TAPS;
 	if (tmpScanEnd > scanEnd)
 		tmpScanEnd = scanEnd;
 
@@ -989,7 +1179,7 @@
 		/* If the scan area is including the fixed samples (for branchless mixer interpolation),
 		** do a special procedure to scan the original non-touched samples when needed.
 		*/
-		const bool insideRange = index >= s->fixedPos && index < s->fixedPos+NUM_FIXED_TAP_SAMPLES;
+		const bool insideRange = index >= s->fixedPos && index < s->fixedPos+SINC_RIGHT_TAPS;
 		if (insideRange || (index < s->fixedPos && scanEnd >= s->fixedPos))
 		{
 			if (s->typ & 16)
--- a/src/ft2_sample_saver.c
+++ b/src/ft2_sample_saver.c
@@ -70,7 +70,7 @@
 	if (fixedPos >= (uint32_t)s->len)
 		return;
 
-	uint32_t bytesToWrite = NUM_FIXED_TAP_SAMPLES * (sample16Bit+1);
+	uint32_t bytesToWrite = SINC_RIGHT_TAPS * (sample16Bit+1);
 	if (fixedPos+bytesToWrite > (uint32_t)s->len)
 		bytesToWrite = s->len - fixedPos;
 
--- a/src/ft2_scopes.c
+++ b/src/ft2_scopes.c
@@ -99,7 +99,7 @@
 		ch->realVol = 0;
 		ch->outVol = 0;
 		ch->oldVol = 0;
-		ch->fFinalVol = 0.0f;
+		ch->dFinalVol = 0.0;
 		ch->outPan = 128;
 		ch->oldPan = 128;
 		ch->finalPan = 128;
@@ -533,7 +533,7 @@
 		status = scopeUpdateStatus[i];
 
 		if (status & IS_Vol)
-			sc->vol = (int32_t)((ch->fFinalVol * SCOPE_HEIGHT) + 0.5f); // rounded
+			sc->vol = (int32_t)((ch->dFinalVol * SCOPE_HEIGHT) + 0.5); // rounded
 
 		if (status & IS_Period)
 		{
--- a/src/ft2_trim.c
+++ b/src/ft2_trim.c
@@ -256,7 +256,7 @@
 	memcpy(tmpInst, &instr[1], MAX_INST * sizeof (instr[0]));
 
 	memset(&instr[1], 0, numInsts * sizeof (instr[0]));
-	memset(song.instrName[1], 0, numInsts * sizeof (song.instrName[0]));
+	memset(song.instrName[1], 0, numInsts * sizeof (song.instrName[0])); // XXX: Is this safe?
 
 	for (i = 0; i < numInsts; i++)
 	{
--- a/src/helpdata/FT2.HLP
+++ b/src/helpdata/FT2.HLP
@@ -785,7 +785,7 @@
 Selects what type of resampling interpolation to use.
 "None" uses no interpolation (nearest neighbor), which will result in
 aliasing (noise) in the sound. "Linear" is what real FT2 uses, which is a
-mediocre interpolation type. "Cubic spline" is the recommended setting
+mediocre interpolation type. "Windowed-sinc" is the recommended setting
 for the best audio quality, although it may sometimes sound too filtered
 on low-quality samples (f.ex. Amiga MODs).
 
--- a/src/helpdata/ft2_help_data.h
+++ b/src/helpdata/ft2_help_data.h
@@ -3,9 +3,9 @@
 
 #include <stdint.h>
 
-#define HELP_DATA_LEN 26983
+#define HELP_DATA_LEN 26984
 
-const uint8_t helpData[26983] =
+const uint8_t helpData[26984] =
 {
 	0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
@@ -1793,469 +1793,469 @@
 	0x20,0x22,0x4C,0x69,0x6E,0x65,0x61,0x72,0x22,0x20,0x69,0x73,
 	0x20,0x77,0x68,0x61,0x74,0x20,0x72,0x65,0x61,0x6C,0x20,0x46,
 	0x54,0x32,0x20,0x75,0x73,0x65,0x73,0x2C,0x20,0x77,0x68,0x69,
-	0x63,0x68,0x20,0x69,0x73,0x20,0x61,0x46,0x6D,0x65,0x64,0x69,
+	0x63,0x68,0x20,0x69,0x73,0x20,0x61,0x47,0x6D,0x65,0x64,0x69,
 	0x6F,0x63,0x72,0x65,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,
 	0x6C,0x61,0x74,0x69,0x6F,0x6E,0x20,0x74,0x79,0x70,0x65,0x2E,
-	0x20,0x22,0x43,0x75,0x62,0x69,0x63,0x20,0x73,0x70,0x6C,0x69,
-	0x6E,0x65,0x22,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x72,
-	0x65,0x63,0x6F,0x6D,0x6D,0x65,0x6E,0x64,0x65,0x64,0x20,0x73,
-	0x65,0x74,0x74,0x69,0x6E,0x67,0x48,0x66,0x6F,0x72,0x20,0x74,
-	0x68,0x65,0x20,0x62,0x65,0x73,0x74,0x20,0x61,0x75,0x64,0x69,
-	0x6F,0x20,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,0x2C,0x20,0x61,
-	0x6C,0x74,0x68,0x6F,0x75,0x67,0x68,0x20,0x69,0x74,0x20,0x6D,
-	0x61,0x79,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,0x73,
-	0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,0x74,0x6F,0x6F,0x20,0x66,
-	0x69,0x6C,0x74,0x65,0x72,0x65,0x64,0x2A,0x6F,0x6E,0x20,0x6C,
-	0x6F,0x77,0x2D,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,0x20,0x73,
-	0x61,0x6D,0x70,0x6C,0x65,0x73,0x20,0x28,0x66,0x2E,0x65,0x78,
-	0x2E,0x20,0x41,0x6D,0x69,0x67,0x61,0x20,0x4D,0x4F,0x44,0x73,
-	0x29,0x2E,0x00,0x1A,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,
-	0x30,0x30,0x31,0x56,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x72,0x61,
-	0x6D,0x70,0x69,0x6E,0x67,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,
-	0x30,0x40,0x43,0x30,0x30,0x32,0x3B,0x45,0x6E,0x61,0x62,0x6C,
-	0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x61,0x6E,0x74,0x69,0x2D,
-	0x63,0x6C,0x69,0x63,0x6B,0x20,0x73,0x79,0x73,0x74,0x65,0x6D,
-	0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x61,0x75,0x64,0x69,
-	0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,0x20,0x28,0x46,0x54,0x32,
-	0x2E,0x30,0x38,0x2B,0x29,0x2E,0x3B,0x50,0x6C,0x65,0x61,0x73,
-	0x65,0x20,0x6E,0x6F,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,
-	0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x20,0x46,0x54,0x32,
-	0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6C,0x6F,0x61,0x64,0x20,
-	0x74,0x68,0x69,0x73,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x20,
-	0x65,0x6E,0x74,0x72,0x79,0x2C,0x0B,0x63,0x6C,0x6F,0x6E,0x65,
-	0x20,0x6F,0x6E,0x6C,0x79,0x2E,0x00,0x19,0x3E,0x40,0x58,0x30,
-	0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x41,0x6D,0x70,0x6C,0x69,
-	0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x3A,0x0B,0x3E,0x40,
-	0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x46,0x41,0x6D,
-	0x70,0x6C,0x69,0x66,0x69,0x65,0x73,0x20,0x74,0x68,0x65,0x20,
-	0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x77,0x68,0x65,0x6E,0x20,
-	0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,0x20,0x49,0x66,0x20,0x79,
-	0x6F,0x75,0x20,0x73,0x65,0x74,0x20,0x74,0x68,0x69,0x73,0x20,
-	0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,0x20,0x68,0x69,0x67,0x68,
-	0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,0x6C,0x3A,0x67,0x65,0x74,
-	0x20,0x64,0x69,0x73,0x74,0x6F,0x72,0x74,0x69,0x6F,0x6E,0x2E,
-	0x20,0x33,0x32,0x58,0x20,0x65,0x71,0x75,0x61,0x6C,0x73,0x20,
-	0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,0x70,0x6C,0x69,0x74,0x75,
-	0x64,0x65,0x20,0x66,0x6F,0x72,0x20,0x6F,0x6E,0x65,0x20,0x63,
-	0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,0x00,0x1B,0x3E,0x40,0x58,
-	0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x46,0x72,0x65,0x71,
-	0x75,0x65,0x6E,0x63,0x79,0x20,0x74,0x61,0x62,0x6C,0x65,0x3A,
-	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
-	0x40,0x54,0x68,0x65,0x20,0x6C,0x69,0x6E,0x65,0x61,0x72,0x20,
-	0x66,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x74,0x61,
-	0x62,0x6C,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,0x61,0x6C,
-	0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x62,0x65,0x6E,0x64,
-	0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x63,0x6F,0x6E,
-	0x73,0x74,0x61,0x6E,0x74,0x3F,0x73,0x70,0x65,0x65,0x64,0x2C,
-	0x20,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,0x64,0x65,0x6E,0x74,
-	0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x72,
-	0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,
-	0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x77,
-	0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,0x73,0x41,0x6F,0x6E,
-	0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,0x66,0x69,0x6E,0x69,
-	0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,0x67,0x2C,0x20,0x69,
-	0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,0x73,0x6F,0x75,0x6E,
-	0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,0x65,0x20,0x69,0x66,
-	0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,0x75,
-	0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,0x6D,0x65,0x6E,
-	0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,0x30,0x32,0x30,
-	0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,
-	0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,0x61,0x79,0x6F,
-	0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,0x30,0x34,0x30,
-	0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,0x65,0x72,0x6E,
-	0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,0x68,0x65,0x78,
-	0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,0x67,0x3A,0x0B,
-	0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x41,
-	0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,0x65,0x20,0x70,
-	0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,0x68,0x61,0x74,
-	0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,0x65,0x72,0x20,
-	0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,0x69,0x6E,0x65,
-	0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,0x6F,0x75,0x6C,
-	0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,0x20,0x63,0x6F,
-	0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,0x6E,0x63,0x65,
-	0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x6F,
-	0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,0x69,0x74,0x73,
-	0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,0x69,0x6E,0x65,
-	0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,0x6F,0x6C,0x75,
-	0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,
-	0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,0x73,0x3A,0x0B,
-	0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x43,
-	0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,0x74,0x61,0x6E,
-	0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,0x6C,0x20,0x73,
-	0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,0x70,
-	0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x20,0x61,0x73,
-	0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,0x6C,0x69,0x6B,
-	0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x41,0x22,0x4C,0x69,0x6E,
-	0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,0x64,0x72,0x61,
-	0x77,0x20,0x6C,0x69,0x6E,0x65,0x73,0x20,0x62,0x65,0x74,0x77,
-	0x65,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x6F,0x69,0x6E,
-	0x74,0x73,0x2C,0x20,0x6C,0x69,0x6B,0x65,0x20,0x61,0x6E,0x20,
-	0x6F,0x73,0x63,0x69,0x6C,0x6C,0x6F,0x73,0x63,0x6F,0x70,0x65,
-	0x2E,0x00,0x27,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,
-	0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,
-	0x6F,0x6E,0x2C,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,
-	0x6E,0x65,0x6F,0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,0x58,
-	0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,0x6E,
-	0x63,0x20,0x6F,0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,
-	0x30,0x40,0x43,0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,0x73,
-	0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,
-	0x20,0x74,0x6F,0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,0x20,
-	0x56,0x53,0x79,0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,0x69,
-	0x64,0x65,0x6F,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x72,
-	0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,0x72,
-	0x65,0x66,0x72,0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,
-	0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,
-	0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,0x74,
-	0x68,0x65,0x6E,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,0x73,
-	0x20,0x61,0x6C,0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,0x20,
-	0x66,0x6F,0x72,0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,
-	0x67,0x72,0x61,0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,0x61,
-	0x76,0x69,0x6E,0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,
-	0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,
-	0x6E,0x20,0x6C,0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,0x74,
-	0x2F,0x76,0x69,0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,0x79,
-	0x2C,0x1E,0x62,0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,0x70,
-	0x6F,0x74,0x65,0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,0x75,
-	0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x2E,0x01,0x20,0x18,0x3E,
-	0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x69,
-	0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x3A,0x0B,
-	0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x43,
-	0x41,0x70,0x70,0x6C,0x69,0x65,0x73,0x20,0x61,0x20,0x73,0x75,
-	0x62,0x70,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,
-	0x72,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x73,0x20,0x75,0x73,
-	0x65,0x64,0x20,0x77,0x68,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,
-	0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,0x69,0x73,0x20,0x75,0x70,
-	0x73,0x63,0x61,0x6C,0x65,0x64,0x2E,0x43,0x54,0x68,0x69,0x73,
-	0x20,0x61,0x6C,0x73,0x6F,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,
-	0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,
-	0x6F,0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,
-	0x6C,0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,
-	0x75,0x74,0x20,0x69,0x66,0x20,0x69,0x74,0x20,0x64,0x69,0x64,
-	0x6E,0x27,0x74,0x44,0x61,0x6C,0x72,0x65,0x61,0x64,0x79,0x2E,
-	0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6B,0x65,0x65,0x70,
-	0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20,0x74,0x68,0x61,
-	0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,
-	0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,
-	0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x2E,
-	0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,
-	0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64,0x20,0x65,0x64,0x69,
-	0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x3A,
-	0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,
-	0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F,0x50,0x61,0x73,0x74,
-	0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x3A,0x0B,0x3E,
-	0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x37,0x54,
-	0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x20,0x69,
-	0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66,0x6F,0x72,0x20,0x63,
-	0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70,0x61,0x73,0x74,0x69,
-	0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x70,0x61,0x72,0x74,
-	0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22,0x6E,0x6F,0x74,0x65,
-	0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20,0x54,0x68,0x65,0x20,
-	0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x70,0x61,
-	0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x20,0x22,0x6E,0x6F,
-	0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x20,0x69,0x73,0x20,
-	0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E,0x73,0x74,0x72,0x2E,
-	0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F,0x6C,0x75,0x6D,0x65,
-	0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,0x6E,0x72,0x20,
-	0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,0x64,0x61,0x74,
-	0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79,0x6F,0x75,0x20,0x63,
-	0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69,0x6E,0x20,0x74,0x68,
-	0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,0x74,0x68,0x65,
-	0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33,0x20,0x63,0x6F,0x6C,
-	0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D,0x22,0x65,0x6E,0x61,
-	0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x20,
-	0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22,0x20,0x77,0x68,0x69,
-	0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74,0x68,0x65,0x20,0x6C,
-	0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43,0x2C,0x50,0x20,0x26,
-	0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,0x45,0x3E,0x43,
-	0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63,0x6F,0x70,0x79,0x2C,
-	0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,
+	0x20,0x22,0x57,0x69,0x6E,0x64,0x6F,0x77,0x65,0x64,0x2D,0x73,
+	0x69,0x6E,0x63,0x22,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,
+	0x72,0x65,0x63,0x6F,0x6D,0x6D,0x65,0x6E,0x64,0x65,0x64,0x20,
+	0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x48,0x66,0x6F,0x72,0x20,
+	0x74,0x68,0x65,0x20,0x62,0x65,0x73,0x74,0x20,0x61,0x75,0x64,
+	0x69,0x6F,0x20,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,0x2C,0x20,
+	0x61,0x6C,0x74,0x68,0x6F,0x75,0x67,0x68,0x20,0x69,0x74,0x20,
+	0x6D,0x61,0x79,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,
+	0x73,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,0x74,0x6F,0x6F,0x20,
+	0x66,0x69,0x6C,0x74,0x65,0x72,0x65,0x64,0x2A,0x6F,0x6E,0x20,
+	0x6C,0x6F,0x77,0x2D,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,0x20,
+	0x73,0x61,0x6D,0x70,0x6C,0x65,0x73,0x20,0x28,0x66,0x2E,0x65,
+	0x78,0x2E,0x20,0x41,0x6D,0x69,0x67,0x61,0x20,0x4D,0x4F,0x44,
+	0x73,0x29,0x2E,0x00,0x1A,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,
+	0x43,0x30,0x30,0x31,0x56,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x72,
+	0x61,0x6D,0x70,0x69,0x6E,0x67,0x3A,0x0B,0x3E,0x40,0x58,0x30,
+	0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3B,0x45,0x6E,0x61,0x62,
+	0x6C,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x61,0x6E,0x74,0x69,
+	0x2D,0x63,0x6C,0x69,0x63,0x6B,0x20,0x73,0x79,0x73,0x74,0x65,
+	0x6D,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x61,0x75,0x64,
+	0x69,0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,0x20,0x28,0x46,0x54,
+	0x32,0x2E,0x30,0x38,0x2B,0x29,0x2E,0x3B,0x50,0x6C,0x65,0x61,
+	0x73,0x65,0x20,0x6E,0x6F,0x74,0x65,0x20,0x74,0x68,0x61,0x74,
+	0x20,0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x20,0x46,0x54,
+	0x32,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6C,0x6F,0x61,0x64,
+	0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,
+	0x20,0x65,0x6E,0x74,0x72,0x79,0x2C,0x0B,0x63,0x6C,0x6F,0x6E,
+	0x65,0x20,0x6F,0x6E,0x6C,0x79,0x2E,0x00,0x19,0x3E,0x40,0x58,
+	0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x41,0x6D,0x70,0x6C,
+	0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x3A,0x0B,0x3E,
+	0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x46,0x41,
+	0x6D,0x70,0x6C,0x69,0x66,0x69,0x65,0x73,0x20,0x74,0x68,0x65,
+	0x20,0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x77,0x68,0x65,0x6E,
+	0x20,0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,0x20,0x49,0x66,0x20,
+	0x79,0x6F,0x75,0x20,0x73,0x65,0x74,0x20,0x74,0x68,0x69,0x73,
+	0x20,0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,0x20,0x68,0x69,0x67,
+	0x68,0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,0x6C,0x3A,0x67,0x65,
+	0x74,0x20,0x64,0x69,0x73,0x74,0x6F,0x72,0x74,0x69,0x6F,0x6E,
+	0x2E,0x20,0x33,0x32,0x58,0x20,0x65,0x71,0x75,0x61,0x6C,0x73,
+	0x20,0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,0x70,0x6C,0x69,0x74,
+	0x75,0x64,0x65,0x20,0x66,0x6F,0x72,0x20,0x6F,0x6E,0x65,0x20,
+	0x63,0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,0x00,0x1B,0x3E,0x40,
+	0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x46,0x72,0x65,
+	0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x74,0x61,0x62,0x6C,0x65,
+	0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,
+	0x32,0x40,0x54,0x68,0x65,0x20,0x6C,0x69,0x6E,0x65,0x61,0x72,
+	0x20,0x66,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x74,
+	0x61,0x62,0x6C,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,0x61,
+	0x6C,0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x62,0x65,0x6E,
+	0x64,0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x63,0x6F,
+	0x6E,0x73,0x74,0x61,0x6E,0x74,0x3F,0x73,0x70,0x65,0x65,0x64,
+	0x2C,0x20,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,0x64,0x65,0x6E,
+	0x74,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,
+	0x72,0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,0x75,0x65,0x6E,
+	0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x73,
+	0x77,0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,0x73,0x41,0x6F,
+	0x6E,0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,0x66,0x69,0x6E,
+	0x69,0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,0x67,0x2C,0x20,
+	0x69,0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,0x73,0x6F,0x75,
+	0x6E,0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,0x65,0x20,0x69,
+	0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,
+	0x75,0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,0x6D,0x65,
+	0x6E,0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,0x30,0x32,
+	0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,
+	0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,0x61,0x79,
+	0x6F,0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,0x30,0x34,
+	0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,0x65,0x72,
+	0x6E,0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,0x68,0x65,
+	0x78,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,0x67,0x3A,
+	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
+	0x41,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,0x65,0x20,
+	0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,0x68,0x61,
+	0x74,0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,0x65,0x72,
+	0x20,0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,0x69,0x6E,
+	0x65,0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,0x6F,0x75,
+	0x6C,0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,0x20,0x63,
+	0x6F,0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,0x6E,0x63,
+	0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,
+	0x6F,0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,0x69,0x74,
+	0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,0x69,0x6E,
+	0x65,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,0x6F,0x6C,
+	0x75,0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,0x34,0x30,
+	0x40,0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,0x73,0x3A,
+	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
+	0x43,0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,0x74,0x61,
+	0x6E,0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,0x6C,0x20,
+	0x73,0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,
+	0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x20,0x61,
+	0x73,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,0x6C,0x69,
+	0x6B,0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x41,0x22,0x4C,0x69,
+	0x6E,0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,0x64,0x72,
+	0x61,0x77,0x20,0x6C,0x69,0x6E,0x65,0x73,0x20,0x62,0x65,0x74,
+	0x77,0x65,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x6F,0x69,
+	0x6E,0x74,0x73,0x2C,0x20,0x6C,0x69,0x6B,0x65,0x20,0x61,0x6E,
+	0x20,0x6F,0x73,0x63,0x69,0x6C,0x6C,0x6F,0x73,0x63,0x6F,0x70,
+	0x65,0x2E,0x00,0x27,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,
+	0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,
+	0x69,0x6F,0x6E,0x2C,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,
+	0x61,0x6E,0x65,0x6F,0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,
+	0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,
+	0x6E,0x63,0x20,0x6F,0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,
+	0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,
+	0x73,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,
+	0x6D,0x20,0x74,0x6F,0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,
+	0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,
+	0x69,0x64,0x65,0x6F,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,
+	0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,
+	0x72,0x65,0x66,0x72,0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,
+	0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,
+	0x20,0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,
+	0x74,0x68,0x65,0x6E,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,
+	0x73,0x20,0x61,0x6C,0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,
+	0x20,0x66,0x6F,0x72,0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,
+	0x6F,0x67,0x72,0x61,0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,
+	0x61,0x76,0x69,0x6E,0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,
+	0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,
+	0x69,0x6E,0x20,0x6C,0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,
+	0x74,0x2F,0x76,0x69,0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,
+	0x79,0x2C,0x1E,0x62,0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,
+	0x70,0x6F,0x74,0x65,0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,
+	0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x2E,0x01,0x20,0x18,
+	0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x50,
+	0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x3A,
+	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
+	0x43,0x41,0x70,0x70,0x6C,0x69,0x65,0x73,0x20,0x61,0x20,0x73,
+	0x75,0x62,0x70,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,
+	0x65,0x72,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x73,0x20,0x75,
+	0x73,0x65,0x64,0x20,0x77,0x68,0x65,0x6E,0x20,0x74,0x68,0x65,
+	0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,0x69,0x73,0x20,0x75,
+	0x70,0x73,0x63,0x61,0x6C,0x65,0x64,0x2E,0x43,0x54,0x68,0x69,
+	0x73,0x20,0x61,0x6C,0x73,0x6F,0x20,0x6D,0x61,0x6B,0x65,0x73,
+	0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,
+	0x6D,0x6F,0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,
+	0x65,0x6C,0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,
+	0x6F,0x75,0x74,0x20,0x69,0x66,0x20,0x69,0x74,0x20,0x64,0x69,
+	0x64,0x6E,0x27,0x74,0x44,0x61,0x6C,0x72,0x65,0x61,0x64,0x79,
+	0x2E,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6B,0x65,0x65,
+	0x70,0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20,0x74,0x68,
+	0x61,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,0x6C,0x6C,
+	0x20,0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,
+	0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,
+	0x2E,0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,
+	0x31,0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64,0x20,0x65,0x64,
+	0x69,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,
+	0x3A,0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,
+	0x43,0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F,0x50,0x61,0x73,
+	0x74,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x3A,0x0B,
+	0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x37,
+	0x54,0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x20,
+	0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66,0x6F,0x72,0x20,
+	0x63,0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70,0x61,0x73,0x74,
+	0x69,0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x70,0x61,0x72,
+	0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22,0x6E,0x6F,0x74,
+	0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20,0x54,0x68,0x65,
+	0x20,0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x70,
+	0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x20,0x22,0x6E,
+	0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x20,0x69,0x73,
+	0x20,0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E,0x73,0x74,0x72,
+	0x2E,0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F,0x6C,0x75,0x6D,
+	0x65,0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,0x6E,0x72,
+	0x20,0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,0x64,0x61,
+	0x74,0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79,0x6F,0x75,0x20,
+	0x63,0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69,0x6E,0x20,0x74,
+	0x68,0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,0x74,0x68,
+	0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33,0x20,0x63,0x6F,
+	0x6C,0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D,0x22,0x65,0x6E,
+	0x61,0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,
+	0x20,0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22,0x20,0x77,0x68,
+	0x69,0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74,0x68,0x65,0x20,
+	0x6C,0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43,0x2C,0x50,0x20,
+	0x26,0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,0x45,0x3E,
+	0x43,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63,0x6F,0x70,0x79,
+	0x2C,0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,
+	0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,0x74,
+	0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,
+	0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,
+	0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E,0x3E,0x50,0x20,
+	0x6D,0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73,0x74,0x65,0x20,
+	0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,
 	0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,0x74,0x73,
-	0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x69,
-	0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,
-	0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E,0x3E,0x50,0x20,0x6D,
-	0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73,0x74,0x65,0x20,0x61,
-	0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,0x20,
-	0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,0x74,0x73,0x20,
-	0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x6F,0x75,
-	0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74,0x68,0x65,0x0B,0x63,
-	0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x45,0x3E,
-	0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x74,0x72,0x61,0x6E,
-	0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,
-	0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,
-	0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x73,0x74,0x69,
-	0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E,0x27,0x74,0x20,0x6F,
-	0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65,0x3D,0x64,0x61,0x74,
-	0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E,0x69,0x6C,0x2D,0x69,
-	0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,
-	0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,
-	0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20,0x61,0x20,0x6E,0x75,
-	0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20,0x30,0x2E,0x01,0x3E,
-	0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75,0x74,0x20,0x66,0x75,
-	0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20,0x77,0x6F,0x72,0x6B,
-	0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70,0x61,0x73,0x74,0x69,
-	0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20,0x7A,0x65,0x72,0x6F,
-	0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,
-	0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68,0x61,0x74,0x20,0x74,
-	0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69,0x6E,0x67,0x20,0x69,
-	0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x6C,0x65,0x64,
-	0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D,0x63,0x6F,0x6C,0x75,
-	0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54,0x2D,0x63,0x6F,0x6C,
-	0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57,0x68,0x65,0x6E,0x20,
-	0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79,0x20,0x64,0x61,0x74,
-	0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D,0x61,0x73,0x6B,0x69,
-	0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x73,0x61,
-	0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x61,
-	0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63,0x6C,0x65,0x61,0x72,
-	0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,
-	0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x20,0x28,0x4D,
-	0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74,0x20,0x70,0x6F,0x73,
-	0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F,0x20,0x63,0x6F,0x6C,
-	0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61,0x20,0x66,0x72,
-	0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x6C,
-	0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20,0x69,0x6E,0x74,
-	0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,0x62,0x75,
-	0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03,0x45,0x4E,0x44,0x4C,
-	0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x6F,
+	0x75,0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74,0x68,0x65,0x0B,
+	0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x45,
+	0x3E,0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x74,0x72,0x61,
+	0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,
+	0x66,0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E,0x61,0x62,0x6C,
+	0x65,0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x73,0x74,
+	0x69,0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E,0x27,0x74,0x20,
+	0x6F,0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65,0x3D,0x64,0x61,
+	0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E,0x69,0x6C,0x2D,
+	0x69,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x2C,
+	0x20,0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74,0x68,0x20,0x61,
+	0x20,0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20,0x61,0x20,0x6E,
+	0x75,0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20,0x30,0x2E,0x01,
+	0x3E,0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75,0x74,0x20,0x66,
+	0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20,0x77,0x6F,0x72,
+	0x6B,0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70,0x61,0x73,0x74,
+	0x69,0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20,0x7A,0x65,0x72,
+	0x6F,0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54,0x68,0x69,0x73,
+	0x20,0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68,0x61,0x74,0x20,
+	0x74,0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69,0x6E,0x67,0x20,
+	0x69,0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x6C,0x65,
+	0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D,0x63,0x6F,0x6C,
+	0x75,0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54,0x2D,0x63,0x6F,
+	0x6C,0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57,0x68,0x65,0x6E,
+	0x20,0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79,0x20,0x64,0x61,
+	0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D,0x61,0x73,0x6B,
+	0x69,0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x73,
+	0x61,0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72,0x74,0x73,0x20,
+	0x61,0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63,0x6C,0x65,0x61,
+	0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,
+	0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x20,0x28,
+	0x4D,0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74,0x20,0x70,0x6F,
+	0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F,0x20,0x63,0x6F,
+	0x6C,0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61,0x20,0x66,
+	0x72,0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,
+	0x6C,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20,0x69,0x6E,
+	0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,0x62,
+	0x75,0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03,0x45,0x4E,0x44,
+	0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0E,0x40,0x4C,
-	0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x2F,0x46,0x41,0x51,
-	0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x41,0x3E,0x40,0x43,0x30,
-	0x30,0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,0x49,0x20,0x6D,
-	0x61,0x6B,0x65,0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,
-	0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x73,0x74,0x72,0x65,
-	0x74,0x63,0x68,0x20,0x6F,0x75,0x74,0x20,0x74,0x68,0x65,0x20,
-	0x77,0x68,0x6F,0x6C,0x65,0x20,0x73,0x63,0x72,0x65,0x65,0x6E,
-	0x3F,0x3A,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x45,
-	0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x50,0x69,0x78,0x65,0x6C,
-	0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x69,0x6E,0x20,
-	0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,
-	0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,
-	0x4D,0x3E,0x40,0x58,0x30,0x33,0x35,0x49,0x74,0x20,0x77,0x6F,
-	0x6E,0x27,0x74,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x70,0x72,0x65,
-	0x74,0x74,0x79,0x2C,0x20,0x62,0x75,0x74,0x20,0x74,0x6F,0x20,
-	0x73,0x6F,0x6D,0x65,0x20,0x70,0x65,0x6F,0x70,0x6C,0x65,0x20,
-	0x69,0x74,0x27,0x73,0x20,0x6D,0x75,0x63,0x68,0x20,0x62,0x65,
-	0x74,0x74,0x65,0x72,0x20,0x74,0x68,0x61,0x6E,0x20,0x6E,0x6F,
-	0x74,0x68,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,
-	0x30,0x27,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x49,
-	0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x75,0x73,0x65,0x20,0x41,
-	0x4C,0x54,0x2B,0x46,0x34,0x20,0x61,0x6E,0x64,0x20,0x41,0x4C,
-	0x54,0x2B,0x46,0x35,0x21,0x4E,0x3E,0x40,0x43,0x30,0x30,0x32,
-	0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,0x20,
-	0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x68,0x61,0x76,0x65,0x20,
-	0x47,0x65,0x46,0x6F,0x72,0x63,0x65,0x20,0x45,0x78,0x70,0x65,
-	0x72,0x69,0x65,0x6E,0x63,0x65,0x20,0x69,0x6E,0x73,0x74,0x61,
-	0x6C,0x6C,0x65,0x64,0x2C,0x20,0x79,0x6F,0x75,0x20,0x6E,0x65,
-	0x65,0x64,0x20,0x74,0x6F,0x20,0x63,0x68,0x61,0x6E,0x67,0x65,
-	0x2B,0x3E,0x40,0x58,0x30,0x33,0x35,0x74,0x68,0x65,0x20,0x6B,
-	0x65,0x79,0x62,0x69,0x6E,0x64,0x69,0x6E,0x67,0x73,0x20,0x69,
-	0x6E,0x20,0x69,0x74,0x73,0x20,0x73,0x65,0x74,0x74,0x69,0x6E,
-	0x67,0x73,0x20,0x70,0x61,0x67,0x65,0x2E,0x56,0x6D,0x61,0x63,
-	0x4F,0x53,0x2F,0x4F,0x53,0x20,0x58,0x3A,0x20,0x43,0x68,0x61,
-	0x6E,0x67,0x65,0x20,0x41,0x4C,0x54,0x2B,0x46,0x34,0x2F,0x41,
-	0x4C,0x54,0x2B,0x46,0x35,0x20,0x6B,0x65,0x79,0x73,0x20,0x69,
-	0x6E,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,0x74,0x6F,0x20,
-	0x73,0x6F,0x6D,0x65,0x74,0x68,0x69,0x6E,0x67,0x20,0x65,0x6C,
-	0x73,0x65,0x2E,0x20,0x41,0x6C,0x73,0x6F,0x20,0x66,0x6F,0x72,
-	0x20,0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,0x2E,0x06,
-	0x3E,0x40,0x58,0x30,0x32,0x30,0x2B,0x3E,0x40,0x43,0x30,0x30,
-	0x31,0x51,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,
-	0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,0x69,0x73,0x20,
-	0x64,0x65,0x6C,0x61,0x79,0x65,0x64,0x2F,0x6C,0x61,0x67,0x67,
-	0x79,0x21,0x44,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,
-	0x4D,0x61,0x6B,0x65,0x20,0x73,0x75,0x72,0x65,0x20,0x22,0x53,
-	0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x6D,0x6F,0x75,0x73,
-	0x65,0x22,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x61,0x62,0x6C,
-	0x65,0x64,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,
-	0x20,0x2D,0x3E,0x20,0x4C,0x61,0x79,0x6F,0x75,0x74,0x2E,0x4B,
-	0x3E,0x40,0x58,0x30,0x33,0x35,0x41,0x6C,0x74,0x65,0x72,0x6E,
-	0x61,0x74,0x69,0x76,0x65,0x6C,0x79,0x2C,0x20,0x79,0x6F,0x75,
-	0x20,0x63,0x61,0x6E,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,0x20,
-	0x22,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F,0x66,0x66,0x22,0x20,
-	0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,
-	0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,
-	0x75,0x73,0x2E,0x46,0x3E,0x54,0x68,0x69,0x73,0x20,0x68,0x6F,
-	0x77,0x65,0x76,0x65,0x72,0x2C,0x20,0x77,0x69,0x6C,0x6C,0x20,
-	0x69,0x6E,0x74,0x72,0x6F,0x64,0x75,0x63,0x65,0x20,0x73,0x74,
-	0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,0x63,
-	0x61,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x6E,
-	0x64,0x65,0x72,0x69,0x6E,0x67,0x20,0x72,0x61,0x74,0x65,0x20,
-	0x69,0x73,0x22,0x3E,0x6E,0x6F,0x74,0x20,0x65,0x78,0x61,0x63,
-	0x74,0x20,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,
-	0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x20,0x72,0x61,0x74,0x65,
-	0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x33,0x3E,0x40,0x43,
-	0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x69,0x6C,0x6C,0x20,0x79,
-	0x6F,0x75,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,
-	0x20,0x4D,0x49,0x44,0x49,0x20,0x6F,0x75,0x74,0x20,0x66,0x75,
-	0x6E,0x63,0x74,0x69,0x6F,0x6E,0x61,0x6C,0x69,0x74,0x79,0x3F,
-	0x4D,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x4E,0x6F,
-	0x2C,0x20,0x73,0x6F,0x72,0x72,0x79,0x2E,0x20,0x54,0x68,0x69,
-	0x73,0x20,0x69,0x73,0x20,0x76,0x65,0x72,0x79,0x20,0x64,0x69,
-	0x66,0x66,0x69,0x63,0x75,0x6C,0x74,0x20,0x74,0x6F,0x20,0x69,
-	0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,0x63,0x6F,0x72,
-	0x72,0x65,0x63,0x74,0x6C,0x79,0x20,0x77,0x68,0x65,0x6E,0x20,
-	0x68,0x61,0x76,0x69,0x6E,0x67,0x3C,0x3E,0x40,0x58,0x30,0x33,
-	0x35,0x68,0x69,0x67,0x68,0x65,0x72,0x20,0x61,0x75,0x64,0x69,
-	0x6F,0x20,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x73,0x69,0x7A,
-	0x65,0x73,0x20,0x28,0x62,0x75,0x66,0x66,0x65,0x72,0x65,0x64,
-	0x20,0x72,0x65,0x70,0x6C,0x61,0x79,0x65,0x72,0x20,0x74,0x69,
-	0x63,0x6B,0x73,0x29,0x2E,0x2E,0x2E,0x06,0x3E,0x40,0x58,0x30,
-	0x32,0x30,0x30,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,
-	0x57,0x68,0x65,0x72,0x65,0x20,0x69,0x73,0x20,0x74,0x68,0x65,
-	0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,
-	0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x73,0x74,0x6F,0x72,
-	0x65,0x64,0x3F,0x3F,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
-	0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,0x20,0x5C,0x55,
-	0x73,0x65,0x72,0x73,0x5C,0x55,0x53,0x45,0x52,0x5C,0x41,0x70,
-	0x70,0x44,0x61,0x74,0x61,0x5C,0x52,0x6F,0x61,0x6D,0x69,0x6E,
-	0x67,0x5C,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x5C,
-	0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x45,0x3E,0x40,0x58,0x30,
-	0x33,0x35,0x4F,0x53,0x20,0x58,0x3A,0x20,0x2F,0x55,0x73,0x65,
-	0x72,0x73,0x2F,0x55,0x53,0x45,0x52,0x2F,0x4C,0x69,0x62,0x72,
-	0x61,0x72,0x79,0x2F,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74,
-	0x69,0x6F,0x6E,0x20,0x53,0x75,0x70,0x70,0x6F,0x72,0x74,0x2F,
-	0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x2F,0x46,0x54,
-	0x32,0x2E,0x43,0x46,0x47,0x2F,0x47,0x4E,0x55,0x2F,0x4C,0x69,
-	0x6E,0x75,0x78,0x3A,0x20,0x2F,0x68,0x6F,0x6D,0x65,0x2F,0x55,
-	0x53,0x45,0x52,0x2F,0x2E,0x63,0x6F,0x6E,0x66,0x69,0x67,0x2F,
-	0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x2F,0x46,0x54,
-	0x32,0x2E,0x43,0x46,0x47,0x01,0x3E,0x48,0x49,0x74,0x20,0x77,
-	0x69,0x6C,0x6C,0x20,0x62,0x65,0x20,0x73,0x74,0x6F,0x72,0x65,
-	0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,
-	0x67,0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,
-	0x72,0x79,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x70,0x61,
-	0x74,0x68,0x20,0x63,0x6F,0x75,0x6C,0x64,0x6E,0x27,0x74,0x20,
-	0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x2E,0x4D,0x49,0x66,0x20,
-	0x79,0x6F,0x75,0x20,0x70,0x75,0x74,0x20,0x74,0x68,0x65,0x20,
-	0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,
-	0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x69,0x6E,0x20,0x74,0x68,
-	0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,0x69,
-	0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x2C,0x20,0x69,0x74,0x20,
-	0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x61,0x64,0x20,0x74,0x68,
-	0x61,0x74,0x4A,0x6F,0x6E,0x65,0x20,0x61,0x6E,0x64,0x20,0x6E,
-	0x6F,0x74,0x20,0x61,0x74,0x74,0x65,0x6D,0x70,0x74,0x20,0x74,
-	0x6F,0x20,0x63,0x72,0x65,0x61,0x74,0x65,0x20,0x63,0x6F,0x6E,
-	0x66,0x69,0x67,0x20,0x64,0x69,0x72,0x73,0x20,0x66,0x6F,0x72,
-	0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,0x75,0x73,0x65,0x72,
-	0x2E,0x20,0x28,0x70,0x6F,0x72,0x74,0x61,0x62,0x6C,0x65,0x20,
-	0x6D,0x6F,0x64,0x65,0x29,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,
-	0x42,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x43,0x61,
-	0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x20,
-	0x72,0x65,0x61,0x64,0x20,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,
-	0x20,0x66,0x72,0x6F,0x6D,0x20,0x72,0x65,0x61,0x6C,0x20,0x46,
-	0x54,0x32,0x2C,0x20,0x61,0x6E,0x64,0x20,0x76,0x69,0x63,0x65,
-	0x20,0x76,0x65,0x72,0x73,0x61,0x3F,0x4C,0x3E,0x40,0x43,0x30,
-	0x30,0x32,0x41,0x3A,0x20,0x59,0x65,0x73,0x2C,0x20,0x69,0x74,
-	0x20,0x73,0x68,0x6F,0x75,0x6C,0x64,0x20,0x77,0x6F,0x72,0x6B,
-	0x20,0x6A,0x75,0x73,0x74,0x20,0x66,0x69,0x6E,0x65,0x2E,0x20,
-	0x50,0x75,0x74,0x20,0x69,0x74,0x20,0x69,0x6E,0x20,0x74,0x68,
-	0x65,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,
-	0x73,0x68,0x6F,0x77,0x6E,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,
-	0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x52,0x3E,0x40,0x43,0x30,
-	0x30,0x31,0x51,0x3A,0x20,0x53,0x6D,0x70,0x2E,0x20,0x45,0x64,
-	0x2E,0x3A,0x20,0x57,0x68,0x69,0x6C,0x65,0x20,0x7A,0x6F,0x6F,
-	0x6D,0x69,0x6E,0x67,0x20,0x69,0x6E,0x2C,0x20,0x49,0x20,0x73,
-	0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,0x73,0x20,0x63,0x61,0x6E,
-	0x27,0x74,0x20,0x6D,0x61,0x72,0x6B,0x20,0x74,0x68,0x65,0x20,
-	0x6C,0x61,0x73,0x74,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,
-	0x70,0x6F,0x69,0x6E,0x74,0x21,0x47,0x3E,0x40,0x43,0x30,0x30,
-	0x32,0x41,0x3A,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,
-	0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E,0x20,0x54,0x68,0x69,0x73,
-	0x20,0x69,0x73,0x20,0x61,0x20,0x6C,0x69,0x6D,0x69,0x74,0x61,
-	0x74,0x69,0x6F,0x6E,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,
-	0x6E,0x61,0x74,0x75,0x72,0x65,0x20,0x6F,0x66,0x20,0x73,0x63,
-	0x61,0x6C,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,
-	0x30,0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x49,
-	0x20,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x20,0x62,0x75,0x67,
-	0x21,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x50,
-	0x6C,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6E,0x64,0x20,0x6D,
-	0x65,0x20,0x61,0x20,0x6D,0x61,0x69,0x6C,0x20,0x28,0x66,0x6F,
-	0x75,0x6E,0x64,0x20,0x61,0x74,0x20,0x31,0x36,0x2D,0x62,0x69,
-	0x74,0x73,0x2E,0x6F,0x72,0x67,0x29,0x20,0x61,0x6E,0x64,0x20,
-	0x74,0x72,0x79,0x20,0x74,0x6F,0x20,0x65,0x78,0x70,0x6C,0x61,
-	0x69,0x6E,0x20,0x69,0x74,0x2E,0x00,0x03,0x45,0x4E,0x44,0x4C,
-	0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0E,0x40,
+	0x4C,0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x2F,0x46,0x41,
+	0x51,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x41,0x3E,0x40,0x43,
+	0x30,0x30,0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,0x49,0x20,
+	0x6D,0x61,0x6B,0x65,0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,
+	0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x73,0x74,0x72,
+	0x65,0x74,0x63,0x68,0x20,0x6F,0x75,0x74,0x20,0x74,0x68,0x65,
+	0x20,0x77,0x68,0x6F,0x6C,0x65,0x20,0x73,0x63,0x72,0x65,0x65,
+	0x6E,0x3F,0x3A,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,
+	0x45,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x50,0x69,0x78,0x65,
+	0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x69,0x6E,
+	0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,
+	0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,
+	0x2E,0x4D,0x3E,0x40,0x58,0x30,0x33,0x35,0x49,0x74,0x20,0x77,
+	0x6F,0x6E,0x27,0x74,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x70,0x72,
+	0x65,0x74,0x74,0x79,0x2C,0x20,0x62,0x75,0x74,0x20,0x74,0x6F,
+	0x20,0x73,0x6F,0x6D,0x65,0x20,0x70,0x65,0x6F,0x70,0x6C,0x65,
+	0x20,0x69,0x74,0x27,0x73,0x20,0x6D,0x75,0x63,0x68,0x20,0x62,
+	0x65,0x74,0x74,0x65,0x72,0x20,0x74,0x68,0x61,0x6E,0x20,0x6E,
+	0x6F,0x74,0x68,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,0x30,
+	0x32,0x30,0x27,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,
+	0x49,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x75,0x73,0x65,0x20,
+	0x41,0x4C,0x54,0x2B,0x46,0x34,0x20,0x61,0x6E,0x64,0x20,0x41,
+	0x4C,0x54,0x2B,0x46,0x35,0x21,0x4E,0x3E,0x40,0x43,0x30,0x30,
+	0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,
+	0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x68,0x61,0x76,0x65,
+	0x20,0x47,0x65,0x46,0x6F,0x72,0x63,0x65,0x20,0x45,0x78,0x70,
+	0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20,0x69,0x6E,0x73,0x74,
+	0x61,0x6C,0x6C,0x65,0x64,0x2C,0x20,0x79,0x6F,0x75,0x20,0x6E,
+	0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x63,0x68,0x61,0x6E,0x67,
+	0x65,0x2B,0x3E,0x40,0x58,0x30,0x33,0x35,0x74,0x68,0x65,0x20,
+	0x6B,0x65,0x79,0x62,0x69,0x6E,0x64,0x69,0x6E,0x67,0x73,0x20,
+	0x69,0x6E,0x20,0x69,0x74,0x73,0x20,0x73,0x65,0x74,0x74,0x69,
+	0x6E,0x67,0x73,0x20,0x70,0x61,0x67,0x65,0x2E,0x56,0x6D,0x61,
+	0x63,0x4F,0x53,0x2F,0x4F,0x53,0x20,0x58,0x3A,0x20,0x43,0x68,
+	0x61,0x6E,0x67,0x65,0x20,0x41,0x4C,0x54,0x2B,0x46,0x34,0x2F,
+	0x41,0x4C,0x54,0x2B,0x46,0x35,0x20,0x6B,0x65,0x79,0x73,0x20,
+	0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,0x74,0x6F,
+	0x20,0x73,0x6F,0x6D,0x65,0x74,0x68,0x69,0x6E,0x67,0x20,0x65,
+	0x6C,0x73,0x65,0x2E,0x20,0x41,0x6C,0x73,0x6F,0x20,0x66,0x6F,
+	0x72,0x20,0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,0x2E,
+	0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2B,0x3E,0x40,0x43,0x30,
+	0x30,0x31,0x51,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,0x6F,0x75,
+	0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,0x69,0x73,
+	0x20,0x64,0x65,0x6C,0x61,0x79,0x65,0x64,0x2F,0x6C,0x61,0x67,
+	0x67,0x79,0x21,0x44,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
+	0x20,0x4D,0x61,0x6B,0x65,0x20,0x73,0x75,0x72,0x65,0x20,0x22,
+	0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x6D,0x6F,0x75,
+	0x73,0x65,0x22,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x61,0x62,
+	0x6C,0x65,0x64,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,
+	0x67,0x20,0x2D,0x3E,0x20,0x4C,0x61,0x79,0x6F,0x75,0x74,0x2E,
+	0x4B,0x3E,0x40,0x58,0x30,0x33,0x35,0x41,0x6C,0x74,0x65,0x72,
+	0x6E,0x61,0x74,0x69,0x76,0x65,0x6C,0x79,0x2C,0x20,0x79,0x6F,
+	0x75,0x20,0x63,0x61,0x6E,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,
+	0x20,0x22,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F,0x66,0x66,0x22,
+	0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,
+	0x3E,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,
+	0x6F,0x75,0x73,0x2E,0x46,0x3E,0x54,0x68,0x69,0x73,0x20,0x68,
+	0x6F,0x77,0x65,0x76,0x65,0x72,0x2C,0x20,0x77,0x69,0x6C,0x6C,
+	0x20,0x69,0x6E,0x74,0x72,0x6F,0x64,0x75,0x63,0x65,0x20,0x73,
+	0x74,0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,
+	0x63,0x61,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x72,0x65,
+	0x6E,0x64,0x65,0x72,0x69,0x6E,0x67,0x20,0x72,0x61,0x74,0x65,
+	0x20,0x69,0x73,0x22,0x3E,0x6E,0x6F,0x74,0x20,0x65,0x78,0x61,
+	0x63,0x74,0x20,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,
+	0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x20,0x72,0x61,0x74,
+	0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x33,0x3E,0x40,
+	0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x69,0x6C,0x6C,0x20,
+	0x79,0x6F,0x75,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,
+	0x74,0x20,0x4D,0x49,0x44,0x49,0x20,0x6F,0x75,0x74,0x20,0x66,
+	0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x61,0x6C,0x69,0x74,0x79,
+	0x3F,0x4D,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x4E,
+	0x6F,0x2C,0x20,0x73,0x6F,0x72,0x72,0x79,0x2E,0x20,0x54,0x68,
+	0x69,0x73,0x20,0x69,0x73,0x20,0x76,0x65,0x72,0x79,0x20,0x64,
+	0x69,0x66,0x66,0x69,0x63,0x75,0x6C,0x74,0x20,0x74,0x6F,0x20,
+	0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,0x63,0x6F,
+	0x72,0x72,0x65,0x63,0x74,0x6C,0x79,0x20,0x77,0x68,0x65,0x6E,
+	0x20,0x68,0x61,0x76,0x69,0x6E,0x67,0x3C,0x3E,0x40,0x58,0x30,
+	0x33,0x35,0x68,0x69,0x67,0x68,0x65,0x72,0x20,0x61,0x75,0x64,
+	0x69,0x6F,0x20,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x73,0x69,
+	0x7A,0x65,0x73,0x20,0x28,0x62,0x75,0x66,0x66,0x65,0x72,0x65,
+	0x64,0x20,0x72,0x65,0x70,0x6C,0x61,0x79,0x65,0x72,0x20,0x74,
+	0x69,0x63,0x6B,0x73,0x29,0x2E,0x2E,0x2E,0x06,0x3E,0x40,0x58,
+	0x30,0x32,0x30,0x30,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,
+	0x20,0x57,0x68,0x65,0x72,0x65,0x20,0x69,0x73,0x20,0x74,0x68,
+	0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,
+	0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x73,0x74,0x6F,
+	0x72,0x65,0x64,0x3F,0x3F,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,
+	0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,0x20,0x5C,
+	0x55,0x73,0x65,0x72,0x73,0x5C,0x55,0x53,0x45,0x52,0x5C,0x41,
+	0x70,0x70,0x44,0x61,0x74,0x61,0x5C,0x52,0x6F,0x61,0x6D,0x69,
+	0x6E,0x67,0x5C,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,
+	0x5C,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x45,0x3E,0x40,0x58,
+	0x30,0x33,0x35,0x4F,0x53,0x20,0x58,0x3A,0x20,0x2F,0x55,0x73,
+	0x65,0x72,0x73,0x2F,0x55,0x53,0x45,0x52,0x2F,0x4C,0x69,0x62,
+	0x72,0x61,0x72,0x79,0x2F,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,
+	0x74,0x69,0x6F,0x6E,0x20,0x53,0x75,0x70,0x70,0x6F,0x72,0x74,
+	0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x2F,0x46,
+	0x54,0x32,0x2E,0x43,0x46,0x47,0x2F,0x47,0x4E,0x55,0x2F,0x4C,
+	0x69,0x6E,0x75,0x78,0x3A,0x20,0x2F,0x68,0x6F,0x6D,0x65,0x2F,
+	0x55,0x53,0x45,0x52,0x2F,0x2E,0x63,0x6F,0x6E,0x66,0x69,0x67,
+	0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x2F,0x46,
+	0x54,0x32,0x2E,0x43,0x46,0x47,0x01,0x3E,0x48,0x49,0x74,0x20,
+	0x77,0x69,0x6C,0x6C,0x20,0x62,0x65,0x20,0x73,0x74,0x6F,0x72,
+	0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x72,
+	0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,0x63,0x74,
+	0x6F,0x72,0x79,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x70,
+	0x61,0x74,0x68,0x20,0x63,0x6F,0x75,0x6C,0x64,0x6E,0x27,0x74,
+	0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x2E,0x4D,0x49,0x66,
+	0x20,0x79,0x6F,0x75,0x20,0x70,0x75,0x74,0x20,0x74,0x68,0x65,
+	0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,
+	0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x69,0x6E,0x20,0x74,
+	0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,
+	0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x2C,0x20,0x69,0x74,
+	0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x61,0x64,0x20,0x74,
+	0x68,0x61,0x74,0x4A,0x6F,0x6E,0x65,0x20,0x61,0x6E,0x64,0x20,
+	0x6E,0x6F,0x74,0x20,0x61,0x74,0x74,0x65,0x6D,0x70,0x74,0x20,
+	0x74,0x6F,0x20,0x63,0x72,0x65,0x61,0x74,0x65,0x20,0x63,0x6F,
+	0x6E,0x66,0x69,0x67,0x20,0x64,0x69,0x72,0x73,0x20,0x66,0x6F,
+	0x72,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,0x75,0x73,0x65,
+	0x72,0x2E,0x20,0x28,0x70,0x6F,0x72,0x74,0x61,0x62,0x6C,0x65,
+	0x20,0x6D,0x6F,0x64,0x65,0x29,0x06,0x3E,0x40,0x58,0x30,0x32,
+	0x30,0x42,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x43,
+	0x61,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6C,0x6F,0x6E,0x65,
+	0x20,0x72,0x65,0x61,0x64,0x20,0x46,0x54,0x32,0x2E,0x43,0x46,
+	0x47,0x20,0x66,0x72,0x6F,0x6D,0x20,0x72,0x65,0x61,0x6C,0x20,
+	0x46,0x54,0x32,0x2C,0x20,0x61,0x6E,0x64,0x20,0x76,0x69,0x63,
+	0x65,0x20,0x76,0x65,0x72,0x73,0x61,0x3F,0x4C,0x3E,0x40,0x43,
+	0x30,0x30,0x32,0x41,0x3A,0x20,0x59,0x65,0x73,0x2C,0x20,0x69,
+	0x74,0x20,0x73,0x68,0x6F,0x75,0x6C,0x64,0x20,0x77,0x6F,0x72,
+	0x6B,0x20,0x6A,0x75,0x73,0x74,0x20,0x66,0x69,0x6E,0x65,0x2E,
+	0x20,0x50,0x75,0x74,0x20,0x69,0x74,0x20,0x69,0x6E,0x20,0x74,
+	0x68,0x65,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,
+	0x20,0x73,0x68,0x6F,0x77,0x6E,0x20,0x61,0x62,0x6F,0x76,0x65,
+	0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x52,0x3E,0x40,0x43,
+	0x30,0x30,0x31,0x51,0x3A,0x20,0x53,0x6D,0x70,0x2E,0x20,0x45,
+	0x64,0x2E,0x3A,0x20,0x57,0x68,0x69,0x6C,0x65,0x20,0x7A,0x6F,
+	0x6F,0x6D,0x69,0x6E,0x67,0x20,0x69,0x6E,0x2C,0x20,0x49,0x20,
+	0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,0x73,0x20,0x63,0x61,
+	0x6E,0x27,0x74,0x20,0x6D,0x61,0x72,0x6B,0x20,0x74,0x68,0x65,
+	0x20,0x6C,0x61,0x73,0x74,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,
+	0x20,0x70,0x6F,0x69,0x6E,0x74,0x21,0x47,0x3E,0x40,0x43,0x30,
+	0x30,0x32,0x41,0x3A,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,
+	0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E,0x20,0x54,0x68,0x69,
+	0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x6C,0x69,0x6D,0x69,0x74,
+	0x61,0x74,0x69,0x6F,0x6E,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,
+	0x20,0x6E,0x61,0x74,0x75,0x72,0x65,0x20,0x6F,0x66,0x20,0x73,
+	0x63,0x61,0x6C,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,0x30,
+	0x32,0x30,0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,
+	0x49,0x20,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x20,0x62,0x75,
+	0x67,0x21,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,
+	0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6E,0x64,0x20,
+	0x6D,0x65,0x20,0x61,0x20,0x6D,0x61,0x69,0x6C,0x20,0x28,0x66,
+	0x6F,0x75,0x6E,0x64,0x20,0x61,0x74,0x20,0x31,0x36,0x2D,0x62,
+	0x69,0x74,0x73,0x2E,0x6F,0x72,0x67,0x29,0x20,0x61,0x6E,0x64,
+	0x20,0x74,0x72,0x79,0x20,0x74,0x6F,0x20,0x65,0x78,0x70,0x6C,
+	0x61,0x69,0x6E,0x20,0x69,0x74,0x2E,0x00,0x03,0x45,0x4E,0x44,
+	0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0C,0x40,0x4C,
-	0x4B,0x6E,0x6F,0x77,0x6E,0x20,0x62,0x75,0x67,0x73,0x06,0x3E,
-	0x40,0x58,0x30,0x31,0x30,0x2C,0x3E,0x40,0x43,0x30,0x30,0x31,
-	0x57,0x41,0x56,0x20,0x65,0x78,0x70,0x6F,0x72,0x74,0x69,0x6E,
-	0x67,0x20,0x28,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,0x67,
-	0x20,0x73,0x6F,0x6E,0x67,0x20,0x74,0x6F,0x20,0x57,0x41,0x56,
-	0x29,0x3A,0x01,0x3E,0x50,0x3E,0x40,0x43,0x30,0x30,0x32,0x2D,
-	0x20,0x53,0x6F,0x6E,0x67,0x73,0x20,0x74,0x68,0x61,0x74,0x20,
-	0x6A,0x75,0x6D,0x70,0x20,0x62,0x61,0x63,0x6B,0x20,0x74,0x6F,
-	0x20,0x61,0x20,0x70,0x72,0x65,0x76,0x69,0x6F,0x75,0x73,0x20,
-	0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x20,0x77,0x69,0x6C,0x6C,
-	0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x66,0x6F,0x72,0x65,
-	0x76,0x65,0x72,0x20,0x61,0x6E,0x64,0x20,0x65,0x76,0x65,0x72,
-	0x2C,0x50,0x61,0x6E,0x64,0x20,0x79,0x6F,0x75,0x20,0x6E,0x65,
-	0x65,0x64,0x20,0x74,0x6F,0x20,0x70,0x72,0x65,0x73,0x73,0x20,
-	0x61,0x20,0x6B,0x65,0x79,0x20,0x6F,0x72,0x20,0x63,0x6C,0x69,
-	0x63,0x6B,0x20,0x74,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,
-	0x20,0x74,0x6F,0x20,0x61,0x62,0x6F,0x72,0x74,0x20,0x74,0x68,
-	0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x77,0x68,0x65,
-	0x6E,0x20,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x06,0x69,
-	0x74,0x20,0x74,0x6F,0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,0x30,
-	0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x4D,0x6F,0x75,0x73,0x65,
-	0x20,0x2F,0x20,0x6B,0x65,0x79,0x62,0x6F,0x61,0x72,0x64,0x3A,
-	0x01,0x3E,0x43,0x3E,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x4C,
-	0x69,0x6E,0x75,0x78,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,0x6F,
-	0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,0x67,
-	0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x20,0x63,0x61,0x6E,0x20,
-	0x62,0x65,0x20,0x67,0x6C,0x69,0x74,0x63,0x68,0x79,0x20,0x61,
-	0x74,0x20,0x74,0x69,0x6D,0x65,0x73,0x2E,0x2E,0x2E,0x06,0x3E,
-	0x40,0x58,0x30,0x31,0x30,0x0C,0x3E,0x40,0x43,0x30,0x30,0x31,
-	0x56,0x69,0x64,0x65,0x6F,0x3A,0x06,0x3E,0x40,0x43,0x30,0x30,
-	0x32,0x50,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x46,0x75,
-	0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,
-	0x65,0x20,0x63,0x61,0x6E,0x20,0x62,0x65,0x20,0x75,0x6E,0x62,
-	0x65,0x61,0x72,0x61,0x62,0x6C,0x79,0x20,0x73,0x6C,0x6F,0x77,
-	0x20,0x6F,0x6E,0x20,0x61,0x20,0x52,0x61,0x73,0x70,0x62,0x65,
-	0x72,0x72,0x79,0x20,0x50,0x69,0x20,0x28,0x65,0x76,0x65,0x6E,
-	0x20,0x6F,0x6E,0x20,0x52,0x50,0x69,0x20,0x34,0x29,0x01,0x3E,
-	0x52,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x4E,0x6F,0x74,
-	0x20,0x61,0x20,0x62,0x75,0x67,0x2C,0x20,0x62,0x75,0x74,0x20,
-	0x69,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,
-	0x74,0x6F,0x72,0x27,0x73,0x20,0x72,0x65,0x66,0x72,0x65,0x73,
-	0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20,0x6E,0x6F,
-	0x74,0x20,0x73,0x65,0x74,0x20,0x74,0x6F,0x20,0x36,0x30,0x48,
-	0x7A,0x20,0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x4F,
-	0x3E,0x40,0x58,0x30,0x32,0x31,0x79,0x6F,0x75,0x20,0x6D,0x61,
-	0x79,0x20,0x65,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,
-	0x20,0x76,0x69,0x73,0x75,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,
-	0x74,0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,
-	0x73,0x65,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C,
-	0x6C,0x20,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65,
-	0x64,0x20,0x74,0x68,0x65,0x6E,0x2E,0x51,0x49,0x20,0x68,0x69,
-	0x67,0x68,0x6C,0x79,0x20,0x72,0x65,0x63,0x6F,0x6D,0x6D,0x65,
-	0x6E,0x64,0x20,0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x20,0x79,
-	0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x20,
-	0x61,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x69,0x66,0x20,0x79,
-	0x6F,0x75,0x27,0x72,0x65,0x20,0x61,0x20,0x68,0x61,0x72,0x64,
-	0x63,0x6F,0x72,0x65,0x20,0x75,0x73,0x65,0x72,0x20,0x6F,0x66,
-	0x20,0x74,0x68,0x69,0x73,0x08,0x70,0x72,0x6F,0x67,0x72,0x61,
-	0x6D,0x2E,0x00,0x03,0x45,0x4E,0x44
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0C,0x40,
+	0x4C,0x4B,0x6E,0x6F,0x77,0x6E,0x20,0x62,0x75,0x67,0x73,0x06,
+	0x3E,0x40,0x58,0x30,0x31,0x30,0x2C,0x3E,0x40,0x43,0x30,0x30,
+	0x31,0x57,0x41,0x56,0x20,0x65,0x78,0x70,0x6F,0x72,0x74,0x69,
+	0x6E,0x67,0x20,0x28,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,
+	0x67,0x20,0x73,0x6F,0x6E,0x67,0x20,0x74,0x6F,0x20,0x57,0x41,
+	0x56,0x29,0x3A,0x01,0x3E,0x50,0x3E,0x40,0x43,0x30,0x30,0x32,
+	0x2D,0x20,0x53,0x6F,0x6E,0x67,0x73,0x20,0x74,0x68,0x61,0x74,
+	0x20,0x6A,0x75,0x6D,0x70,0x20,0x62,0x61,0x63,0x6B,0x20,0x74,
+	0x6F,0x20,0x61,0x20,0x70,0x72,0x65,0x76,0x69,0x6F,0x75,0x73,
+	0x20,0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x20,0x77,0x69,0x6C,
+	0x6C,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x66,0x6F,0x72,
+	0x65,0x76,0x65,0x72,0x20,0x61,0x6E,0x64,0x20,0x65,0x76,0x65,
+	0x72,0x2C,0x50,0x61,0x6E,0x64,0x20,0x79,0x6F,0x75,0x20,0x6E,
+	0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x70,0x72,0x65,0x73,0x73,
+	0x20,0x61,0x20,0x6B,0x65,0x79,0x20,0x6F,0x72,0x20,0x63,0x6C,
+	0x69,0x63,0x6B,0x20,0x74,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,
+	0x65,0x20,0x74,0x6F,0x20,0x61,0x62,0x6F,0x72,0x74,0x20,0x74,
+	0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x77,0x68,
+	0x65,0x6E,0x20,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x06,
+	0x69,0x74,0x20,0x74,0x6F,0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,
+	0x30,0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x4D,0x6F,0x75,0x73,
+	0x65,0x20,0x2F,0x20,0x6B,0x65,0x79,0x62,0x6F,0x61,0x72,0x64,
+	0x3A,0x01,0x3E,0x43,0x3E,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,
+	0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,
+	0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,
+	0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x20,0x63,0x61,0x6E,
+	0x20,0x62,0x65,0x20,0x67,0x6C,0x69,0x74,0x63,0x68,0x79,0x20,
+	0x61,0x74,0x20,0x74,0x69,0x6D,0x65,0x73,0x2E,0x2E,0x2E,0x06,
+	0x3E,0x40,0x58,0x30,0x31,0x30,0x0C,0x3E,0x40,0x43,0x30,0x30,
+	0x31,0x56,0x69,0x64,0x65,0x6F,0x3A,0x06,0x3E,0x40,0x43,0x30,
+	0x30,0x32,0x50,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x46,
+	0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,
+	0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x62,0x65,0x20,0x75,0x6E,
+	0x62,0x65,0x61,0x72,0x61,0x62,0x6C,0x79,0x20,0x73,0x6C,0x6F,
+	0x77,0x20,0x6F,0x6E,0x20,0x61,0x20,0x52,0x61,0x73,0x70,0x62,
+	0x65,0x72,0x72,0x79,0x20,0x50,0x69,0x20,0x28,0x65,0x76,0x65,
+	0x6E,0x20,0x6F,0x6E,0x20,0x52,0x50,0x69,0x20,0x34,0x29,0x01,
+	0x3E,0x52,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x4E,0x6F,
+	0x74,0x20,0x61,0x20,0x62,0x75,0x67,0x2C,0x20,0x62,0x75,0x74,
+	0x20,0x69,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,
+	0x69,0x74,0x6F,0x72,0x27,0x73,0x20,0x72,0x65,0x66,0x72,0x65,
+	0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20,0x6E,
+	0x6F,0x74,0x20,0x73,0x65,0x74,0x20,0x74,0x6F,0x20,0x36,0x30,
+	0x48,0x7A,0x20,0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,
+	0x4F,0x3E,0x40,0x58,0x30,0x32,0x31,0x79,0x6F,0x75,0x20,0x6D,
+	0x61,0x79,0x20,0x65,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,
+	0x65,0x20,0x76,0x69,0x73,0x75,0x61,0x6C,0x20,0x73,0x74,0x75,
+	0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,0x63,0x61,
+	0x75,0x73,0x65,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,
+	0x6C,0x6C,0x20,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x75,0x73,
+	0x65,0x64,0x20,0x74,0x68,0x65,0x6E,0x2E,0x51,0x49,0x20,0x68,
+	0x69,0x67,0x68,0x6C,0x79,0x20,0x72,0x65,0x63,0x6F,0x6D,0x6D,
+	0x65,0x6E,0x64,0x20,0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x20,
+	0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,
+	0x20,0x61,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x69,0x66,0x20,
+	0x79,0x6F,0x75,0x27,0x72,0x65,0x20,0x61,0x20,0x68,0x61,0x72,
+	0x64,0x63,0x6F,0x72,0x65,0x20,0x75,0x73,0x65,0x72,0x20,0x6F,
+	0x66,0x20,0x74,0x68,0x69,0x73,0x08,0x70,0x72,0x6F,0x67,0x72,
+	0x61,0x6D,0x2E,0x00,0x03,0x45,0x4E,0x44
 };
 
 #endif
--- a/src/mixer/ft2_center_mix.c
+++ b/src/mixer/ft2_center_mix.c
@@ -13,7 +13,7 @@
 void centerMix8bNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -55,7 +55,7 @@
 void centerMix8bLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -97,7 +97,7 @@
 void centerMix8bBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -138,10 +138,10 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix8bNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix8bNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -158,19 +158,19 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			INC_POS
 		}
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			INC_POS
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			INC_POS
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			INC_POS
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			INC_POS
 		}
 
@@ -180,10 +180,10 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix8bLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix8bLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -203,19 +203,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
 			}
 		}
@@ -223,19 +223,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS
 			}
 		}
@@ -246,10 +246,10 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix8bBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix8bBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -270,19 +270,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 		}
@@ -290,19 +290,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
 			}
 		}
@@ -318,7 +318,7 @@
 void centerMix8bNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -360,7 +360,7 @@
 void centerMix8bLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -402,7 +402,7 @@
 void centerMix8bBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -446,9 +446,9 @@
 void centerMix8bRampNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -496,9 +496,9 @@
 void centerMix8bRampLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -546,9 +546,9 @@
 void centerMix8bRampBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -595,12 +595,12 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix8bRampNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix8bRampNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -617,7 +617,7 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
 		}
@@ -624,16 +624,16 @@
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
-			RENDER_8BIT_SMP_MONO_CINTRP
+			RENDER_8BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
 		}
@@ -645,12 +645,12 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix8bRampLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix8bRampLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -670,7 +670,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -677,16 +677,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -695,7 +695,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -702,16 +702,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -724,12 +724,12 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix8bRampBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix8bRampBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -750,7 +750,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -757,16 +757,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -775,7 +775,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -782,16 +782,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_MONO_CINTRP
+				RENDER_8BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -808,9 +808,9 @@
 void centerMix8bRampNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -858,9 +858,9 @@
 void centerMix8bRampLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -908,9 +908,9 @@
 void centerMix8bRampBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -964,7 +964,7 @@
 void centerMix16bNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1006,7 +1006,7 @@
 void centerMix16bLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1048,7 +1048,7 @@
 void centerMix16bBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -1089,10 +1089,10 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix16bNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix16bNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1109,19 +1109,19 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			INC_POS
 		}
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			INC_POS
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			INC_POS
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			INC_POS
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			INC_POS
 		}
 
@@ -1131,10 +1131,10 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix16bLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix16bLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1154,19 +1154,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS
 			}
 		}
@@ -1174,19 +1174,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS
 			}
 		}
@@ -1197,10 +1197,10 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix16bBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix16bBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -1221,19 +1221,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 		}
@@ -1241,19 +1241,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				INC_POS_BIDI
 			}
 		}
@@ -1268,7 +1268,7 @@
 void centerMix16bNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1310,7 +1310,7 @@
 void centerMix16bLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1352,7 +1352,7 @@
 void centerMix16bBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -1397,9 +1397,9 @@
 void centerMix16bRampNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1447,9 +1447,9 @@
 void centerMix16bRampLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1497,9 +1497,9 @@
 void centerMix16bRampBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -1546,12 +1546,12 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix16bRampNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix16bRampNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1568,7 +1568,7 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
 		}
@@ -1575,16 +1575,16 @@
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
-			RENDER_16BIT_SMP_MONO_CINTRP
+			RENDER_16BIT_SMP_MONO_SINTRP
 			VOLUME_RAMPING_MONO
 			INC_POS
 		}
@@ -1596,12 +1596,12 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix16bRampLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix16bRampLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1621,7 +1621,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -1628,16 +1628,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -1646,7 +1646,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -1653,16 +1653,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS
 			}
@@ -1675,12 +1675,12 @@
 	SET_BACK_MIXER_POS
 }
 
-void centerMix16bRampBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+void centerMix16bRampBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -1701,7 +1701,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -1708,16 +1708,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -1726,7 +1726,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -1733,16 +1733,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_MONO_CINTRP
+				RENDER_16BIT_SMP_MONO_SINTRP
 				VOLUME_RAMPING_MONO
 				INC_POS_BIDI
 			}
@@ -1759,9 +1759,9 @@
 void centerMix16bRampNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1809,9 +1809,9 @@
 void centerMix16bRampLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1859,9 +1859,9 @@
 void centerMix16bRampBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolL;
+	double dVolLDelta, dVolL;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
--- a/src/mixer/ft2_center_mix.h
+++ b/src/mixer/ft2_center_mix.h
@@ -9,9 +9,9 @@
 void centerMix8bNoLoop(voice_t *v, uint32_t numSamples);
 void centerMix8bLoop(voice_t *v, uint32_t numSamples);
 void centerMix8bBidiLoop(voice_t *v, uint32_t numSamples);
-void centerMix8bNoLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix8bLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix8bBidiLoopCIntrp(voice_t *v, uint32_t numSamples);
+void centerMix8bNoLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix8bLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix8bBidiLoopSIntrp(voice_t *v, uint32_t numSamples);
 void centerMix8bNoLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix8bLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix8bBidiLoopLIntrp(voice_t *v, uint32_t numSamples);
@@ -20,9 +20,9 @@
 void centerMix16bNoLoop(voice_t *v, uint32_t numSamples);
 void centerMix16bLoop(voice_t *v, uint32_t numSamples);
 void centerMix16bBidiLoop(voice_t *v, uint32_t numSamples);
-void centerMix16bNoLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix16bLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix16bBidiLoopCIntrp(voice_t *v, uint32_t numSamples);
+void centerMix16bNoLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix16bLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix16bBidiLoopSIntrp(voice_t *v, uint32_t numSamples);
 void centerMix16bNoLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix16bLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix16bBidiLoopLIntrp(voice_t *v, uint32_t numSamples);
@@ -33,9 +33,9 @@
 void centerMix8bRampNoLoop(voice_t *v, uint32_t numSamples);
 void centerMix8bRampLoop(voice_t *v, uint32_t numSamples);
 void centerMix8bRampBidiLoop(voice_t *v, uint32_t numSamples);
-void centerMix8bRampNoLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix8bRampLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix8bRampBidiLoopCIntrp(voice_t *v, uint32_t numSamples);
+void centerMix8bRampNoLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix8bRampLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix8bRampBidiLoopSIntrp(voice_t *v, uint32_t numSamples);
 void centerMix8bRampNoLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix8bRampLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix8bRampBidiLoopLIntrp(voice_t *v, uint32_t numSamples);
@@ -44,9 +44,9 @@
 void centerMix16bRampNoLoop(voice_t *v, uint32_t numSamples);
 void centerMix16bRampLoop(voice_t *v, uint32_t numSamples);
 void centerMix16bRampBidiLoop(voice_t *v, uint32_t numSamples);
-void centerMix16bRampNoLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix16bRampLoopCIntrp(voice_t *v, uint32_t numSamples);
-void centerMix16bRampBidiLoopCIntrp(voice_t *v, uint32_t numSamples);
+void centerMix16bRampNoLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix16bRampLoopSIntrp(voice_t *v, uint32_t numSamples);
+void centerMix16bRampBidiLoopSIntrp(voice_t *v, uint32_t numSamples);
 void centerMix16bRampNoLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix16bRampLoopLIntrp(voice_t *v, uint32_t numSamples);
 void centerMix16bRampBidiLoopLIntrp(voice_t *v, uint32_t numSamples);
--- a/src/mixer/ft2_cubicspline.c
+++ /dev/null
@@ -1,59 +1,0 @@
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include "ft2_cubicspline.h"
-
-float *fCubicSplineLUT8 = NULL;
-float *fCubicSplineLUT16 = NULL;
-
-/* 4-tap cubic spline interpolation (Horner's method)
-**
-** This simplified LUT formula has been used in several trackers, but
-** I think it originates from ModPlug Tracker (not sure about this).
-*/
-
-static void calcCubicLUT(float *fLUTPtr, const double dSale)
-{
-	for (int32_t i = 0; i < CUBIC_PHASES; i++)
-	{
-		const double x  = i * (1.0 / CUBIC_PHASES);
-		const double x2 = x * x;  // x^2
-		const double x3 = x2 * x; // x^3
-
-		*fLUTPtr++ = (float)((-0.5 * x3 + 1.0 * x2 - 0.5 * x) * dSale);
-		*fLUTPtr++ = (float)(( 1.5 * x3 - 2.5 * x2 + 1.0)     * dSale);
-		*fLUTPtr++ = (float)((-1.5 * x3 + 2.0 * x2 + 0.5 * x) * dSale);
-		*fLUTPtr++ = (float)(( 0.5 * x3 - 0.5 * x2)           * dSale);
-	}
-}
-
-bool calcCubicTable(void)
-{
-	fCubicSplineLUT8 = (float *)malloc(CUBIC_LUT_LEN * sizeof (float));
-	if (fCubicSplineLUT8 == NULL)
-		return false;
-
-	fCubicSplineLUT16 = (float *)malloc(CUBIC_LUT_LEN * sizeof (float));
-	if (fCubicSplineLUT16 == NULL)
-		return false;
-
-	calcCubicLUT(fCubicSplineLUT8, 1.0 / 128.0); // for 8-bit samples
-	calcCubicLUT(fCubicSplineLUT16, 1.0 / 32768.0); // for 16-bit samples
-
-	return true;
-}
-
-void freeCubicTable(void)
-{
-	if (fCubicSplineLUT8 != NULL)
-	{
-		free(fCubicSplineLUT8);
-		fCubicSplineLUT8 = NULL;
-	}
-
-	if (fCubicSplineLUT16 != NULL)
-	{
-		free(fCubicSplineLUT16);
-		fCubicSplineLUT16 = NULL;
-	}
-}
--- a/src/mixer/ft2_cubicspline.h
+++ /dev/null
@@ -1,22 +1,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include "../ft2_audio.h" // MIXER_FRAC_BITS definition
-
-// if you change this, also change CUBIC_PHASES_BITS
-#define CUBIC_PHASES 4096
-#define CUBIC_PHASES_BITS 12 /* log2(CUBIC_PHASES) */
-
-// don't change these!
-
-#define CUBIC_WIDTH 4
-#define CUBIC_WIDTH_BITS 2
-#define CUBIC_LUT_LEN (CUBIC_WIDTH * CUBIC_PHASES)
-#define CUBIC_FSHIFT (MIXER_FRAC_BITS-(CUBIC_PHASES_BITS+CUBIC_WIDTH_BITS))
-#define CUBIC_FMASK ((CUBIC_WIDTH*CUBIC_PHASES)-CUBIC_WIDTH)
-
-extern float *fCubicSplineLUT8;
-extern float *fCubicSplineLUT16;
-
-bool calcCubicTable(void);
-void freeCubicTable(void);
--- a/src/mixer/ft2_mix.c
+++ b/src/mixer/ft2_mix.c
@@ -5,17 +5,17 @@
 #include "ft2_center_mix.h"
 
 /*
-** -------------------- floating point audio channel mixer ---------------------
+** -------------------- doubleing point audio channel mixer ---------------------
 **            (Note: Mixing macros can be found in ft2_mix_macros.h)
 **
 ** Specifications:
-** - Either no interpolation, 2-tap linear interpolation (FT2) or 4-tap cubic interpolation
+** - Either no interpolation, 2-tap linear interpolation (FT2) or 8-tap windowed-sinc interpolation
 ** - Linear volume ramping, matching FT2 (can be turned off)
 ** - 32.32 fixed-point logic for resampling delta
-** - 32-bit single-precision float logic for mixing and interpolation
+** - 64-bit doube-precision logic for mixing and interpolation
 **
 ** This file has separate routines for EVERY possible sampling variation:
-** Interpolation none/cubic/linear, volumeramp on/off, 8-bit, 16-bit, no loop, loop, bidi.
+** Interpolation none/sinc/linear, volumeramp on/off, 8-bit, 16-bit, no loop, loop, bidi.
 ** (36 mixing routines in total + another 36 for center-mixing)
 **
 ** Every voice has a function pointer set to the according mixing routine on
@@ -34,7 +34,7 @@
 static void mix8bNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -76,7 +76,7 @@
 static void mix8bLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -118,7 +118,7 @@
 static void mix8bBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -158,10 +158,10 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix8bNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -178,19 +178,19 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			INC_POS
 		}
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			INC_POS
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			INC_POS
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			INC_POS
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			INC_POS
 		}
 
@@ -200,10 +200,10 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix8bLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -223,19 +223,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
 			}
 		}
@@ -243,19 +243,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS
 			}
 		}
@@ -266,10 +266,10 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix8bBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -290,19 +290,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 		}
@@ -310,19 +310,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				INC_POS_BIDI
 			}
 		}
@@ -337,7 +337,7 @@
 static void mix8bNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -379,7 +379,7 @@
 static void mix8bLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -421,7 +421,7 @@
 static void mix8bBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -465,9 +465,9 @@
 static void mix8bRampNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -515,9 +515,9 @@
 static void mix8bRampLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -565,9 +565,9 @@
 static void mix8bRampBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -614,12 +614,12 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bRampNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix8bRampNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -636,7 +636,7 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
 		}
@@ -643,16 +643,16 @@
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
-			RENDER_8BIT_SMP_CINTRP
+			RENDER_8BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
 		}
@@ -664,12 +664,12 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bRampLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix8bRampLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -689,7 +689,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -696,16 +696,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -714,7 +714,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -721,16 +721,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -743,12 +743,12 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bRampBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix8bRampBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -769,7 +769,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -776,16 +776,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP_TAP_FIX
+				RENDER_8BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -794,7 +794,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -801,16 +801,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_8BIT_SMP_CINTRP
+				RENDER_8BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -827,9 +827,9 @@
 static void mix8bRampNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -877,9 +877,9 @@
 static void mix8bRampLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -927,9 +927,9 @@
 static void mix8bRampBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -983,7 +983,7 @@
 static void mix16bNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1025,7 +1025,7 @@
 static void mix16bLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1067,7 +1067,7 @@
 static void mix16bBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -1108,10 +1108,10 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix16bNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1128,19 +1128,19 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			INC_POS
 		}
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			INC_POS
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			INC_POS
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			INC_POS
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			INC_POS
 		}
 
@@ -1150,10 +1150,10 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix16bLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1173,19 +1173,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS
 			}
 		}
@@ -1193,19 +1193,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS
 			}
 		}
@@ -1216,10 +1216,10 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix16bBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -1240,19 +1240,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				INC_POS_BIDI
 			}
 		}
@@ -1260,19 +1260,19 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS_BIDI
 			}
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				INC_POS_BIDI
 			}
 		}
@@ -1287,7 +1287,7 @@
 static void mix16bNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1329,7 +1329,7 @@
 static void mix16bLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
@@ -1371,7 +1371,7 @@
 static void mix16bBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
@@ -1415,9 +1415,9 @@
 static void mix16bRampNoLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1465,9 +1465,9 @@
 static void mix16bRampLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1515,9 +1515,9 @@
 static void mix16bRampBidiLoop(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -1564,12 +1564,12 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bRampNoLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix16bRampNoLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1586,7 +1586,7 @@
 
 		for (i = 0; i < (samplesToMix & 3); i++)
 		{
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
 		}
@@ -1593,16 +1593,16 @@
 		samplesToMix >>= 2;
 		for (i = 0; i < samplesToMix; i++)
 		{
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
-			RENDER_16BIT_SMP_CINTRP
+			RENDER_16BIT_SMP_SINTRP
 			VOLUME_RAMPING
 			INC_POS
 		}
@@ -1614,12 +1614,12 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bRampLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix16bRampLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1639,7 +1639,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -1646,16 +1646,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -1664,7 +1664,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -1671,16 +1671,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS
 			}
@@ -1693,12 +1693,12 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bRampBidiLoopCIntrp(voice_t *v, uint32_t numSamples)
+static void mix16bRampBidiLoopSIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float s0, s1, s2, s3, fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -1719,7 +1719,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -1726,16 +1726,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP_TAP_FIX
+				RENDER_16BIT_SMP_SINTRP_TAP_FIX
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -1744,7 +1744,7 @@
 		{
 			for (i = 0; i < (samplesToMix & 3); i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -1751,16 +1751,16 @@
 			samplesToMix >>= 2;
 			for (i = 0; i < samplesToMix; i++)
 			{
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
-				RENDER_16BIT_SMP_CINTRP
+				RENDER_16BIT_SMP_SINTRP
 				VOLUME_RAMPING
 				INC_POS_BIDI
 			}
@@ -1777,9 +1777,9 @@
 static void mix16bRampNoLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1827,9 +1827,9 @@
 static void mix16bRampLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac;
 
@@ -1877,9 +1877,9 @@
 static void mix16bRampBidiLoopLIntrp(voice_t *v, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
-	float fSample, *fMixBufferL, *fMixBufferR;
+	double dSample, *dMixBufferL, *dMixBufferR;
 	int32_t pos;
-	float fVolLDelta, fVolRDelta, fVolL, fVolR;
+	double dVolLDelta, dVolRDelta, dVolL, dVolR;
 	uint32_t i, samplesToMix, samplesLeft;
 	uint64_t posFrac, tmpDelta;
 
@@ -1942,9 +1942,9 @@
 	(mixFunc)mix8bNoLoop,
 	(mixFunc)mix8bLoop,
 	(mixFunc)mix8bBidiLoop,
-	(mixFunc)mix8bNoLoopCIntrp,
-	(mixFunc)mix8bLoopCIntrp,
-	(mixFunc)mix8bBidiLoopCIntrp,
+	(mixFunc)mix8bNoLoopSIntrp,
+	(mixFunc)mix8bLoopSIntrp,
+	(mixFunc)mix8bBidiLoopSIntrp,
 	(mixFunc)mix8bNoLoopLIntrp,
 	(mixFunc)mix8bLoopLIntrp,
 	(mixFunc)mix8bBidiLoopLIntrp,
@@ -1953,9 +1953,9 @@
 	(mixFunc)mix16bNoLoop,
 	(mixFunc)mix16bLoop,
 	(mixFunc)mix16bBidiLoop,
-	(mixFunc)mix16bNoLoopCIntrp,
-	(mixFunc)mix16bLoopCIntrp,
-	(mixFunc)mix16bBidiLoopCIntrp,
+	(mixFunc)mix16bNoLoopSIntrp,
+	(mixFunc)mix16bLoopSIntrp,
+	(mixFunc)mix16bBidiLoopSIntrp,
 	(mixFunc)mix16bNoLoopLIntrp,
 	(mixFunc)mix16bLoopLIntrp,
 	(mixFunc)mix16bBidiLoopLIntrp,
@@ -1966,9 +1966,9 @@
 	(mixFunc)mix8bRampNoLoop,
 	(mixFunc)mix8bRampLoop,
 	(mixFunc)mix8bRampBidiLoop,
-	(mixFunc)mix8bRampNoLoopCIntrp,
-	(mixFunc)mix8bRampLoopCIntrp,
-	(mixFunc)mix8bRampBidiLoopCIntrp,
+	(mixFunc)mix8bRampNoLoopSIntrp,
+	(mixFunc)mix8bRampLoopSIntrp,
+	(mixFunc)mix8bRampBidiLoopSIntrp,
 	(mixFunc)mix8bRampNoLoopLIntrp,
 	(mixFunc)mix8bRampLoopLIntrp,
 	(mixFunc)mix8bRampBidiLoopLIntrp,
@@ -1977,9 +1977,9 @@
 	(mixFunc)mix16bRampNoLoop,
 	(mixFunc)mix16bRampLoop,
 	(mixFunc)mix16bRampBidiLoop,
-	(mixFunc)mix16bRampNoLoopCIntrp,
-	(mixFunc)mix16bRampLoopCIntrp,
-	(mixFunc)mix16bRampBidiLoopCIntrp,
+	(mixFunc)mix16bRampNoLoopSIntrp,
+	(mixFunc)mix16bRampLoopSIntrp,
+	(mixFunc)mix16bRampBidiLoopSIntrp,
 	(mixFunc)mix16bRampNoLoopLIntrp,
 	(mixFunc)mix16bRampLoopLIntrp,
 	(mixFunc)mix16bRampBidiLoopLIntrp,
@@ -1996,9 +1996,9 @@
 	(mixFunc)centerMix8bNoLoop,
 	(mixFunc)centerMix8bLoop,
 	(mixFunc)centerMix8bBidiLoop,
-	(mixFunc)centerMix8bNoLoopCIntrp,
-	(mixFunc)centerMix8bLoopCIntrp,
-	(mixFunc)centerMix8bBidiLoopCIntrp,
+	(mixFunc)centerMix8bNoLoopSIntrp,
+	(mixFunc)centerMix8bLoopSIntrp,
+	(mixFunc)centerMix8bBidiLoopSIntrp,
 	(mixFunc)centerMix8bNoLoopLIntrp,
 	(mixFunc)centerMix8bLoopLIntrp,
 	(mixFunc)centerMix8bBidiLoopLIntrp,
@@ -2007,9 +2007,9 @@
 	(mixFunc)centerMix16bNoLoop,
 	(mixFunc)centerMix16bLoop,
 	(mixFunc)centerMix16bBidiLoop,
-	(mixFunc)centerMix16bNoLoopCIntrp,
-	(mixFunc)centerMix16bLoopCIntrp,
-	(mixFunc)centerMix16bBidiLoopCIntrp,
+	(mixFunc)centerMix16bNoLoopSIntrp,
+	(mixFunc)centerMix16bLoopSIntrp,
+	(mixFunc)centerMix16bBidiLoopSIntrp,
 	(mixFunc)centerMix16bNoLoopLIntrp,
 	(mixFunc)centerMix16bLoopLIntrp,
 	(mixFunc)centerMix16bBidiLoopLIntrp,
@@ -2020,9 +2020,9 @@
 	(mixFunc)centerMix8bRampNoLoop,
 	(mixFunc)centerMix8bRampLoop,
 	(mixFunc)centerMix8bRampBidiLoop,
-	(mixFunc)centerMix8bRampNoLoopCIntrp,
-	(mixFunc)centerMix8bRampLoopCIntrp,
-	(mixFunc)centerMix8bRampBidiLoopCIntrp,
+	(mixFunc)centerMix8bRampNoLoopSIntrp,
+	(mixFunc)centerMix8bRampLoopSIntrp,
+	(mixFunc)centerMix8bRampBidiLoopSIntrp,
 	(mixFunc)centerMix8bRampNoLoopLIntrp,
 	(mixFunc)centerMix8bRampLoopLIntrp,
 	(mixFunc)centerMix8bRampBidiLoopLIntrp,
@@ -2031,9 +2031,9 @@
 	(mixFunc)centerMix16bRampNoLoop,
 	(mixFunc)centerMix16bRampLoop,
 	(mixFunc)centerMix16bRampBidiLoop,
-	(mixFunc)centerMix16bRampNoLoopCIntrp,
-	(mixFunc)centerMix16bRampLoopCIntrp,
-	(mixFunc)centerMix16bRampBidiLoopCIntrp,
+	(mixFunc)centerMix16bRampNoLoopSIntrp,
+	(mixFunc)centerMix16bRampLoopSIntrp,
+	(mixFunc)centerMix16bRampBidiLoopSIntrp,
 	(mixFunc)centerMix16bRampNoLoopLIntrp,
 	(mixFunc)centerMix16bRampLoopLIntrp,
 	(mixFunc)centerMix16bRampBidiLoopLIntrp
--- a/src/mixer/ft2_mix_macros.h
+++ b/src/mixer/ft2_mix_macros.h
@@ -2,7 +2,7 @@
 
 #include <assert.h>
 #include "../ft2_audio.h"
-#include "ft2_cubicspline.h"
+#include "ft2_windowed_sinc.h"
 
 /* ----------------------------------------------------------------------- */
 /*                          GENERAL MIXER MACROS                           */
@@ -9,57 +9,57 @@
 /* ----------------------------------------------------------------------- */
 
 #define GET_VOL \
-	const float fVolL = v->fVolL; \
-	const float fVolR = v->fVolR; \
+	const double dVolL = v->dVolL; \
+	const double dVolR = v->dVolR; \
 
 #define GET_VOL_MONO \
-	const float fVolL = v->fVolL; \
+	const double dVolL = v->dVolL; \
 
 #define GET_VOL_RAMP \
-	fVolL = v->fVolL; \
-	fVolR = v->fVolR; \
+	dVolL = v->dVolL; \
+	dVolR = v->dVolR; \
 
 #define GET_VOL_MONO_RAMP \
-	fVolL = v->fVolL; \
+	dVolL = v->dVolL; \
 
 #define SET_VOL_BACK \
-	v->fVolL = fVolL; \
-	v->fVolR = fVolR; \
+	v->dVolL = dVolL; \
+	v->dVolR = dVolR; \
 
 #define SET_VOL_BACK_MONO \
-	v->fVolL = v->fVolR = fVolL; \
+	v->dVolL = v->dVolR = dVolL; \
 
 #define GET_MIXER_VARS \
 	const uint64_t delta = v->delta; \
-	fMixBufferL = audio.fMixBufferL; \
-	fMixBufferR = audio.fMixBufferR; \
+	dMixBufferL = audio.dMixBufferL; \
+	dMixBufferR = audio.dMixBufferR; \
 	pos = v->pos; \
 	posFrac = v->posFrac; \
 
 #define GET_MIXER_VARS_RAMP \
 	const uint64_t delta = v->delta; \
-	fMixBufferL = audio.fMixBufferL; \
-	fMixBufferR = audio.fMixBufferR; \
-	fVolLDelta = v->fVolDeltaL; \
-	fVolRDelta = v->fVolDeltaR; \
+	dMixBufferL = audio.dMixBufferL; \
+	dMixBufferR = audio.dMixBufferR; \
+	dVolLDelta = v->dVolDeltaL; \
+	dVolRDelta = v->dVolDeltaR; \
 	pos = v->pos; \
 	posFrac = v->posFrac; \
 
 #define GET_MIXER_VARS_MONO_RAMP \
 	const uint64_t delta = v->delta; \
-	fMixBufferL = audio.fMixBufferL; \
-	fMixBufferR = audio.fMixBufferR; \
-	fVolLDelta = v->fVolDeltaL; \
+	dMixBufferL = audio.dMixBufferL; \
+	dMixBufferR = audio.dMixBufferR; \
+	dVolLDelta = v->dVolDeltaL; \
 	pos = v->pos; \
 	posFrac = v->posFrac; \
 
 #define PREPARE_TAP_FIX8 \
 	const int8_t *loopStartPtr = &v->base8[v->loopStart]; \
-	const float fTapFixSample = v->fTapFixSample; \
+	const int8_t *leftEdgePtr = loopStartPtr+SINC_LEFT_TAPS; \
 
 #define PREPARE_TAP_FIX16 \
 	const int16_t *loopStartPtr = &v->base16[v->loopStart]; \
-	const float fTapFixSample = v->fTapFixSample; \
+	const int16_t *leftEdgePtr = loopStartPtr+SINC_LEFT_TAPS; \
 
 #define SET_BASE8 \
 	base = v->base8; \
@@ -97,77 +97,77 @@
 /* ----------------------------------------------------------------------- */
 
 #define VOLUME_RAMPING \
-	fVolL += fVolLDelta; \
-	fVolR += fVolRDelta; \
+	dVolL += dVolLDelta; \
+	dVolR += dVolRDelta; \
 
 #define VOLUME_RAMPING_MONO \
-	fVolL += fVolLDelta; \
+	dVolL += dVolLDelta; \
 
 #define RENDER_8BIT_SMP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	fSample = *smpPtr * (1.0f / 128.0f); \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	dSample = *smpPtr * (1.0 / 128.0); \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
 #define RENDER_8BIT_SMP_MONO \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	fSample = (*smpPtr * (1.0f / 128.0f)) * fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	dSample = (*smpPtr * (1.0 / 128.0)) * dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
 #define RENDER_16BIT_SMP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	fSample = *smpPtr * (1.0f / 32768.0f); \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	dSample = *smpPtr * (1.0 / 32768.0); \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
 #define RENDER_16BIT_SMP_MONO \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	fSample = (*smpPtr * (1.0f / 32768.0f)) * fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	dSample = (*smpPtr * (1.0 / 32768.0)) * dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
 // 2-tap linear interpolation (like FT2)
 
-#define LINEAR_INTERPOLATION16(s, f) \
+#define LINEAR_INTERPOLATION8(s, f) \
 { \
-	const float fFrac = (const float)((uint32_t)f * (1.0f / (UINT32_MAX+1.0f))); /* 0.0 .. 0.999f */ \
-	fSample = ((s[0] + (s[1]-s[0]) * fFrac)) * (1.0f / 32768.0f); \
+	const double dFrac = (const double)((uint32_t)f * (1.0 / (UINT32_MAX+1.0))); /* 0.0 .. 0.999999999 */ \
+	dSample = ((s[0] + (s[1]-s[0]) * dFrac)) * (1.0 / 128.0); \
 } \
 
-#define LINEAR_INTERPOLATION8(s, f) \
+#define LINEAR_INTERPOLATION16(s, f) \
 { \
-	const float fFrac = (const float)((uint32_t)f * (1.0f / (UINT32_MAX+1.0f))); /* 0.0f .. 0.999f */ \
-	fSample = ((s[0] + (s[1]-s[0]) * fFrac)) * (1.0f / 128.0f); \
+	const double dFrac = (const double)((uint32_t)f * (1.0 / (UINT32_MAX+1.0))); /* 0.0 .. 0.999999999 */ \
+	dSample = ((s[0] + (s[1]-s[0]) * dFrac)) * (1.0 / 32768.0); \
 } \
 
 #define RENDER_8BIT_SMP_LINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
 	LINEAR_INTERPOLATION8(smpPtr, posFrac) \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
 #define RENDER_8BIT_SMP_MONO_LINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
 	LINEAR_INTERPOLATION8(smpPtr, posFrac) \
-	fSample *= fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	dSample *= dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
 #define RENDER_16BIT_SMP_LINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
 	LINEAR_INTERPOLATION16(smpPtr, posFrac) \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
 #define RENDER_16BIT_SMP_MONO_LINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
 	LINEAR_INTERPOLATION16(smpPtr, posFrac) \
-	fSample *= fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	dSample *= dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
-// 4-tap cubic spline interpolation (better quality, through LUT: mixer/ft2_cubicspline.c)
+// 8-tap windowed-sinc interpolation (better quality, through LUT: mixer/ft2_windowed_sinc.c)
 
 /* 8bitbubsy: It may look like we are potentially going out of bounds while looking up the sample points,
 ** but the sample data is actually padded on both the left (negative) and right side, where correct tap
@@ -177,85 +177,119 @@
 **
 */
 
-#define CUBICSPLINE_INTERPOLATION(LUT, s, f) \
+#define WINDOWED_SINC_INTERPOLATION8(s, f) \
 { \
-	const float *t = (const float *)LUT + (((uint32_t)f >> CUBIC_FSHIFT) & CUBIC_FMASK); \
-	fSample = (s[-1] * t[0]) + (s[0] * t[1]) + (s[1] * t[2]) + (s[2] * t[3]); \
+	const double *t = v->dSincLUT + (((uint32_t)f >> SINC_FSHIFT) & SINC_FMASK); \
+	dSample = ((s[-3] * t[0]) + \
+	           (s[-2] * t[1]) + \
+	           (s[-1] * t[2]) + \
+	           ( s[0] * t[3]) + \
+	           ( s[1] * t[4]) + \
+	           ( s[2] * t[5]) + \
+	           ( s[3] * t[6]) + \
+	           ( s[4] * t[7])) * (1.0 / 128.0); \
 } \
 
-#define CUBICSPLINE_INTERPOLATION_CUSTOM(LUT, f) \
+#define WINDOWED_SINC_INTERPOLATION16(s, f) \
 { \
-	const float *t = (const float *)LUT + (((uint32_t)f >> CUBIC_FSHIFT) & CUBIC_FMASK); \
-	fSample = (s0 * t[0]) + (s1 * t[1]) + (s2 * t[2]) + (s3 * t[3]); \
+	const double *t = v->dSincLUT + (((uint32_t)f >> SINC_FSHIFT) & SINC_FMASK); \
+	dSample = ((s[-3] * t[0]) + \
+	           (s[-2] * t[1]) + \
+	           (s[-1] * t[2]) + \
+	           ( s[0] * t[3]) + \
+	           ( s[1] * t[4]) + \
+	           ( s[2] * t[5]) + \
+	           ( s[3] * t[6]) + \
+	           ( s[4] * t[7])) * (1.0 / 32768.0); \
 } \
 
-#define RENDER_8BIT_SMP_CINTRP \
+#define RENDER_8BIT_SMP_SINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	CUBICSPLINE_INTERPOLATION(fCubicSplineLUT8, smpPtr, posFrac) \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	WINDOWED_SINC_INTERPOLATION8(smpPtr, posFrac) \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
-#define RENDER_8BIT_SMP_MONO_CINTRP \
+#define RENDER_8BIT_SMP_MONO_SINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	CUBICSPLINE_INTERPOLATION(fCubicSplineLUT8, smpPtr, posFrac) \
-	fSample *= fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	WINDOWED_SINC_INTERPOLATION8(smpPtr, posFrac) \
+	dSample *= dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
-#define RENDER_16BIT_SMP_CINTRP \
+#define RENDER_16BIT_SMP_SINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	CUBICSPLINE_INTERPOLATION(fCubicSplineLUT16, smpPtr, posFrac) \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	WINDOWED_SINC_INTERPOLATION16(smpPtr, posFrac) \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
-#define RENDER_16BIT_SMP_MONO_CINTRP \
+#define RENDER_16BIT_SMP_MONO_SINTRP \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	CUBICSPLINE_INTERPOLATION(fCubicSplineLUT16, smpPtr, posFrac) \
-	fSample *= fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	WINDOWED_SINC_INTERPOLATION16(smpPtr, posFrac) \
+	dSample *= dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
-#define RENDER_8BIT_SMP_CINTRP_TAP_FIX  \
+/* Special left-edge case mixers to get proper tap data after one loop cycle.
+** These are only used with sinc interpolation on looped samples.
+*/
+
+#define RENDER_8BIT_SMP_SINTRP_TAP_FIX  \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	s0 = (smpPtr != loopStartPtr) ? smpPtr[-1] : fTapFixSample; \
-	s1 = smpPtr[0]; \
-	s2 = smpPtr[1]; \
-	s3 = smpPtr[2]; \
-	CUBICSPLINE_INTERPOLATION_CUSTOM(fCubicSplineLUT8, posFrac) \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	if (smpPtr <= leftEdgePtr) \
+	{ \
+		const double *tapData = &v->dLeftEdgeTaps[(int32_t)(smpPtr - loopStartPtr)]; \
+		WINDOWED_SINC_INTERPOLATION8(tapData, posFrac) \
+	} \
+	else \
+	{ \
+		WINDOWED_SINC_INTERPOLATION8(smpPtr, posFrac) \
+	} \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
-#define RENDER_8BIT_SMP_MONO_CINTRP_TAP_FIX \
+#define RENDER_8BIT_SMP_MONO_SINTRP_TAP_FIX \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	s0 = (smpPtr != loopStartPtr) ? smpPtr[-1] : fTapFixSample; \
-	s1 = smpPtr[0]; \
-	s2 = smpPtr[1]; \
-	s3 = smpPtr[2]; \
-	CUBICSPLINE_INTERPOLATION_CUSTOM(fCubicSplineLUT8, posFrac) \
-	fSample *= fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	if (smpPtr <= leftEdgePtr) \
+	{ \
+		const double *tapData = &v->dLeftEdgeTaps[(int32_t)(smpPtr - loopStartPtr)]; \
+		WINDOWED_SINC_INTERPOLATION8(tapData, posFrac) \
+	} \
+	else \
+	{ \
+		WINDOWED_SINC_INTERPOLATION8(smpPtr, posFrac) \
+	} \
+	dSample *= dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
-#define RENDER_16BIT_SMP_CINTRP_TAP_FIX \
+#define RENDER_16BIT_SMP_SINTRP_TAP_FIX \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	s0 = (smpPtr != loopStartPtr) ? smpPtr[-1] : fTapFixSample; \
-	s1 = smpPtr[0]; \
-	s2 = smpPtr[1]; \
-	s3 = smpPtr[2]; \
-	CUBICSPLINE_INTERPOLATION_CUSTOM(fCubicSplineLUT16, posFrac) \
-	*fMixBufferL++ += fSample * fVolL; \
-	*fMixBufferR++ += fSample * fVolR; \
+	if (smpPtr <= leftEdgePtr) \
+	{ \
+		const double *tapData = &v->dLeftEdgeTaps[(int32_t)(smpPtr - loopStartPtr)]; \
+		WINDOWED_SINC_INTERPOLATION16(tapData, posFrac) \
+	} \
+	else \
+	{ \
+		WINDOWED_SINC_INTERPOLATION16(smpPtr, posFrac) \
+	} \
+	*dMixBufferL++ += dSample * dVolL; \
+	*dMixBufferR++ += dSample * dVolR; \
 
-#define RENDER_16BIT_SMP_MONO_CINTRP_TAP_FIX \
+#define RENDER_16BIT_SMP_MONO_SINTRP_TAP_FIX \
 	assert(smpPtr >= base && smpPtr < base+v->end); \
-	s0 = (smpPtr != loopStartPtr) ? smpPtr[-1] : fTapFixSample; \
-	s1 = smpPtr[0]; \
-	s2 = smpPtr[1]; \
-	s3 = smpPtr[2]; \
-	CUBICSPLINE_INTERPOLATION_CUSTOM(fCubicSplineLUT16, posFrac) \
-	fSample *= fVolL; \
-	*fMixBufferL++ += fSample; \
-	*fMixBufferR++ += fSample; \
+	if (smpPtr <= leftEdgePtr) \
+	{ \
+		const double *tapData = &v->dLeftEdgeTaps[(int32_t)(smpPtr - loopStartPtr)]; \
+		WINDOWED_SINC_INTERPOLATION16(tapData, posFrac) \
+	} \
+	else \
+	{ \
+		WINDOWED_SINC_INTERPOLATION16(smpPtr, posFrac) \
+	} \
+	dSample *= dVolL; \
+	*dMixBufferL++ += dSample; \
+	*dMixBufferR++ += dSample; \
 
 /* ----------------------------------------------------------------------- */
 /*                      SAMPLES-TO-MIX LIMITING MACROS                     */
@@ -267,6 +301,11 @@
 		i = 65535; \
 	\
 	i = (i << 16) | ((uint32_t)(posFrac >> 16) ^ 0xFFFF); \
+	\
+	/* This is hackish, but fast. This is sometimes off by one (-1), so */ \
+	/* we need to do another cycle to reach the end of the sample. The */ \
+	/* error is never +1, it's always below (safe). */ \
+	\
 	samplesToMix = ((int64_t)i * v->revDelta) >> 32; \
 	samplesToMix++; \
 	\
@@ -295,8 +334,8 @@
 #define LIMIT_MIX_NUM_RAMP \
 	if (v->volRampSamples == 0) \
 	{ \
-		fVolLDelta = 0; \
-		fVolRDelta = 0; \
+		dVolLDelta = 0.0; \
+		dVolRDelta = 0.0; \
 		\
 		if (v->isFadeOutVoice) \
 		{ \
@@ -315,7 +354,7 @@
 #define LIMIT_MIX_NUM_MONO_RAMP \
 	if (v->volRampSamples == 0) \
 	{ \
-		fVolLDelta = 0; \
+		dVolLDelta = 0.0; \
 		if (v->isFadeOutVoice) \
 		{ \
 			v->active = false; /* volume ramp fadeout-voice is done, shut it down */ \
--- a/src/mixer/ft2_silence_mix.c
+++ b/src/mixer/ft2_silence_mix.c
@@ -1,27 +1,58 @@
 #include <stdint.h>
 #include "../ft2_audio.h"
-#include "ft2_silence_mix.h"
 
+// used for the audio channel mixer when voice volume is zero
+
 void silenceMixRoutine(voice_t *v, int32_t numSamples)
 {
-	int32_t pos;
-	uint64_t posFrac;
+	const uint64_t newPos = v->delta * (uint64_t)numSamples;
+	const uint32_t addPos = (uint32_t)(newPos >> MIXER_FRAC_BITS);
+	uint64_t addFrac = newPos & MIXER_FRAC_MASK;
 
-	SILENCE_MIX_INC_POS
+	addFrac += v->posFrac;
+	int32_t pos = v->pos + addPos + (uint32_t)(addFrac >> MIXER_FRAC_BITS);
+	uint64_t  posFrac = addFrac & MIXER_FRAC_MASK;
 
+	if (pos < v->end) // we haven't reached the sample's end yet
+	{
+		v->posFrac = posFrac;
+		v->pos = pos;
+		return;
+	}
+
+	// end of sample (or loop) reached
+
 	if (v->loopType == LOOP_DISABLED)
 	{
-		SILENCE_MIX_NO_LOOP
+		v->active = false; // shut down voice
+		return;
 	}
-	else if (v->loopType == LOOP_FORWARD)
+
+	if (v->loopType == LOOP_FORWARD)
 	{
-		SILENCE_MIX_LOOP
+		if (v->loopLength >= 2)
+			pos = v->loopStart + ((pos - v->end) % v->loopLength);
+		else
+			pos = v->loopStart;
 	}
 	else // pingpong loop
 	{
-		SILENCE_MIX_BIDI_LOOP
+		if (v->loopLength >= 2)
+		{
+			const int32_t overflow = pos - v->end;
+			const int32_t cycles = overflow / v->loopLength;
+			const int32_t phase = overflow % v->loopLength;
+
+			pos = v->loopStart + phase;
+			v->backwards ^= !(cycles & 1);
+		}
+		else
+		{
+			pos = v->loopStart;
+		}
 	}
 
+	v->hasLooped = true;
 	v->posFrac = posFrac;
 	v->pos = pos;
 }
--- a/src/mixer/ft2_silence_mix.h
+++ b/src/mixer/ft2_silence_mix.h
@@ -1,53 +1,6 @@
 #pragma once
 
 #include <stdint.h>
-#include <assert.h>
 #include "../ft2_audio.h"
-
-#define SILENCE_MIX_NO_LOOP \
-	if (pos >= v->end) \
-	{ \
-		v->active = false; /* shut down voice */ \
-		return; \
-	} \
-
-#define SILENCE_MIX_INC_POS \
-	const uint64_t newPos = v->delta * (uint64_t)numSamples; \
-	const uint32_t addPos = (uint32_t)(newPos >> MIXER_FRAC_BITS); \
-	uint64_t addFrac = newPos & MIXER_FRAC_MASK; \
-	\
-	addFrac += v->posFrac; \
-	pos = v->pos + addPos + (uint32_t)(addFrac >> MIXER_FRAC_BITS); \
-	posFrac = addFrac & MIXER_FRAC_MASK; \
-
-#define SILENCE_MIX_LOOP \
-	if (pos >= v->end) \
-	{ \
-		if (v->loopLength >= 2) \
-			pos = v->loopStart + ((pos - v->end) % v->loopLength); \
-		else \
-			pos = v->loopStart; \
-		\
-		v->hasLooped = true; \
-	} \
-
-#define SILENCE_MIX_BIDI_LOOP \
-	if (pos >= v->end) \
-	{ \
-		if (v->loopLength >= 2) \
-		{ \
-			const int32_t overflow = pos - v->end; \
-			const int32_t cycles = overflow / v->loopLength; \
-			const int32_t phase = overflow % v->loopLength; \
-			\
-			pos = v->loopStart + phase; \
-			v->backwards ^= !(cycles & 1); \
-		} \
-		else \
-		{ \
-			pos = v->loopStart; \
-		} \
-		v->hasLooped = true; \
-	} \
 
 void silenceMixRoutine(voice_t *v, int32_t numSamples);
--- /dev/null
+++ b/src/mixer/ft2_windowed_sinc.c
@@ -1,0 +1,99 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <math.h>
+#include "ft2_windowed_sinc.h"
+
+// globalized
+double *gKaiserSinc = NULL;
+double *gDownSample1 = NULL;
+double *gDownSample2 = NULL;
+
+/* Code taken from the OpenMPT project, which has a BSD
+** license which is compatible with this this project.
+**
+** The code has been slightly modified.
+*/
+
+static double Izero(double y) // Compute Bessel function Izero(y) using a series approximation
+{
+	double s = 1.0, ds = 1.0, d = 0.0;
+
+	const double epsilon = 1E-9; // 8bb: 1E-7 -> 1E-9 for added precision (still fast to calculate)
+
+	do
+	{
+		d = d + 2.0;
+		ds = ds * (y * y) / (d * d);
+		s = s + ds;
+	}
+	while (ds > epsilon * s);
+
+	return s;
+}
+
+static void getSinc(double *dLUTPtr, const double beta, const double cutoff)
+{
+	const double izeroBeta = Izero(beta);
+	const double kPi = 4.0 * atan(1.0) * cutoff; // M_PI can't be trusted
+
+	for (int32_t i = 0; i < SINC_LUT_LEN; i++)
+	{
+		double dSinc;
+		int32_t ix = (SINC_TAPS-1) - (i & (SINC_TAPS-1));
+
+		ix = (ix * SINC_PHASES) + (i >> SINC_TAPS_BITS);
+		if (ix == SINC_MID_TAP)
+		{
+			dSinc = 1.0;
+		}
+		else
+		{
+			const double x = (ix - SINC_MID_TAP) * (1.0 / SINC_PHASES);
+			const double xPi = x * kPi;
+
+			const double xMul = 1.0 / ((SINC_TAPS/2) * (SINC_TAPS/2));
+			dSinc = sin(xPi) * Izero(beta * sqrt(1.0 - x * x * xMul)) / (izeroBeta * xPi); // Kaiser window
+		}
+
+		dLUTPtr[i] = dSinc * cutoff;
+	}
+}
+
+bool calcWindowedSincTables(void)
+{
+	gKaiserSinc  = (double *)malloc(SINC_LUT_LEN * sizeof (double));
+	gDownSample1 = (double *)malloc(SINC_LUT_LEN * sizeof (double));
+	gDownSample2 = (double *)malloc(SINC_LUT_LEN * sizeof (double));
+
+	if (gKaiserSinc == NULL || gDownSample1 == NULL || gDownSample2 == NULL)
+		return false;
+
+	// OpenMPT parameters
+	getSinc(gKaiserSinc, 9.6377, 0.97);
+	getSinc(gDownSample1, 8.5, 0.5);
+	getSinc(gDownSample2, 2.7625, 0.425);
+
+	return true;
+}
+
+void freeWindowedSincTables(void)
+{
+	if (gKaiserSinc != NULL)
+	{
+		free(gKaiserSinc);
+		gKaiserSinc = NULL;
+	}
+
+	if (gDownSample1 != NULL)
+	{
+		free(gDownSample1);
+		gDownSample1 = NULL;
+	}
+
+	if (gDownSample2 != NULL)
+	{
+		free(gDownSample2);
+		gDownSample2 = NULL;
+	}
+}
--- /dev/null
+++ b/src/mixer/ft2_windowed_sinc.h
@@ -1,0 +1,33 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifndef MIXER_FRAC_BITS
+#define MIXER_FRAC_BITS 32
+#endif
+
+// if you change this, also change SINC_PHASES_BITS (>4096 makes little sense)
+#define SINC_PHASES 4096
+#define SINC_PHASES_BITS 12 /* log2(SINC_PHASES) */
+
+// don't change these!
+
+#define SINC_TAPS 8
+#define SINC_TAPS_BITS 3
+#define SINC_LUT_LEN (SINC_TAPS * SINC_PHASES)
+#define SINC_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC_TAPS_BITS))
+#define SINC_FMASK ((SINC_TAPS*SINC_PHASES)-SINC_TAPS)
+
+#define SINC_LEFT_TAPS ((SINC_TAPS/2)-1)
+#define SINC_RIGHT_TAPS (SINC_TAPS/2)
+
+// for LUT calculation
+#define SINC_MID_TAP ((SINC_TAPS/2)*SINC_PHASES)
+
+extern double *gKaiserSinc;
+extern double *gDownSample1;
+extern double *gDownSample2;
+
+bool calcWindowedSincTables(void);
+void freeWindowedSincTables(void);
--- a/vs2019_project/ft2-clone/ft2-clone.vcxproj
+++ b/vs2019_project/ft2-clone/ft2-clone.vcxproj
@@ -336,7 +336,7 @@
     <ClCompile Include="..\..\src\gfxdata\ft2_bmp_instr.c" />
     <ClCompile Include="..\..\src\gfxdata\ft2_bmp_looppins.c" />
     <ClCompile Include="..\..\src\gfxdata\ft2_bmp_scopes.c" />
-    <ClCompile Include="..\..\src\mixer\ft2_cubicspline.c" />
+    <ClCompile Include="..\..\src\mixer\ft2_windowed_sinc.c" />
     <ClCompile Include="..\..\src\mixer\ft2_mix.c" />
     <ClCompile Include="..\..\src\mixer\ft2_center_mix.c" />
     <ClCompile Include="..\..\src\mixer\ft2_silence_mix.c" />
@@ -400,7 +400,7 @@
     <ClInclude Include="..\..\src\ft2_unicode.h" />
     <ClInclude Include="..\..\src\ft2_video.h" />
     <ClInclude Include="..\..\src\ft2_wav_renderer.h" />
-    <ClInclude Include="..\..\src\mixer\ft2_cubicspline.h" />
+    <ClInclude Include="..\..\src\mixer\ft2_windowed_sinc.h" />
     <ClInclude Include="..\..\src\mixer\ft2_mix.h" />
     <ClInclude Include="..\..\src\mixer\ft2_mix_macros.h" />
     <ClInclude Include="..\..\src\mixer\ft2_center_mix.h" />
--- a/vs2019_project/ft2-clone/ft2-clone.vcxproj.filters
+++ b/vs2019_project/ft2-clone/ft2-clone.vcxproj.filters
@@ -84,7 +84,7 @@
     <ClCompile Include="..\..\src\mixer\ft2_silence_mix.c">
       <Filter>mixer</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\mixer\ft2_cubicspline.c">
+    <ClCompile Include="..\..\src\mixer\ft2_windowed_sinc.c">
       <Filter>mixer</Filter>
     </ClCompile>
   </ItemGroup>
@@ -233,7 +233,7 @@
     <ClInclude Include="..\..\src\mixer\ft2_silence_mix.h">
       <Filter>mixer</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\src\mixer\ft2_cubicspline.h">
+    <ClInclude Include="..\..\src\mixer\ft2_windowed_sinc.h">
       <Filter>mixer</Filter>
     </ClInclude>
   </ItemGroup>