Fixed up the Lanczos interpolation in NCSF (thanks to kode54), also allowed the NCSF plugin to use 32-bit samples in it's GenerateSamples function.
Fixed up the Lanczos interpolation in NCSF (thanks to kode54), also allowed the NCSF plugin to use 32-bit samples in it's GenerateSamples function.

--- a/src/in_ncsf/SSEQPlayer/Channel.cpp
+++ b/src/in_ncsf/SSEQPlayer/Channel.cpp
@@ -1,7 +1,7 @@
 /*
  * SSEQ Player - Channel structures
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Adapted from source code of FeOS Sound System
  * By fincs
@@ -44,7 +44,7 @@
 
 bool Channel::initializedLUTs = false;
 double Channel::cosine_lut[Channel::COSINE_RESOLUTION];
-double Channel::lanczos_lut[Channel::LANCZOS_SAMPLES];
+double Channel::lanczos_lut[Channel::LANCZOS_SAMPLES + 1];
 
 #ifndef M_PI
 static const double M_PI = 3.14159265358979323846;
@@ -65,7 +65,7 @@
 		for (unsigned i = 0; i < COSINE_RESOLUTION; ++i)
 			this->cosine_lut[i] = (1.0 - std::cos((static_cast<double>(i) / COSINE_RESOLUTION) * M_PI)) * 0.5;
 		double dx = static_cast<double>(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0;
-		for (unsigned i = 0; i < LANCZOS_SAMPLES; ++i, x += dx)
+		for (unsigned i = 0; i <= LANCZOS_SAMPLES; ++i, x += dx)
 			this->lanczos_lut[i] = std::abs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0;
 		this->initializedLUTs = true;
 	}
@@ -604,37 +604,48 @@
 	double ratio = this->reg.samplePosition;
 	ratio -= static_cast<int32_t>(ratio);
 
-	const auto &data = &this->sampleHistory[this->sampleHistoryPtr + 5];
-	int32_t a = data[0], b = data[1];
-
-	double c0, c1, c2, c3, c4, c5;
-	if (this->ply->interpolation > INTERPOLATION_COSINE)
-	{
-		int32_t c = data[2], z = data[-1];
+	const auto &data = &this->sampleHistory[this->sampleHistoryPtr + 16];
+
+	if (this->ply->interpolation == INTERPOLATION_LANCZOS)
+	{
+		double kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0;
+		int i = LANCZOS_WIDTH, shift = static_cast<int>(std::floor(ratio * LANCZOS_RESOLUTION));
+		int step = this->reg.sampleIncrease > 1.0 ? static_cast<int>(LANCZOS_RESOLUTION / this->reg.sampleIncrease) : LANCZOS_RESOLUTION;
+		for (; i >= -static_cast<int>(LANCZOS_WIDTH - 1); --i)
+		{
+			int pos = i * step;
+			kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = this->lanczos_lut[std::abs(shift - pos)];
+		}
+		double sum = 0.0;
+		for (i = 0; i < static_cast<int>(LANCZOS_WIDTH * 2); ++i)
+			sum += data[i - static_cast<int>(LANCZOS_WIDTH) + 1] * kernel[i];
+		return static_cast<int32_t>(sum / kernel_sum);
+	}
+	else if (this->ply->interpolation > INTERPOLATION_COSINE)
+	{
+		double c0, c1, c2, c3, c4, c5;
 
 		if (this->ply->interpolation > INTERPOLATION_4POINTBSPLINE)
 		{
-			int32_t d = data[3], y = data[-2];
-
 			if (this->ply->interpolation == INTERPOLATION_6POINTBSPLINE)
 			{
-				double ym2py2 = y + c, ym1py1 = z + b;
-				double y2mym2 = c - y, y1mym1 = b - z;
+				double ym2py2 = data[-2] + data[2], ym1py1 = data[-1] + data[1];
+				double y2mym2 = data[2] - data[-2], y1mym1 = data[1] - data[-1];
 				double sixthym1py1 = 1 / 6.0 * ym1py1;
-				c0 = 1 / 120.0 * ym2py2 + 13 / 60.0 * ym1py1 + 0.55 * a;
+				c0 = 1 / 120.0 * ym2py2 + 13 / 60.0 * ym1py1 + 0.55 * data[0];
 				c1 = 1 / 24.0 * y2mym2 + 5 / 12.0 * y1mym1;
-				c2 = 1 / 12.0 * ym2py2 + sixthym1py1 - 0.5 * a;
+				c2 = 1 / 12.0 * ym2py2 + sixthym1py1 - 0.5 * data[0];
 				c3 = 1 / 12.0 * y2mym2 - 1 / 6.0 * y1mym1;
-				c4 = 1 / 24.0 * ym2py2 - sixthym1py1 + 0.25 * a;
-				c5 = 1 / 120.0 * (d - y) + 1 / 24.0 * (z - c) + 1 / 12.0 * (b - a);
+				c4 = 1 / 24.0 * ym2py2 - sixthym1py1 + 0.25 * data[0];
+				c5 = 1 / 120.0 * (data[3] - data[-2]) + 1 / 24.0 * (data[-1] - data[2]) + 1 / 12.0 * (data[1] - data[0]);
 				return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
 			}
-			else if (this->ply->interpolation == INTERPOLATION_6POINTOSCULATING)
+			else // INTERPOLATION_6POINTOSCULATING
 			{
 				ratio -= 0.5;
-				double even1 = y + d, odd1 = y - d;
-				double even2 = z + c, odd2 = z - c;
-				double even3 = a + b, odd3 = a - b;
+				double even1 = data[-2] + data[3], odd1 = data[-2] - data[3];
+				double even2 = data[-1] + data[2], odd2 = data[-1] - data[2];
+				double even3 = data[0] + data[1], odd3 = data[0] - data[1];
 				c0 = 0.01171875 * even1 - 0.09765625 * even2 + 0.5859375 * even3;
 				c1 = 0.2109375 * odd2 - 281 / 192.0 * odd3 - 13 / 384.0 * odd1;
 				c2 = 0.40625 * even2 - 17 / 48.0 * even3 - 5 / 96.0 * even1;
@@ -643,34 +654,21 @@
 				c5 = 25 / 24.0 * odd2 - 25 / 12.0 * odd3 - 5 / 24.0 * odd1;
 				return static_cast<int32_t>(((((c5 * ratio + c4) * ratio + c3) * ratio + c2) * ratio + c1) * ratio + c0);
 			}
-			else // INTERPOLATION_6POINTLANCZOS
-			{
-				double kernel[6], kernel_sum = 0.0;
-				int i = 3, shift = static_cast<int>(std::floor(ratio * LANCZOS_RESOLUTION));
-				for (; i >= -2; --i)
-				{
-					int pos = i * LANCZOS_RESOLUTION;
-					kernel_sum += kernel[i + 2] = this->lanczos_lut[std::abs(shift - pos)];
-				}
-				for (i = 0; i < 6; ++i)
-					kernel[i] /= kernel_sum;
-				return static_cast<int32_t>(y * kernel[0] + z * kernel[1] + a * kernel[2] + b * kernel[3] + c * kernel[4] + d * kernel[5]);
-			}
 		}
 		else // INTERPOLATION_4POINTBSPLINE
 		{
-			double ym1py1 = z + b;
-			c0 = 1 / 6.0 * ym1py1 + 2 / 3.0 * a;
-			c1 = 0.5 * (b - z);
-			c2 = 0.5 * ym1py1 - a;
-			c3 = 0.5 * (a - b) + 1 / 6.0 * (c - z);
+			double ym1py1 = data[-1] + data[1];
+			c0 = 1 / 6.0 * ym1py1 + 2 / 3.0 * data[0];
+			c1 = 0.5 * (data[1] - data[-1]);
+			c2 = 0.5 * ym1py1 - data[0];
+			c3 = 0.5 * (data[0] - data[1]) + 1 / 6.0 * (data[2] - data[-1]);
 			return static_cast<int32_t>(((c3 * ratio + c2) * ratio + c1) * ratio + c0);
 		}
 	}
 	else if (this->ply->interpolation == INTERPOLATION_COSINE)
-		return static_cast<int32_t>(a + this->cosine_lut[static_cast<unsigned>(ratio * COSINE_RESOLUTION)] * (b - a));
+		return static_cast<int32_t>(data[0] + this->cosine_lut[static_cast<unsigned>(ratio * COSINE_RESOLUTION)] * (data[1] - data[0]));
 	else // INTERPOLATION_LINEAR
-		return static_cast<int32_t>(a + ratio * (b - a));
+		return static_cast<int32_t>(data[0] + ratio * (data[1] - data[0]));
 }
 
 int32_t Channel::GenerateSample()
@@ -732,9 +730,9 @@
 
 		while (loc != newloc)
 		{
-			this->sampleHistory[this->sampleHistoryPtr] = this->sampleHistory[this->sampleHistoryPtr + 8] = this->reg.source->dataptr[loc++];
-
-			this->sampleHistoryPtr = (this->sampleHistoryPtr + 1) & 7;
+			this->sampleHistory[this->sampleHistoryPtr] = this->sampleHistory[this->sampleHistoryPtr + 32] = this->reg.source->dataptr[loc++];
+
+			this->sampleHistoryPtr = (this->sampleHistoryPtr + 1) & 31;
 
 			if (loc >= this->reg.totalLength)
 				loc -= this->reg.length;

--- a/src/in_ncsf/SSEQPlayer/Channel.h
+++ b/src/in_ncsf/SSEQPlayer/Channel.h
@@ -1,7 +1,7 @@
 /*
  * SSEQ Player - Channel structures
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Adapted from source code of FeOS Sound System
  * By fincs
@@ -132,7 +132,7 @@
 	 * simplify the case of wrapping. Thanks to kode54 for providing this.
 	 */
 	uint32_t sampleHistoryPtr;
