* Use enum class instead of enum (except for the enums for the resource IDs, not really necessary there).
* For NCSF specifically, included a function to convert an enum class to its underlying integral type (as this is needed for use with the std::bitset class).
* Cleanup headers so all the ones needed in a file are explicitly included even if they may possibly be included in another header.
* Used forward declarations in a few spots.
* Explicitly namespaced all (u)int*_t uses (this might seem like overkill, but it helps me see when the standard types are being used with a simple search for std::).
* Made sure it all builds with MinGW-w64 as well (both gcc and clang).
* Removed some std::move from DialogBuilder.cpp based on clang's warnings for that.
* Replaced use of std::copy_n on strings in DialogBuilder.cpp with my CopyToString functions that use wcscpy.
* Replaced CHAR_MIN/CHAR_MAX in eqstr.h and ltstr.h with std::numeric_limits<char>::min/max().
| ... | ... |
@@ -5,10 +5,13 @@ |
| 5 | 5 |
* Partially based on the vio*sf framework |
| 6 | 6 |
*/ |
| 7 | 7 |
|
| 8 |
-#include <cstring> |
|
| 9 |
-#include "XSFPlayer.h" |
|
| 10 |
-#include "XSFConfig.h" |
|
| 8 |
+#include <algorithm> |
|
| 9 |
+#include <limits> |
|
| 10 |
+#include <vector> |
|
| 11 |
+#include <cstdint> |
|
| 11 | 12 |
#include "XSFCommon.h" |
| 13 |
+#include "XSFConfig.h" |
|
| 14 |
+#include "XSFPlayer.h" |
|
| 12 | 15 |
|
| 13 | 16 |
extern XSFConfig *xSFConfig; |
| 14 | 17 |
|
| ... | ... |
@@ -50,26 +53,26 @@ XSFPlayer &XSFPlayer::operator=(const XSFPlayer &xSFPlayer) |
| 50 | 53 |
return *this; |
| 51 | 54 |
} |
| 52 | 55 |
|
| 53 |
-bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
|
| 56 |
+bool XSFPlayer::FillBuffer(std::vector<std::uint8_t> &buf, unsigned &samplesWritten) |
|
| 54 | 57 |
{
|
| 55 | 58 |
bool endFlag = false; |
| 56 | 59 |
unsigned detectSilence = xSFConfig->GetDetectSilenceSec(); |
| 57 | 60 |
unsigned pos = 0, bufsize = buf.size() >> 2; |
| 58 |
- auto trueBuffer = std::vector<uint8_t>(bufsize << (this->uses32BitSamplesClampedTo16Bit ? 3 : 2)); |
|
| 59 |
- auto longBuffer = std::vector<uint8_t>(bufsize << 3); |
|
| 60 |
- auto bufLong = reinterpret_cast<int32_t *>(&longBuffer[0]); |
|
| 61 |
+ auto trueBuffer = std::vector<std::uint8_t>(bufsize << (this->uses32BitSamplesClampedTo16Bit ? 3 : 2)); |
|
| 62 |
+ auto longBuffer = std::vector<std::uint8_t>(bufsize << 3); |
|
| 63 |
+ auto bufLong = reinterpret_cast<std::int32_t *>(&longBuffer[0]); |
|
| 61 | 64 |
while (pos < bufsize) |
| 62 | 65 |
{
|
| 63 | 66 |
unsigned remain = bufsize - pos, offset = pos; |
| 64 | 67 |
this->GenerateSamples(trueBuffer, pos << (this->uses32BitSamplesClampedTo16Bit ? 2 : 1), remain); |
| 65 | 68 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 66 | 69 |
{
|
| 67 |
- auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 70 |
+ auto trueBufLong = reinterpret_cast<std::int32_t *>(&trueBuffer[0]); |
|
| 68 | 71 |
std::copy_n(&trueBufLong[0], bufsize << 1, &bufLong[0]); |
| 69 | 72 |
} |
| 70 | 73 |
else |
| 71 | 74 |
{
|
| 72 |
- auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 75 |
+ auto trueBufShort = reinterpret_cast<std::int16_t *>(&trueBuffer[0]); |
|
| 73 | 76 |
std::copy_n(&trueBufShort[0], bufsize << 1, &bufLong[0]); |
| 74 | 77 |
} |
| 75 | 78 |
if (detectSilence || skipSilenceOnStartSec) |
| ... | ... |
@@ -77,7 +80,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 77 | 80 |
unsigned skipOffset = 0; |
| 78 | 81 |
for (unsigned ofs = 0; ofs < remain; ++ofs) |
| 79 | 82 |
{
|
| 80 |
- uint32_t sampleL = bufLong[2 * (offset + ofs)], sampleR = bufLong[2 * (offset + ofs) + 1]; |
|
| 83 |
+ std::uint32_t sampleL = bufLong[2 * (offset + ofs)], sampleR = bufLong[2 * (offset + ofs) + 1]; |
|
| 81 | 84 |
bool silence = (sampleL + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleL <= CHECK_SILENCE_LEVEL * 2 && |
| 82 | 85 |
(sampleR + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleR <= CHECK_SILENCE_LEVEL * 2; |
| 83 | 86 |
|
| ... | ... |
@@ -114,7 +117,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 114 | 117 |
{
|
| 115 | 118 |
if (skipOffset) |
| 116 | 119 |
{
|
| 117 |
- auto tmpBuf = std::vector<int32_t>((bufsize - skipOffset) << 1); |
|
| 120 |
+ auto tmpBuf = std::vector<std::int32_t>((bufsize - skipOffset) << 1); |
|
| 118 | 121 |
std::copy(&bufLong[(offset + skipOffset) << 1], &bufLong[bufsize << 1], &tmpBuf[0]); |
| 119 | 122 |
std::copy_n(&tmpBuf[0], (bufsize - skipOffset) << 1, &bufLong[offset << 1]); |
| 120 | 123 |
pos += skipOffset; |
| ... | ... |
@@ -129,12 +132,12 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 129 | 132 |
{
|
| 130 | 133 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 131 | 134 |
{
|
| 132 |
- auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 135 |
+ auto trueBufLong = reinterpret_cast<std::int32_t *>(&trueBuffer[0]); |
|
| 133 | 136 |
std::copy_n(&bufLong[0], bufsize << 1, &trueBufLong[0]); |
| 134 | 137 |
} |
| 135 | 138 |
else |
| 136 | 139 |
{
|
| 137 |
- auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 140 |
+ auto trueBufShort = reinterpret_cast<std::int16_t *>(&trueBuffer[0]); |
|
| 138 | 141 |
std::copy_n(&bufLong[0], bufsize << 1, &trueBufShort[0]); |
| 139 | 142 |
} |
| 140 | 143 |
} |
| ... | ... |
@@ -164,29 +167,29 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 164 | 167 |
double s1 = bufLong[2 * ofs] * scale, s2 = bufLong[2 * ofs + 1] * scale; |
| 165 | 168 |
if (!this->uses32BitSamplesClampedTo16Bit) |
| 166 | 169 |
{
|
| 167 |
- clamp(s1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 168 |
- clamp(s2, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 170 |
+ clamp(s1, std::numeric_limits<std::int16_t>::min(), std::numeric_limits<std::int16_t>::max()); |
|
| 171 |
+ clamp(s2, std::numeric_limits<std::int16_t>::min(), std::numeric_limits<std::int16_t>::max()); |
|
| 169 | 172 |
} |
| 170 |
- bufLong[2 * ofs] = static_cast<int32_t>(s1); |
|
| 171 |
- bufLong[2 * ofs + 1] = static_cast<int32_t>(s2); |
|
| 173 |
+ bufLong[2 * ofs] = static_cast<std::int32_t>(s1); |
|
| 174 |
+ bufLong[2 * ofs + 1] = static_cast<std::int32_t>(s2); |
|
| 172 | 175 |
} |
| 173 | 176 |
} |
| 174 | 177 |
|
| 175 | 178 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 176 | 179 |
{
|
| 177 |
- auto bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 180 |
+ auto bufShort = reinterpret_cast<std::int16_t *>(&buf[0]); |
|
| 178 | 181 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 179 | 182 |
{
|
| 180 |
- int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1]; |
|
| 181 |
- clamp(s1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 182 |
- clamp(s2, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 183 |
- bufShort[2 * ofs] = static_cast<int16_t>(s1); |
|
| 184 |
- bufShort[2 * ofs + 1] = static_cast<int16_t>(s2); |
|
| 183 |
+ std::int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1]; |
|
| 184 |
+ clamp(s1, std::numeric_limits<std::int16_t>::min(), std::numeric_limits<std::int16_t>::max()); |
|
| 185 |
+ clamp(s2, std::numeric_limits<std::int16_t>::min(), std::numeric_limits<std::int16_t>::max()); |
|
| 186 |
+ bufShort[2 * ofs] = static_cast<std::int16_t>(s1); |
|
| 187 |
+ bufShort[2 * ofs + 1] = static_cast<std::int16_t>(s2); |
|
| 185 | 188 |
} |
| 186 | 189 |
} |
| 187 | 190 |
else |
| 188 | 191 |
{
|
| 189 |
- auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 192 |
+ auto trueBufShort = reinterpret_cast<std::int16_t *>(&trueBuffer[0]); |
|
| 190 | 193 |
std::copy_n(&bufLong[0], bufsize << 1, &trueBufShort[0]); |
| 191 | 194 |
std::copy(&trueBuffer[0], &trueBuffer[bufsize << 2], &buf[0]); |
| 192 | 195 |
} |
| ... | ... |
@@ -194,12 +197,12 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 194 | 197 |
/* Fading */ |
| 195 | 198 |
if (!xSFConfig->GetPlayInfinitely() && this->fadeSample && this->currentSample + bufsize >= this->lengthSample) |
| 196 | 199 |
{
|
| 197 |
- auto bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 200 |
+ auto bufShort = reinterpret_cast<std::int16_t *>(&buf[0]); |
|
| 198 | 201 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 199 | 202 |
{
|
| 200 | 203 |
if (this->currentSample + ofs >= this->lengthSample && this->currentSample + ofs < this->lengthSample + this->fadeSample) |
| 201 | 204 |
{
|
| 202 |
- int scale = static_cast<uint64_t>(this->lengthSample + this->fadeSample - (this->currentSample + ofs)) * 0x10000 / this->fadeSample; |
|
| 205 |
+ int scale = static_cast<std::uint64_t>(this->lengthSample + this->fadeSample - (this->currentSample + ofs)) * 0x10000 / this->fadeSample; |
|
| 203 | 206 |
bufShort[2 * ofs] = (bufShort[2 * ofs] * scale) >> 16; |
| 204 | 207 |
bufShort[2 * ofs + 1] = (bufShort[2 * ofs + 1] * scale) >> 16; |
| 205 | 208 |
} |
| ... | ... |
@@ -217,8 +220,8 @@ bool XSFPlayer::Load() |
| 217 | 220 |
{
|
| 218 | 221 |
this->lengthInMS = this->xSF->GetLengthMS(xSFConfig->GetDefaultLength()); |
| 219 | 222 |
this->fadeInMS = this->xSF->GetFadeMS(xSFConfig->GetDefaultFade()); |
| 220 |
- this->lengthSample = static_cast<uint64_t>(this->lengthInMS) * this->sampleRate / 1000; |
|
| 221 |
- this->fadeSample = static_cast<uint64_t>(this->fadeInMS) * this->sampleRate / 1000; |
|
| 223 |
+ this->lengthSample = static_cast<std::uint64_t>(this->lengthInMS) * this->sampleRate / 1000; |
|
| 224 |
+ this->fadeSample = static_cast<std::uint64_t>(this->fadeInMS) * this->sampleRate / 1000; |
|
| 222 | 225 |
this->volume = this->xSF->GetVolume(xSFConfig->GetVolumeType(), xSFConfig->GetPeakType()); |
| 223 | 226 |
return true; |
| 224 | 227 |
} |
| ... | ... |
@@ -233,9 +236,9 @@ void XSFPlayer::SeekTop() |
| 233 | 236 |
#ifdef WINAMP_PLUGIN |
| 234 | 237 |
static inline DWORD TicksDiff(DWORD prev, DWORD cur) { return cur >= prev ? cur - prev : 0xFFFFFFFF - prev + cur; }
|
| 235 | 238 |
|
| 236 |
-int XSFPlayer::Seek(unsigned seekPosition, volatile int *killswitch, std::vector<uint8_t> &buf, Out_Module *outMod) |
|
| 239 |
+int XSFPlayer::Seek(unsigned seekPosition, volatile int *killswitch, std::vector<std::uint8_t> &buf, Out_Module *outMod) |
|
| 237 | 240 |
{
|
| 238 |
- unsigned bufsize = buf.size() >> 2, seekSample = static_cast<uint64_t>(seekPosition) * this->sampleRate / 1000; |
|
| 241 |
+ unsigned bufsize = buf.size() >> 2, seekSample = static_cast<std::uint64_t>(seekPosition) * this->sampleRate / 1000; |
|
| 239 | 242 |
DWORD prevTick = outMod ? GetTickCount() : 0; |
| 240 | 243 |
if (seekSample < this->currentSample) |
| 241 | 244 |
{
|
| ... | ... |
@@ -253,7 +256,7 @@ int XSFPlayer::Seek(unsigned seekPosition, volatile int *killswitch, std::vector |
| 253 | 256 |
if (TicksDiff(prevTick, curTick) >= 500) |
| 254 | 257 |
{
|
| 255 | 258 |
prevTick = curTick; |
| 256 |
- unsigned cur = static_cast<uint64_t>(this->currentSample) * 1000 / this->sampleRate; |
|
| 259 |
+ unsigned cur = static_cast<std::uint64_t>(this->currentSample) * 1000 / this->sampleRate; |
|
| 257 | 260 |
outMod->Flush(cur); |
| 258 | 261 |
} |
| 259 | 262 |
} |
(I never remember to update these and besides, GitHub history can show when they were last modified.)
* Removed my custom String class, as well as removed the really old
Unicode ConvertUTF, the UTF Converter, and the UTF Encode/Decode
functions.
* Replaced the above with using standard C++ std::wstring_convert and
std::codecvt_utf8.
* Added headers adapted from llvm's libc++ project for allowing the
above C++ classes to exist with GCC and Clang when libc++ isn't being
used.
* Used std::string over std::wstring whenever possible.
* Added header adapted from llvm's libc++ project to create special
versions of the ifstream and ofstream classes that would utilize _wfopen
on non-MSVC Windows compilers, so those compilers could access files on
Windows that use characters outside the current codepage.
* Removed the -static-libgcc and -static-libstdc++ flags from the
Makefile for non-MSVC builds. The generated DLLs will require extra DLLs
from either Cygwin or MinGW (whichever is used to compile), I've only
tested with MinGW and for some reason they crash Winamp on exit, I have
no idea why.
| ... | ... |
@@ -66,12 +66,12 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 66 | 66 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 67 | 67 |
{
|
| 68 | 68 |
auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
| 69 |
- std::copy(&trueBufLong[0], &trueBufLong[bufsize << 1], &bufLong[0]); |
|
| 69 |
+ std::copy_n(&trueBufLong[0], bufsize << 1, &bufLong[0]); |
|
| 70 | 70 |
} |
| 71 | 71 |
else |
| 72 | 72 |
{
|
| 73 | 73 |
auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
| 74 |
- std::copy(&trueBufShort[0], &trueBufShort[bufsize << 1], &bufLong[0]); |
|
| 74 |
+ std::copy_n(&trueBufShort[0], bufsize << 1, &bufLong[0]); |
|
| 75 | 75 |
} |
| 76 | 76 |
if (detectSilence || skipSilenceOnStartSec) |
| 77 | 77 |
{
|
| ... | ... |
@@ -117,7 +117,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 117 | 117 |
{
|
| 118 | 118 |
auto tmpBuf = std::vector<int32_t>((bufsize - skipOffset) << 1); |
| 119 | 119 |
std::copy(&bufLong[(offset + skipOffset) << 1], &bufLong[bufsize << 1], &tmpBuf[0]); |
| 120 |
- std::copy(&tmpBuf[0], &tmpBuf[(bufsize - skipOffset) << 1], &bufLong[offset << 1]); |
|
| 120 |
+ std::copy_n(&tmpBuf[0], (bufsize - skipOffset) << 1, &bufLong[offset << 1]); |
|
| 121 | 121 |
pos += skipOffset; |
| 122 | 122 |
} |
| 123 | 123 |
else |
| ... | ... |
@@ -131,12 +131,12 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 131 | 131 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 132 | 132 |
{
|
| 133 | 133 |
auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
| 134 |
- std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufLong[0]); |
|
| 134 |
+ std::copy_n(&bufLong[0], bufsize << 1, &trueBufLong[0]); |
|
| 135 | 135 |
} |
| 136 | 136 |
else |
| 137 | 137 |
{
|
| 138 | 138 |
auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
| 139 |
- std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]); |
|
| 139 |
+ std::copy_n(&bufLong[0], bufsize << 1, &trueBufShort[0]); |
|
| 140 | 140 |
} |
| 141 | 141 |
} |
| 142 | 142 |
} |
| ... | ... |
@@ -188,7 +188,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 188 | 188 |
else |
| 189 | 189 |
{
|
| 190 | 190 |
auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
| 191 |
- std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]); |
|
| 191 |
+ std::copy_n(&bufLong[0], bufsize << 1, &trueBufShort[0]); |
|
| 192 | 192 |
std::copy(&trueBuffer[0], &trueBuffer[bufsize << 2], &buf[0]); |
| 193 | 193 |
} |
| 194 | 194 |
|
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - Core Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-05-07 |
|
| 4 |
+ * Last modification on 2014-09-08 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
*/ |
| ... | ... |
@@ -56,25 +56,21 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 56 | 56 |
bool endFlag = false; |
| 57 | 57 |
unsigned detectSilence = xSFConfig->GetDetectSilenceSec(); |
| 58 | 58 |
unsigned pos = 0, bufsize = buf.size() >> 2; |
| 59 |
- std::vector<uint8_t> trueBuffer; |
|
| 60 |
- if (this->uses32BitSamplesClampedTo16Bit) |
|
| 61 |
- trueBuffer.resize(bufsize << 3); |
|
| 62 |
- else |
|
| 63 |
- trueBuffer.resize(bufsize << 2); |
|
| 59 |
+ auto trueBuffer = std::vector<uint8_t>(bufsize << (this->uses32BitSamplesClampedTo16Bit ? 3 : 2)); |
|
| 64 | 60 |
auto longBuffer = std::vector<uint8_t>(bufsize << 3); |
| 65 |
- int32_t *bufLong = reinterpret_cast<int32_t *>(&longBuffer[0]); |
|
| 61 |
+ auto bufLong = reinterpret_cast<int32_t *>(&longBuffer[0]); |
|
| 66 | 62 |
while (pos < bufsize) |
| 67 | 63 |
{
|
| 68 | 64 |
unsigned remain = bufsize - pos, offset = pos; |
| 69 | 65 |
this->GenerateSamples(trueBuffer, pos << (this->uses32BitSamplesClampedTo16Bit ? 2 : 1), remain); |
| 70 | 66 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 71 | 67 |
{
|
| 72 |
- int32_t *trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 68 |
+ auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 73 | 69 |
std::copy(&trueBufLong[0], &trueBufLong[bufsize << 1], &bufLong[0]); |
| 74 | 70 |
} |
| 75 | 71 |
else |
| 76 | 72 |
{
|
| 77 |
- int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 73 |
+ auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 78 | 74 |
std::copy(&trueBufShort[0], &trueBufShort[bufsize << 1], &bufLong[0]); |
| 79 | 75 |
} |
| 80 | 76 |
if (detectSilence || skipSilenceOnStartSec) |
| ... | ... |
@@ -134,12 +130,12 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 134 | 130 |
{
|
| 135 | 131 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 136 | 132 |
{
|
| 137 |
- int32_t *trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 133 |
+ auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 138 | 134 |
std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufLong[0]); |
| 139 | 135 |
} |
| 140 | 136 |
else |
| 141 | 137 |
{
|
| 142 |
- int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 138 |
+ auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 143 | 139 |
std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]); |
| 144 | 140 |
} |
| 145 | 141 |
} |
| ... | ... |
@@ -179,7 +175,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 179 | 175 |
|
| 180 | 176 |
if (this->uses32BitSamplesClampedTo16Bit) |
| 181 | 177 |
{
|
| 182 |
- int16_t *bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 178 |
+ auto bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 183 | 179 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 184 | 180 |
{
|
| 185 | 181 |
int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1]; |
| ... | ... |
@@ -191,7 +187,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 191 | 187 |
} |
| 192 | 188 |
else |
| 193 | 189 |
{
|
| 194 |
- int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 190 |
+ auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 195 | 191 |
std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]); |
| 196 | 192 |
std::copy(&trueBuffer[0], &trueBuffer[bufsize << 2], &buf[0]); |
| 197 | 193 |
} |
| ... | ... |
@@ -199,7 +195,7 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 199 | 195 |
/* Fading */ |
| 200 | 196 |
if (!xSFConfig->GetPlayInfinitely() && this->fadeSample && this->currentSample + bufsize >= this->lengthSample) |
| 201 | 197 |
{
|
| 202 |
- int16_t *bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 198 |
+ auto bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 203 | 199 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 204 | 200 |
{
|
| 205 | 201 |
if (this->currentSample + ofs >= this->lengthSample && this->currentSample + ofs < this->lengthSample + this->fadeSample) |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - Core Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-26 |
|
| 4 |
+ * Last modification on 2013-05-07 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
*/ |
| ... | ... |
@@ -169,8 +169,8 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 169 | 169 |
double s1 = bufLong[2 * ofs] * scale, s2 = bufLong[2 * ofs + 1] * scale; |
| 170 | 170 |
if (!this->uses32BitSamplesClampedTo16Bit) |
| 171 | 171 |
{
|
| 172 |
- clamp(s1, -0x7FFF, 0x8000); |
|
| 173 |
- clamp(s2, -0x7FFF, 0x8000); |
|
| 172 |
+ clamp(s1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 173 |
+ clamp(s2, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 174 | 174 |
} |
| 175 | 175 |
bufLong[2 * ofs] = static_cast<int32_t>(s1); |
| 176 | 176 |
bufLong[2 * ofs + 1] = static_cast<int32_t>(s2); |
| ... | ... |
@@ -183,8 +183,8 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 183 | 183 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 184 | 184 |
{
|
| 185 | 185 |
int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1]; |
| 186 |
- clamp(s1, -0x7FFF, 0x8000); |
|
| 187 |
- clamp(s2, -0x7FFF, 0x8000); |
|
| 186 |
+ clamp(s1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 187 |
+ clamp(s2, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); |
|
| 188 | 188 |
bufShort[2 * ofs] = static_cast<int16_t>(s1); |
| 189 | 189 |
bufShort[2 * ofs + 1] = static_cast<int16_t>(s2); |
| 190 | 190 |
} |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - Core Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-23 |
|
| 4 |
+ * Last modification on 2013-04-26 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
*/ |
| ... | ... |
@@ -14,13 +14,14 @@ |
| 14 | 14 |
extern XSFConfig *xSFConfig; |
| 15 | 15 |
|
| 16 | 16 |
XSFPlayer::XSFPlayer() : xSF(), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0), |
| 17 |
- prevSampleL(CHECK_SILENCE_BIAS), prevSampleR(CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false) |
|
| 17 |
+ prevSampleL(CHECK_SILENCE_BIAS), prevSampleR(CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false), uses32BitSamplesClampedTo16Bit(false) |
|
| 18 | 18 |
{
|
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 | 21 |
XSFPlayer::XSFPlayer(const XSFPlayer &xSFPlayer) : xSF(new XSFFile()), sampleRate(xSFPlayer.sampleRate), detectedSilenceSample(xSFPlayer.detectedSilenceSample), detectedSilenceSec(xSFPlayer.detectedSilenceSec), |
| 22 | 22 |
skipSilenceOnStartSec(xSFPlayer.skipSilenceOnStartSec), lengthSample(xSFPlayer.lengthSample), fadeSample(xSFPlayer.fadeSample), currentSample(xSFPlayer.currentSample), prevSampleL(xSFPlayer.prevSampleL), |
| 23 |
- prevSampleR(xSFPlayer.prevSampleR), lengthInMS(xSFPlayer.lengthInMS), fadeInMS(xSFPlayer.fadeInMS), volume(xSFPlayer.volume), ignoreVolume(xSFPlayer.ignoreVolume) |
|
| 23 |
+ prevSampleR(xSFPlayer.prevSampleR), lengthInMS(xSFPlayer.lengthInMS), fadeInMS(xSFPlayer.fadeInMS), volume(xSFPlayer.volume), ignoreVolume(xSFPlayer.ignoreVolume), |
|
| 24 |
+ uses32BitSamplesClampedTo16Bit(xSFPlayer.uses32BitSamplesClampedTo16Bit) |
|
| 24 | 25 |
{
|
| 25 | 26 |
*this->xSF = *xSFPlayer.xSF; |
| 26 | 27 |
} |
| ... | ... |
@@ -45,6 +46,7 @@ XSFPlayer &XSFPlayer::operator=(const XSFPlayer &xSFPlayer) |
| 45 | 46 |
this->fadeInMS = xSFPlayer.fadeInMS; |
| 46 | 47 |
this->volume = xSFPlayer.volume; |
| 47 | 48 |
this->ignoreVolume = xSFPlayer.ignoreVolume; |
| 49 |
+ this->uses32BitSamplesClampedTo16Bit = xSFPlayer.uses32BitSamplesClampedTo16Bit; |
|
| 48 | 50 |
} |
| 49 | 51 |
return *this; |
| 50 | 52 |
} |
| ... | ... |
@@ -54,17 +56,33 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 54 | 56 |
bool endFlag = false; |
| 55 | 57 |
unsigned detectSilence = xSFConfig->GetDetectSilenceSec(); |
| 56 | 58 |
unsigned pos = 0, bufsize = buf.size() >> 2; |
| 59 |
+ std::vector<uint8_t> trueBuffer; |
|
| 60 |
+ if (this->uses32BitSamplesClampedTo16Bit) |
|
| 61 |
+ trueBuffer.resize(bufsize << 3); |
|
| 62 |
+ else |
|
| 63 |
+ trueBuffer.resize(bufsize << 2); |
|
| 64 |
+ auto longBuffer = std::vector<uint8_t>(bufsize << 3); |
|
| 65 |
+ int32_t *bufLong = reinterpret_cast<int32_t *>(&longBuffer[0]); |
|
| 57 | 66 |
while (pos < bufsize) |
| 58 | 67 |
{
|
| 59 | 68 |
unsigned remain = bufsize - pos, offset = pos; |
| 60 |
- this->GenerateSamples(buf, pos << 1, remain); |
|
| 69 |
+ this->GenerateSamples(trueBuffer, pos << (this->uses32BitSamplesClampedTo16Bit ? 2 : 1), remain); |
|
| 70 |
+ if (this->uses32BitSamplesClampedTo16Bit) |
|
| 71 |
+ {
|
|
| 72 |
+ int32_t *trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 73 |
+ std::copy(&trueBufLong[0], &trueBufLong[bufsize << 1], &bufLong[0]); |
|
| 74 |
+ } |
|
| 75 |
+ else |
|
| 76 |
+ {
|
|
| 77 |
+ int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 78 |
+ std::copy(&trueBufShort[0], &trueBufShort[bufsize << 1], &bufLong[0]); |
|
| 79 |
+ } |
|
| 61 | 80 |
if (detectSilence || skipSilenceOnStartSec) |
| 62 | 81 |
{
|
| 63 | 82 |
unsigned skipOffset = 0; |
| 64 | 83 |
for (unsigned ofs = 0; ofs < remain; ++ofs) |
| 65 | 84 |
{
|
| 66 |
- short *bufShort = reinterpret_cast<short *>(&buf[0]); |
|
| 67 |
- unsigned long sampleL = bufShort[2 * (offset + ofs)], sampleR = bufShort[2 * (offset + ofs) + 1]; |
|
| 85 |
+ uint32_t sampleL = bufLong[2 * (offset + ofs)], sampleR = bufLong[2 * (offset + ofs) + 1]; |
|
| 68 | 86 |
bool silence = (sampleL + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleL <= CHECK_SILENCE_LEVEL * 2 && |
| 69 | 87 |
(sampleR + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleR <= CHECK_SILENCE_LEVEL * 2; |
| 70 | 88 |
|
| ... | ... |
@@ -101,9 +119,9 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 101 | 119 |
{
|
| 102 | 120 |
if (skipOffset) |
| 103 | 121 |
{
|
| 104 |
- auto tmpBuf = std::vector<uint8_t>(2 * skipOffset); |
|
| 105 |
- memcpy(&tmpBuf[0], &buf[offset + 2 * skipOffset], 2 * skipOffset); |
|
| 106 |
- memcpy(&buf[offset], &tmpBuf[0], 2 * skipOffset); |
|
| 122 |
+ auto tmpBuf = std::vector<int32_t>((bufsize - skipOffset) << 1); |
|
| 123 |
+ std::copy(&bufLong[(offset + skipOffset) << 1], &bufLong[bufsize << 1], &tmpBuf[0]); |
|
| 124 |
+ std::copy(&tmpBuf[0], &tmpBuf[(bufsize - skipOffset) << 1], &bufLong[offset << 1]); |
|
| 107 | 125 |
pos += skipOffset; |
| 108 | 126 |
} |
| 109 | 127 |
else |
| ... | ... |
@@ -112,6 +130,19 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 112 | 130 |
} |
| 113 | 131 |
else |
| 114 | 132 |
pos += remain; |
| 133 |
+ if (pos < bufsize) |
|
| 134 |
+ {
|
|
| 135 |
+ if (this->uses32BitSamplesClampedTo16Bit) |
|
| 136 |
+ {
|
|
| 137 |
+ int32_t *trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); |
|
| 138 |
+ std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufLong[0]); |
|
| 139 |
+ } |
|
| 140 |
+ else |
|
| 141 |
+ {
|
|
| 142 |
+ int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 143 |
+ std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]); |
|
| 144 |
+ } |
|
| 145 |
+ } |
|
| 115 | 146 |
} |
| 116 | 147 |
|
| 117 | 148 |
/* Detect end of song */ |
| ... | ... |
@@ -133,27 +164,42 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 133 | 164 |
if (!this->ignoreVolume && (!fEqual(this->volume, 1.0) || !fEqual(xSFConfig->GetVolume(), 1.0))) |
| 134 | 165 |
{
|
| 135 | 166 |
double scale = this->volume * xSFConfig->GetVolume(); |
| 136 |
- short *bufShort = reinterpret_cast<short *>(&buf[0]); |
|
| 137 | 167 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 138 | 168 |
{
|
| 139 |
- double s1 = bufShort[2 * ofs] * scale, s2 = bufShort[2 * ofs + 1] * scale; |
|
| 140 |
- if (s1 > 0x7FFF) |
|
| 141 |
- s1 = 0x7FFF; |
|
| 142 |
- else if (s1 < -0x8000) |
|
| 143 |
- s1 = -0x8000; |
|
| 144 |
- if (s2 > 0x7FFF) |
|
| 145 |
- s2 = 0x7FFF; |
|
| 146 |
- else if (s2 < -0x8000) |
|
| 147 |
- s2 = -0x8000; |
|
| 148 |
- bufShort[2 * ofs] = static_cast<short>(s1); |
|
| 149 |
- bufShort[2 * ofs + 1] = static_cast<short>(s2); |
|
| 169 |
+ double s1 = bufLong[2 * ofs] * scale, s2 = bufLong[2 * ofs + 1] * scale; |
|
| 170 |
+ if (!this->uses32BitSamplesClampedTo16Bit) |
|
| 171 |
+ {
|
|
| 172 |
+ clamp(s1, -0x7FFF, 0x8000); |
|
| 173 |
+ clamp(s2, -0x7FFF, 0x8000); |
|
| 174 |
+ } |
|
| 175 |
+ bufLong[2 * ofs] = static_cast<int32_t>(s1); |
|
| 176 |
+ bufLong[2 * ofs + 1] = static_cast<int32_t>(s2); |
|
| 177 |
+ } |
|
| 178 |
+ } |
|
| 179 |
+ |
|
| 180 |
+ if (this->uses32BitSamplesClampedTo16Bit) |
|
| 181 |
+ {
|
|
| 182 |
+ int16_t *bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 183 |
+ for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
|
| 184 |
+ {
|
|
| 185 |
+ int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1]; |
|
| 186 |
+ clamp(s1, -0x7FFF, 0x8000); |
|
| 187 |
+ clamp(s2, -0x7FFF, 0x8000); |
|
| 188 |
+ bufShort[2 * ofs] = static_cast<int16_t>(s1); |
|
| 189 |
+ bufShort[2 * ofs + 1] = static_cast<int16_t>(s2); |
|
| 150 | 190 |
} |
| 151 | 191 |
} |
| 192 |
+ else |
|
| 193 |
+ {
|
|
| 194 |
+ int16_t *trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); |
|
| 195 |
+ std::copy(&bufLong[0], &bufLong[bufsize << 1], &trueBufShort[0]); |
|
| 196 |
+ std::copy(&trueBuffer[0], &trueBuffer[bufsize << 2], &buf[0]); |
|
| 197 |
+ } |
|
| 152 | 198 |
|
| 153 | 199 |
/* Fading */ |
| 154 | 200 |
if (!xSFConfig->GetPlayInfinitely() && this->fadeSample && this->currentSample + bufsize >= this->lengthSample) |
| 155 | 201 |
{
|
| 156 |
- short *bufShort = reinterpret_cast<short *>(&buf[0]); |
|
| 202 |
+ int16_t *bufShort = reinterpret_cast<int16_t *>(&buf[0]); |
|
| 157 | 203 |
for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
| 158 | 204 |
{
|
| 159 | 205 |
if (this->currentSample + ofs >= this->lengthSample && this->currentSample + ofs < this->lengthSample + this->fadeSample) |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - Core Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-03-30 |
|
| 4 |
+ * Last modification on 2013-04-23 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
*/ |
| ... | ... |
@@ -13,8 +13,8 @@ |
| 13 | 13 |
|
| 14 | 14 |
extern XSFConfig *xSFConfig; |
| 15 | 15 |
|
| 16 |
-XSFPlayer::XSFPlayer() : xSF(nullptr), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0), |
|
| 17 |
- prevSampleL(XSFPlayer::CHECK_SILENCE_BIAS), prevSampleR(XSFPlayer::CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false) |
|
| 16 |
+XSFPlayer::XSFPlayer() : xSF(), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0), |
|
| 17 |
+ prevSampleL(CHECK_SILENCE_BIAS), prevSampleR(CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false) |
|
| 18 | 18 |
{
|
| 19 | 19 |
} |
| 20 | 20 |
|
| ... | ... |
@@ -30,7 +30,7 @@ XSFPlayer &XSFPlayer::operator=(const XSFPlayer &xSFPlayer) |
| 30 | 30 |
if (this != &xSFPlayer) |
| 31 | 31 |
{
|
| 32 | 32 |
if (!this->xSF) |
| 33 |
- this->xSF = new XSFFile(); |
|
| 33 |
+ this->xSF.reset(new XSFFile()); |
|
| 34 | 34 |
*this->xSF = *xSFPlayer.xSF; |
| 35 | 35 |
this->sampleRate = xSFPlayer.sampleRate; |
| 36 | 36 |
this->detectedSilenceSample = xSFPlayer.detectedSilenceSample; |
| ... | ... |
@@ -65,8 +65,8 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 65 | 65 |
{
|
| 66 | 66 |
short *bufShort = reinterpret_cast<short *>(&buf[0]); |
| 67 | 67 |
unsigned long sampleL = bufShort[2 * (offset + ofs)], sampleR = bufShort[2 * (offset + ofs) + 1]; |
| 68 |
- bool silence = (sampleL + XSFPlayer::CHECK_SILENCE_BIAS + XSFPlayer::CHECK_SILENCE_LEVEL) - this->prevSampleL <= XSFPlayer::CHECK_SILENCE_LEVEL * 2 && |
|
| 69 |
- (sampleR + XSFPlayer::CHECK_SILENCE_BIAS + XSFPlayer::CHECK_SILENCE_LEVEL) - this->prevSampleR <= XSFPlayer::CHECK_SILENCE_LEVEL * 2; |
|
| 68 |
+ bool silence = (sampleL + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleL <= CHECK_SILENCE_LEVEL * 2 && |
|
| 69 |
+ (sampleR + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleR <= CHECK_SILENCE_LEVEL * 2; |
|
| 70 | 70 |
|
| 71 | 71 |
if (silence) |
| 72 | 72 |
{
|
| ... | ... |
@@ -93,15 +93,15 @@ bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
| 93 | 93 |
} |
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 |
- prevSampleL = sampleL + XSFPlayer::CHECK_SILENCE_BIAS; |
|
| 97 |
- prevSampleR = sampleR + XSFPlayer::CHECK_SILENCE_BIAS; |
|
| 96 |
+ prevSampleL = sampleL + CHECK_SILENCE_BIAS; |
|
| 97 |
+ prevSampleR = sampleR + CHECK_SILENCE_BIAS; |
|
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 | 100 |
if (!this->skipSilenceOnStartSec) |
| 101 | 101 |
{
|
| 102 | 102 |
if (skipOffset) |
| 103 | 103 |
{
|
| 104 |
- std::vector<uint8_t> tmpBuf = std::vector<uint8_t>(2 * skipOffset); |
|
| 104 |
+ auto tmpBuf = std::vector<uint8_t>(2 * skipOffset); |
|
| 105 | 105 |
memcpy(&tmpBuf[0], &buf[offset + 2 * skipOffset], 2 * skipOffset); |
| 106 | 106 |
memcpy(&buf[offset], &tmpBuf[0], 2 * skipOffset); |
| 107 | 107 |
pos += skipOffset; |
| ... | ... |
@@ -186,11 +186,10 @@ void XSFPlayer::SeekTop() |
| 186 | 186 |
{
|
| 187 | 187 |
this->skipSilenceOnStartSec = xSFConfig->GetSkipSilenceOnStartSec(); |
| 188 | 188 |
this->currentSample = this->detectedSilenceSec = this->detectedSilenceSample = 0; |
| 189 |
- this->prevSampleL = this->prevSampleR = XSFPlayer::CHECK_SILENCE_BIAS; |
|
| 189 |
+ this->prevSampleL = this->prevSampleR = CHECK_SILENCE_BIAS; |
|
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 | 192 |
#ifdef WINAMP_PLUGIN |
| 193 |
- |
|
| 194 | 193 |
static inline DWORD TicksDiff(DWORD prev, DWORD cur) { return cur >= prev ? cur - prev : 0xFFFFFFFF - prev + cur; }
|
| 195 | 194 |
|
| 196 | 195 |
int XSFPlayer::Seek(unsigned seekPosition, volatile int *killswitch, std::vector<uint8_t> &buf, Out_Module *outMod) |
| ... | ... |
@@ -229,5 +228,4 @@ int XSFPlayer::Seek(unsigned seekPosition, volatile int *killswitch, std::vector |
| 229 | 228 |
outMod->Flush(seekPosition); |
| 230 | 229 |
return 0; |
| 231 | 230 |
} |
| 232 |
- |
|
| 233 | 231 |
#endif |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - Core Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-03-21 |
|
| 4 |
+ * Last modification on 2013-03-30 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
*/ |
| ... | ... |
@@ -13,7 +13,7 @@ |
| 13 | 13 |
|
| 14 | 14 |
extern XSFConfig *xSFConfig; |
| 15 | 15 |
|
| 16 |
-XSFPlayer::XSFPlayer() : xSF(NULL), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0), |
|
| 16 |
+XSFPlayer::XSFPlayer() : xSF(nullptr), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0), |
|
| 17 | 17 |
prevSampleL(XSFPlayer::CHECK_SILENCE_BIAS), prevSampleR(XSFPlayer::CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false) |
| 18 | 18 |
{
|
| 19 | 19 |
} |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,233 @@ |
| 1 |
+/* |
|
| 2 |
+ * xSF - Core Player |
|
| 3 |
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
|
| 4 |
+ * Last modification on 2013-03-21 |
|
| 5 |
+ * |
|
| 6 |
+ * Partially based on the vio*sf framework |
|
| 7 |
+ */ |
|
| 8 |
+ |
|
| 9 |
+#include <cstring> |
|
| 10 |
+#include "XSFPlayer.h" |
|
| 11 |
+#include "XSFConfig.h" |
|
| 12 |
+#include "XSFCommon.h" |
|
| 13 |
+ |
|
| 14 |
+extern XSFConfig *xSFConfig; |
|
| 15 |
+ |
|
| 16 |
+XSFPlayer::XSFPlayer() : xSF(NULL), sampleRate(0), detectedSilenceSample(0), detectedSilenceSec(0), skipSilenceOnStartSec(5), lengthSample(0), fadeSample(0), currentSample(0), |
|
| 17 |
+ prevSampleL(XSFPlayer::CHECK_SILENCE_BIAS), prevSampleR(XSFPlayer::CHECK_SILENCE_BIAS), lengthInMS(-1), fadeInMS(-1), volume(1.0), ignoreVolume(false) |
|
| 18 |
+{
|
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+XSFPlayer::XSFPlayer(const XSFPlayer &xSFPlayer) : xSF(new XSFFile()), sampleRate(xSFPlayer.sampleRate), detectedSilenceSample(xSFPlayer.detectedSilenceSample), detectedSilenceSec(xSFPlayer.detectedSilenceSec), |
|
| 22 |
+ skipSilenceOnStartSec(xSFPlayer.skipSilenceOnStartSec), lengthSample(xSFPlayer.lengthSample), fadeSample(xSFPlayer.fadeSample), currentSample(xSFPlayer.currentSample), prevSampleL(xSFPlayer.prevSampleL), |
|
| 23 |
+ prevSampleR(xSFPlayer.prevSampleR), lengthInMS(xSFPlayer.lengthInMS), fadeInMS(xSFPlayer.fadeInMS), volume(xSFPlayer.volume), ignoreVolume(xSFPlayer.ignoreVolume) |
|
| 24 |
+{
|
|
| 25 |
+ *this->xSF = *xSFPlayer.xSF; |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+XSFPlayer &XSFPlayer::operator=(const XSFPlayer &xSFPlayer) |
|
| 29 |
+{
|
|
| 30 |
+ if (this != &xSFPlayer) |
|
| 31 |
+ {
|
|
| 32 |
+ if (!this->xSF) |
|
| 33 |
+ this->xSF = new XSFFile(); |
|
| 34 |
+ *this->xSF = *xSFPlayer.xSF; |
|
| 35 |
+ this->sampleRate = xSFPlayer.sampleRate; |
|
| 36 |
+ this->detectedSilenceSample = xSFPlayer.detectedSilenceSample; |
|
| 37 |
+ this->detectedSilenceSec = xSFPlayer.detectedSilenceSec; |
|
| 38 |
+ this->skipSilenceOnStartSec = xSFPlayer.skipSilenceOnStartSec; |
|
| 39 |
+ this->lengthSample = xSFPlayer.lengthSample; |
|
| 40 |
+ this->fadeSample = xSFPlayer.fadeSample; |
|
| 41 |
+ this->currentSample = xSFPlayer.currentSample; |
|
| 42 |
+ this->prevSampleL = xSFPlayer.prevSampleL; |
|
| 43 |
+ this->prevSampleR = xSFPlayer.prevSampleR; |
|
| 44 |
+ this->lengthInMS = xSFPlayer.lengthInMS; |
|
| 45 |
+ this->fadeInMS = xSFPlayer.fadeInMS; |
|
| 46 |
+ this->volume = xSFPlayer.volume; |
|
| 47 |
+ this->ignoreVolume = xSFPlayer.ignoreVolume; |
|
| 48 |
+ } |
|
| 49 |
+ return *this; |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) |
|
| 53 |
+{
|
|
| 54 |
+ bool endFlag = false; |
|
| 55 |
+ unsigned detectSilence = xSFConfig->GetDetectSilenceSec(); |
|
| 56 |
+ unsigned pos = 0, bufsize = buf.size() >> 2; |
|
| 57 |
+ while (pos < bufsize) |
|
| 58 |
+ {
|
|
| 59 |
+ unsigned remain = bufsize - pos, offset = pos; |
|
| 60 |
+ this->GenerateSamples(buf, pos << 1, remain); |
|
| 61 |
+ if (detectSilence || skipSilenceOnStartSec) |
|
| 62 |
+ {
|
|
| 63 |
+ unsigned skipOffset = 0; |
|
| 64 |
+ for (unsigned ofs = 0; ofs < remain; ++ofs) |
|
| 65 |
+ {
|
|
| 66 |
+ short *bufShort = reinterpret_cast<short *>(&buf[0]); |
|
| 67 |
+ unsigned long sampleL = bufShort[2 * (offset + ofs)], sampleR = bufShort[2 * (offset + ofs) + 1]; |
|
| 68 |
+ bool silence = (sampleL + XSFPlayer::CHECK_SILENCE_BIAS + XSFPlayer::CHECK_SILENCE_LEVEL) - this->prevSampleL <= XSFPlayer::CHECK_SILENCE_LEVEL * 2 && |
|
| 69 |
+ (sampleR + XSFPlayer::CHECK_SILENCE_BIAS + XSFPlayer::CHECK_SILENCE_LEVEL) - this->prevSampleR <= XSFPlayer::CHECK_SILENCE_LEVEL * 2; |
|
| 70 |
+ |
|
| 71 |
+ if (silence) |
|
| 72 |
+ {
|
|
| 73 |
+ if (++this->detectedSilenceSample >= this->sampleRate) |
|
| 74 |
+ {
|
|
| 75 |
+ this->detectedSilenceSample -= this->sampleRate; |
|
| 76 |
+ ++this->detectedSilenceSec; |
|
| 77 |
+ if (this->skipSilenceOnStartSec && this->detectedSilenceSec >= this->skipSilenceOnStartSec) |
|
| 78 |
+ {
|
|
| 79 |
+ this->skipSilenceOnStartSec = this->detectedSilenceSec = 0; |
|
| 80 |
+ if (ofs) |
|
| 81 |
+ skipOffset = ofs; |
|
| 82 |
+ } |
|
| 83 |
+ } |
|
| 84 |
+ } |
|
| 85 |
+ else |
|
| 86 |
+ {
|
|
| 87 |
+ this->detectedSilenceSample = this->detectedSilenceSec = 0; |
|
| 88 |
+ if (this->skipSilenceOnStartSec) |
|
| 89 |
+ {
|
|
| 90 |
+ this->skipSilenceOnStartSec = 0; |
|
| 91 |
+ if (ofs) |
|
| 92 |
+ skipOffset = ofs; |
|
| 93 |
+ } |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ prevSampleL = sampleL + XSFPlayer::CHECK_SILENCE_BIAS; |
|
| 97 |
+ prevSampleR = sampleR + XSFPlayer::CHECK_SILENCE_BIAS; |
|
| 98 |
+ } |
|
| 99 |
+ |
|
| 100 |
+ if (!this->skipSilenceOnStartSec) |
|
| 101 |
+ {
|
|
| 102 |
+ if (skipOffset) |
|
| 103 |
+ {
|
|
| 104 |
+ std::vector<uint8_t> tmpBuf = std::vector<uint8_t>(2 * skipOffset); |
|
| 105 |
+ memcpy(&tmpBuf[0], &buf[offset + 2 * skipOffset], 2 * skipOffset); |
|
| 106 |
+ memcpy(&buf[offset], &tmpBuf[0], 2 * skipOffset); |
|
| 107 |
+ pos += skipOffset; |
|
| 108 |
+ } |
|
| 109 |
+ else |
|
| 110 |
+ pos += remain; |
|
| 111 |
+ } |
|
| 112 |
+ } |
|
| 113 |
+ else |
|
| 114 |
+ pos += remain; |
|
| 115 |
+ } |
|
| 116 |
+ |
|
| 117 |
+ /* Detect end of song */ |
|
| 118 |
+ if (!xSFConfig->GetPlayInfinitely()) |
|
| 119 |
+ {
|
|
| 120 |
+ if (this->currentSample >= this->lengthSample + this->fadeSample) |
|
| 121 |
+ {
|
|
| 122 |
+ samplesWritten = 0; |
|
| 123 |
+ return true; |
|
| 124 |
+ } |
|
| 125 |
+ if (this->currentSample + bufsize >= this->lengthSample + this->fadeSample) |
|
| 126 |
+ {
|
|
| 127 |
+ bufsize = this->lengthSample + this->fadeSample - this->currentSample; |
|
| 128 |
+ endFlag = true; |
|
| 129 |
+ } |
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ /* Volume */ |
|
| 133 |
+ if (!this->ignoreVolume && (!fEqual(this->volume, 1.0) || !fEqual(xSFConfig->GetVolume(), 1.0))) |
|
| 134 |
+ {
|
|
| 135 |
+ double scale = this->volume * xSFConfig->GetVolume(); |
|
| 136 |
+ short *bufShort = reinterpret_cast<short *>(&buf[0]); |
|
| 137 |
+ for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
|
| 138 |
+ {
|
|
| 139 |
+ double s1 = bufShort[2 * ofs] * scale, s2 = bufShort[2 * ofs + 1] * scale; |
|
| 140 |
+ if (s1 > 0x7FFF) |
|
| 141 |
+ s1 = 0x7FFF; |
|
| 142 |
+ else if (s1 < -0x8000) |
|
| 143 |
+ s1 = -0x8000; |
|
| 144 |
+ if (s2 > 0x7FFF) |
|
| 145 |
+ s2 = 0x7FFF; |
|
| 146 |
+ else if (s2 < -0x8000) |
|
| 147 |
+ s2 = -0x8000; |
|
| 148 |
+ bufShort[2 * ofs] = static_cast<short>(s1); |
|
| 149 |
+ bufShort[2 * ofs + 1] = static_cast<short>(s2); |
|
| 150 |
+ } |
|
| 151 |
+ } |
|
| 152 |
+ |
|
| 153 |
+ /* Fading */ |
|
| 154 |
+ if (!xSFConfig->GetPlayInfinitely() && this->fadeSample && this->currentSample + bufsize >= this->lengthSample) |
|
| 155 |
+ {
|
|
| 156 |
+ short *bufShort = reinterpret_cast<short *>(&buf[0]); |
|
| 157 |
+ for (unsigned ofs = 0; ofs < bufsize; ++ofs) |
|
| 158 |
+ {
|
|
| 159 |
+ if (this->currentSample + ofs >= this->lengthSample && this->currentSample + ofs < this->lengthSample + this->fadeSample) |
|
| 160 |
+ {
|
|
| 161 |
+ int scale = static_cast<uint64_t>(this->lengthSample + this->fadeSample - (this->currentSample + ofs)) * 0x10000 / this->fadeSample; |
|
| 162 |
+ bufShort[2 * ofs] = (bufShort[2 * ofs] * scale) >> 16; |
|
| 163 |
+ bufShort[2 * ofs + 1] = (bufShort[2 * ofs + 1] * scale) >> 16; |
|
| 164 |
+ } |
|
| 165 |
+ else if (this->currentSample + ofs >= this->lengthSample + this->fadeSample) |
|
| 166 |
+ bufShort[2 * ofs] = bufShort[2 * ofs + 1] = 0; |
|
| 167 |
+ } |
|
| 168 |
+ } |
|
| 169 |
+ |
|
| 170 |
+ this->currentSample += bufsize; |
|
| 171 |
+ samplesWritten = bufsize; |
|
| 172 |
+ return endFlag; |
|
| 173 |
+} |
|
| 174 |
+ |
|
| 175 |
+bool XSFPlayer::Load() |
|
| 176 |
+{
|
|
| 177 |
+ this->lengthInMS = this->xSF->GetLengthMS(xSFConfig->GetDefaultLength()); |
|
| 178 |
+ this->fadeInMS = this->xSF->GetFadeMS(xSFConfig->GetDefaultFade()); |
|
| 179 |
+ this->lengthSample = static_cast<uint64_t>(this->lengthInMS) * this->sampleRate / 1000; |
|
| 180 |
+ this->fadeSample = static_cast<uint64_t>(this->fadeInMS) * this->sampleRate / 1000; |
|
| 181 |
+ this->volume = this->xSF->GetVolume(xSFConfig->GetVolumeType(), xSFConfig->GetPeakType()); |
|
| 182 |
+ return true; |
|
| 183 |
+} |
|
| 184 |
+ |
|
| 185 |
+void XSFPlayer::SeekTop() |
|
| 186 |
+{
|
|
| 187 |
+ this->skipSilenceOnStartSec = xSFConfig->GetSkipSilenceOnStartSec(); |
|
| 188 |
+ this->currentSample = this->detectedSilenceSec = this->detectedSilenceSample = 0; |
|
| 189 |
+ this->prevSampleL = this->prevSampleR = XSFPlayer::CHECK_SILENCE_BIAS; |
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+#ifdef WINAMP_PLUGIN |
|
| 193 |
+ |
|
| 194 |
+static inline DWORD TicksDiff(DWORD prev, DWORD cur) { return cur >= prev ? cur - prev : 0xFFFFFFFF - prev + cur; }
|
|
| 195 |
+ |
|
| 196 |
+int XSFPlayer::Seek(unsigned seekPosition, volatile int *killswitch, std::vector<uint8_t> &buf, Out_Module *outMod) |
|
| 197 |
+{
|
|
| 198 |
+ unsigned bufsize = buf.size() >> 2, seekSample = static_cast<uint64_t>(seekPosition) * this->sampleRate / 1000; |
|
| 199 |
+ DWORD prevTick = outMod ? GetTickCount() : 0; |
|
| 200 |
+ if (seekSample < this->currentSample) |
|
| 201 |
+ {
|
|
| 202 |
+ this->Terminate(); |
|
| 203 |
+ this->Load(); |
|
| 204 |
+ this->SeekTop(); |
|
| 205 |
+ } |
|
| 206 |
+ while (seekSample - this->currentSample > bufsize) |
|
| 207 |
+ {
|
|
| 208 |
+ if (killswitch && *killswitch) |
|
| 209 |
+ return 1; |
|
| 210 |
+ if (outMod) |
|
| 211 |
+ {
|
|
| 212 |
+ DWORD curTick = GetTickCount(); |
|
| 213 |
+ if (TicksDiff(prevTick, curTick) >= 500) |
|
| 214 |
+ {
|
|
| 215 |
+ prevTick = curTick; |
|
| 216 |
+ unsigned cur = static_cast<uint64_t>(this->currentSample) * 1000 / this->sampleRate; |
|
| 217 |
+ outMod->Flush(cur); |
|
| 218 |
+ } |
|
| 219 |
+ } |
|
| 220 |
+ this->GenerateSamples(buf, 0, bufsize); |
|
| 221 |
+ this->currentSample += bufsize; |
|
| 222 |
+ } |
|
| 223 |
+ if (seekSample - this->currentSample > 0) |
|
| 224 |
+ {
|
|
| 225 |
+ this->GenerateSamples(buf, 0, seekSample - this->currentSample); |
|
| 226 |
+ this->currentSample = seekSample; |
|
| 227 |
+ } |
|
| 228 |
+ if (outMod) |
|
| 229 |
+ outMod->Flush(seekPosition); |
|
| 230 |
+ return 0; |
|
| 231 |
+} |
|
| 232 |
+ |
|
| 233 |
+#endif |