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);