-	int16_t sampleHistory[16];
+	int16_t sampleHistory[64];
 
 	/*
 	 * Lookup tables for the cosine and Lanczos Sinc interpolations, to
@@ -143,10 +143,10 @@
 	static bool initializedLUTs;
 	static const unsigned COSINE_RESOLUTION = 8192;
 	static const unsigned LANCZOS_RESOLUTION = 8192;
-	static const unsigned LANCZOS_WIDTH = 3;
+	static const unsigned LANCZOS_WIDTH = 8;
 	static const unsigned LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH;
 	static double cosine_lut[COSINE_RESOLUTION];
-	static double lanczos_lut[LANCZOS_SAMPLES];
+	static double lanczos_lut[LANCZOS_SAMPLES + 1];
 
 	Channel();
 

--- a/src/in_ncsf/SSEQPlayer/consts.h
+++ b/src/in_ncsf/SSEQPlayer/consts.h
@@ -1,7 +1,7 @@
 /*
  * SSEQ Player - Constants/Macros
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Adapted from source code of FeOS Sound System
  * By fincs
@@ -59,7 +59,7 @@
 	INTERPOLATION_4POINTBSPLINE,
 	INTERPOLATION_6POINTOSCULATING,
 	INTERPOLATION_6POINTBSPLINE,
-	INTERPOLATION_6POINTLANCZOS
+	INTERPOLATION_LANCZOS
 };
 
 #endif

--- a/src/in_ncsf/XSFConfig_NCSF.cpp
+++ b/src/in_ncsf/XSFConfig_NCSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - NCSF configuration
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Partially based on the vio*sf framework
  */
@@ -42,7 +42,7 @@
 
 unsigned XSFConfig::initSampleRate = 44100;
 std::wstring XSFConfig::commonName = L"NCSF Decoder";
-std::wstring XSFConfig::versionNumber = L"1.6";
+std::wstring XSFConfig::versionNumber = L"1.7";
 unsigned XSFConfig_NCSF::initInterpolation = 5;
 std::wstring XSFConfig_NCSF::initMutes = L"0000000000000000";
 
@@ -101,7 +101,7 @@
 			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 3rd-order B-spline"));
 			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order Osculating"));
 			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order B-spline"));
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point Lanczos (Sinc)"));
+			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Lanczos (Sinc)"));
 			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, this->interpolation, 0);
 			// Mutes
 			for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)

--- a/src/in_ncsf/XSFPlayer_NCSF.cpp
+++ b/src/in_ncsf/XSFPlayer_NCSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - NCSF Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Partially based on the vio*sf framework
  *
@@ -101,11 +101,13 @@
 
 XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer()
 {
+	this->uses32BitSamplesClampedTo16Bit = true;
 	this->xSF.reset(new XSFFile(filename, 8, 12));
 }
 
 XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer()
 {
+	this->uses32BitSamplesClampedTo16Bit = true;
 	this->xSF.reset(new XSFFile(filename, 8, 12));
 }
 
@@ -130,14 +132,6 @@
 	return XSFPlayer::Load();
 }
 
-template<typename T1, typename T2> static inline void clamp(T1 &valueToClamp, const T2 &minValue, const T2 &maxValue)
-{
-	if (valueToClamp < minValue)
-		valueToClamp = minValue;
-	else if (valueToClamp > maxValue)
-		valueToClamp = maxValue;
-}
-
 static inline int32_t muldiv7(int32_t val, uint8_t mul)
 {
 	return mul == 127 ? val : ((val * mul) >> 7);
@@ -182,13 +176,14 @@
 		leftChannel = muldiv7(leftChannel, this->sseqVol);
 		rightChannel = muldiv7(rightChannel, this->sseqVol);
 
-		clamp(leftChannel, -0x8000, 0x7FFF);
-		clamp(rightChannel, -0x8000, 0x7FFF);
-
 		buf[offset++] = leftChannel & 0xFF;
 		buf[offset++] = (leftChannel >> 8) & 0xFF;
+		buf[offset++] = (leftChannel >> 16) & 0xFF;
+		buf[offset++] = (leftChannel >> 24) & 0xFF;
 		buf[offset++] = rightChannel & 0xFF;
 		buf[offset++] = (rightChannel >> 8) & 0xFF;
+		buf[offset++] = (rightChannel >> 16) & 0xFF;
+		buf[offset++] = (rightChannel >> 24) & 0xFF;
 
 		if (this->secondsIntoPlayback > this->secondsUntilNextClock)
 		{

--- a/src/in_xsf_framework/XSFCommon.h
+++ b/src/in_xsf_framework/XSFCommon.h
@@ -1,7 +1,7 @@
 /*
  * xSF - Common functions
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Partially based on the vio*sf framework
  */
@@ -66,6 +66,15 @@
 	return value + 1;
 }
 
+// Clamp a value between a minimum and maximum value
+template<typename T1, typename T2> inline void clamp(T1 &valueToClamp, const T2 &minValue, const T2 &maxValue)
+{
+	if (valueToClamp < minValue)
+		valueToClamp = minValue;
+	else if (valueToClamp > maxValue)
+		valueToClamp = maxValue;
+}
+
 inline bool FileExists(const std::string &filename)
 {
 	std::ifstream file((filename.c_str()));

--- a/src/in_xsf_framework/XSFPlayer.cpp
+++ b/src/in_xsf_framework/XSFPlayer.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - Core Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Partially based on the vio*sf framework
  */
@@ -14,13 +14,14 @@
 extern XSFConfig *xSFConfig;
 
 XSFPlayer::XSFPlayer() : xSF(), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0),
-	prevSampleL(CHECK_SILENCE_BIAS), prevSampleR(CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false)
+	prevSampleL(CHECK_SILENCE_BIAS), prevSampleR(CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false), uses32BitSamplesClampedTo16Bit(false)
 {
 }
 
 XSFPlayer::XSFPlayer(const XSFPlayer &xSFPlayer) : xSF(new XSFFile()), sampleRate(xSFPlayer.sampleRate), detectedSilenceSample(xSFPlayer.detectedSilenceSample), detectedSilenceSec(xSFPlayer.detectedSilenceSec),
 	skipSilenceOnStartSec(xSFPlayer.skipSilenceOnStartSec), lengthSample(xSFPlayer.lengthSample), fadeSample(xSFPlayer.fadeSample), currentSample(xSFPlayer.currentSample), prevSampleL(xSFPlayer.prevSampleL),
-	prevSampleR(xSFPlayer.prevSampleR), lengthInMS(xSFPlayer.lengthInMS), fadeInMS(xSFPlayer.fadeInMS), volume(xSFPlayer.volume), ignoreVolume(xSFPlayer.ignoreVolume)
+	prevSampleR(xSFPlayer.prevSampleR), lengthInMS(xSFPlayer.lengthInMS), fadeInMS(xSFPlayer.fadeInMS), volume(xSFPlayer.volume), ignoreVolume(xSFPlayer.ignoreVolume),
+	uses32BitSamplesClampedTo16Bit(xSFPlayer.uses32BitSamplesClampedTo16Bit)
 {
 	*this->xSF = *xSFPlayer.xSF;
 }
@@ -45,6 +46,7 @@
 		this->fadeInMS = xSFPlayer.fadeInMS;
 		this->volume = xSFPlayer.volume;
 		this->ignoreVolume = xSFPlayer.ignoreVolume;
+		this->uses32BitSamplesClampedTo16Bit = xSFPlayer.uses32BitSamplesClampedTo16Bit;
 	}
 	return *this;
 }
@@ -54,17 +56,33 @@
 	bool endFlag = false;
 	unsigned detectSilence = xSFConfig->GetDetectSilenceSec();
 	unsigned pos = 0, bufsize = buf.size() >> 2;
+	std::vector<uint8_t> trueBuffer;
+	if (this->uses32BitSamplesClampedTo16Bit)
+		trueBuffer.resize(bufsize << 3);
+	else
+		trueBuffer.resize(bufsize << 2);
+	auto longBuffer = std::vector<uint8_t>(bufsize << 3);
+	int32_t *bufLong = reinterpret_cast<int32_t *>(&longBuffer[0]);
 	while (pos < bufsize)
 	{
 		unsigned remain = bufsize - pos, offset = pos;
-		this->GenerateSamples(buf, pos << 1, remain);
+		this->GenerateSamples(trueBuffer, pos << (this->uses32BitSamplesClampedTo16Bit ? 2 : 1), remain);
+		if (this->uses32BitSamplesClampedTo16Bit)
+		{
+			int32_t *trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]);
+			std::copy(&trueBufLong[0], &trueBufLong[bufsize << 1], &bufLong[0]);
+		}
+		else
+		{
+			int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]);
+			std::copy(&trueBufShort[0], &trueBufShort[bufsize << 1], &bufLong[0]);
+		}
 		if (detectSilence || skipSilenceOnStartSec)
 		{
 			unsigned skipOffset = 0;
 			for (unsigned ofs = 0; ofs < remain; ++ofs)
 			{
-				short *bufShort = reinterpret_cast<short *>(&buf[0]);
-				unsigned long sampleL = bufShort[2 * (offset + ofs)], sampleR = bufShort[2 * (offset + ofs) + 1];
+				uint32_t sampleL = bufLong[2 * (offset + ofs)], sampleR = bufLong[2 * (offset + ofs) + 1];
 				bool silence = (sampleL + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleL <= CHECK_SILENCE_LEVEL * 2 &&
 					(sampleR + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleR <= CHECK_SILENCE_LEVEL * 2;
 
@@ -101,9 +119,9 @@
 			{
 				if (skipOffset)
 				{
-					auto tmpBuf = std::vector<uint8_t>(2 * skipOffset);
-					memcpy(&tmpBuf[0], &buf[offset + 2 * skipOffset], 2 * skipOffset);
-					memcpy(&buf[offset], &tmpBuf[0], 2 * skipOffset);
+					auto tmpBuf = std::vector<int32_t>((bufsize - skipOffset) << 1);
+					std::copy(&bufLong[(offset + skipOffset) << 1], &bufLong[bufsize << 1], &tmpBuf[0]);
+					std::copy(&tmpBuf[0], &tmpBuf[(bufsize - skipOffset) << 1], &bufLong[offset << 1]);
 					pos += skipOffset;
 				}
 				else
@@ -112,6 +130,19 @@
 		}
 		else
 			pos += remain;
+		if (pos < bufsize)
+		{
+			if (this->uses32BitSamplesClampedTo16Bit)
+			{
+				int32_t *trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]);
+				std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufLong[0]);
+			}
+			else
+			{
+				int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]);
+				std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]);
+			}
+		}
 	}
 
 	/* Detect end of song */
@@ -133,27 +164,42 @@
 	if (!this->ignoreVolume && (!fEqual(this->volume, 1.0) || !fEqual(xSFConfig->GetVolume(), 1.0)))
 	{
 		double scale = this->volume * xSFConfig->GetVolume();
-		short *bufShort = reinterpret_cast<short *>(&buf[0]);
 		for (unsigned ofs = 0; ofs < bufsize; ++ofs)
 		{
-			double s1 = bufShort[2 * ofs] * scale, s2 = bufShort[2 * ofs + 1] * scale;
-			if (s1 > 0x7FFF)
-				s1 = 0x7FFF;
-			else if (s1 < -0x8000)
-				s1 = -0x8000;
-			if (s2 > 0x7FFF)
-				s2 = 0x7FFF;
-			else if (s2 < -0x8000)
-				s2 = -0x8000;
-			bufShort[2 * ofs] = static_cast<short>(s1);
-			bufShort[2 * ofs + 1] = static_cast<short>(s2);
-		}
+			double s1 = bufLong[2 * ofs] * scale, s2 = bufLong[2 * ofs + 1] * scale;
+			if (!this->uses32BitSamplesClampedTo16Bit)
+			{
+				clamp(s1, -0x7FFF, 0x8000);
+				clamp(s2, -0x7FFF, 0x8000);
+			}
+			bufLong[2 * ofs] = static_cast<int32_t>(s1);
+			bufLong[2 * ofs + 1] = static_cast<int32_t>(s2);
+		}
+	}
+
+	if (this->uses32BitSamplesClampedTo16Bit)
+	{
+		int16_t *bufShort = reinterpret_cast<int16_t *>(&buf[0]);
+		for (unsigned ofs = 0; ofs < bufsize; ++ofs)
+		{
+			int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1];
+			clamp(s1, -0x7FFF, 0x8000);
+			clamp(s2, -0x7FFF, 0x8000);
+			bufShort[2 * ofs] = static_cast<int16_t>(s1);
+			bufShort[2 * ofs + 1] = static_cast<int16_t>(s2);
+		}
+	}
+	else
+	{
+		int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]);
+		std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]);
+		std::copy(&trueBuffer[0], &trueBuffer[bufsize << 2], &buf[0]);
 	}
 
 	/* Fading */
 	if (!xSFConfig->GetPlayInfinitely() && this->fadeSample && this->currentSample + bufsize >= this->lengthSample)
 	{
-		short *bufShort = reinterpret_cast<short *>(&buf[0]);
+		int16_t *bufShort = reinterpret_cast<int16_t *>(&buf[0]);
 		for (unsigned ofs = 0; ofs < bufsize; ++ofs)
 		{
 			if (this->currentSample + ofs >= this->lengthSample && this->currentSample + ofs < this->lengthSample + this->fadeSample)

--- a/src/in_xsf_framework/XSFPlayer.h
+++ b/src/in_xsf_framework/XSFPlayer.h
@@ -1,7 +1,7 @@
 /*
  * xSF - Core Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2013-04-26
  *
  * Partially based on the vio*sf framework
  */
@@ -19,15 +19,15 @@
 class XSFPlayer
 {
 protected:
-	static const unsigned CHECK_SILENCE_BIAS = 0x8000000;
-	static const unsigned CHECK_SILENCE_LEVEL = 7;
+	static const uint32_t CHECK_SILENCE_BIAS = 0x8000000;
+	static const uint32_t CHECK_SILENCE_LEVEL = 7;
 
 	std::unique_ptr<XSFFile> xSF;
 	unsigned sampleRate, detectedSilenceSample, detectedSilenceSec, skipSilenceOnStartSec, lengthSample, fadeSample, currentSample;
-	unsigned long prevSampleL, prevSampleR;
+	uint32_t prevSampleL, prevSampleR;
 	int lengthInMS, fadeInMS;
 	double volume;
-	bool ignoreVolume;
+	bool ignoreVolume, uses32BitSamplesClampedTo16Bit;
 
 	XSFPlayer();
 	XSFPlayer(const XSFPlayer &xSFPLayer);