| ... | ... |
@@ -30,18 +30,11 @@ const char *XSFPlayer::WinampExts = "ncsf;minincsf\0DS Nitro Composer Sound Form |
| 30 | 30 |
|
| 31 | 31 |
extern XSFConfig *xSFConfig; |
| 32 | 32 |
|
| 33 |
-XSFPlayer *XSFPlayer::Create(const std::string &fn) |
|
| 33 |
+XSFPlayer *XSFPlayer::Create(const std::filesystem::path &path) |
|
| 34 | 34 |
{
|
| 35 |
- return new XSFPlayer_NCSF(fn); |
|
| 35 |
+ return new XSFPlayer_NCSF(path); |
|
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 |
-#ifdef _WIN32 |
|
| 39 |
-XSFPlayer *XSFPlayer::Create(const std::wstring &fn) |
|
| 40 |
-{
|
|
| 41 |
- return new XSFPlayer_NCSF(fn); |
|
| 42 |
-} |
|
| 43 |
-#endif |
|
| 44 |
- |
|
| 45 | 38 |
void XSFPlayer_NCSF::MapNCSFSection(const std::vector<std::uint8_t> §ion) |
| 46 | 39 |
{
|
| 47 | 40 |
std::uint32_t size = Get32BitsLE(§ion[8]), finalSize = size; |
| ... | ... |
@@ -72,11 +65,7 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 72 | 65 |
{
|
| 73 | 66 |
if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
| 74 | 67 |
{
|
| 75 |
-#ifdef _WIN32 |
|
| 76 |
- auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue("_lib")).wstring(), 8, 12);
|
|
| 77 |
-#else |
|
| 78 |
- auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue("_lib")).string(), 8, 12);
|
|
| 79 |
-#endif |
|
| 68 |
+ auto libxSF = std::make_unique<XSFFile>(xSFToLoad->GetFilepath().parent_path() / xSFToLoad->GetTagValue("_lib"), 8, 12);
|
|
| 80 | 69 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 81 | 70 |
return false; |
| 82 | 71 |
} |
| ... | ... |
@@ -93,11 +82,7 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 93 | 82 |
if (xSFToLoad->GetTagExists(libTag)) |
| 94 | 83 |
{
|
| 95 | 84 |
found = true; |
| 96 |
-#ifdef _WIN32 |
|
| 97 |
- auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue(libTag)).wstring(), 8, 12); |
|
| 98 |
-#else |
|
| 99 |
- auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue(libTag)).string(), 8, 12); |
|
| 100 |
-#endif |
|
| 85 |
+ auto libxSF = std::make_unique<XSFFile>(xSFToLoad->GetFilepath().parent_path() / xSFToLoad->GetTagValue(libTag), 8, 12); |
|
| 101 | 86 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 102 | 87 |
return false; |
| 103 | 88 |
} |
| ... | ... |
@@ -111,20 +96,12 @@ bool XSFPlayer_NCSF::LoadNCSF() |
| 111 | 96 |
return this->RecursiveLoadNCSF(this->xSF.get(), 1); |
| 112 | 97 |
} |
| 113 | 98 |
|
| 114 |
-XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes() |
|
| 99 |
+XSFPlayer_NCSF::XSFPlayer_NCSF(const std::filesystem::path &path) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes() |
|
| 115 | 100 |
{
|
| 116 | 101 |
this->uses32BitSamplesClampedTo16Bit = true; |
| 117 |
- this->xSF.reset(new XSFFile(filename, 8, 12)); |
|
| 102 |
+ this->xSF.reset(new XSFFile(path, 8, 12)); |
|
| 118 | 103 |
} |
| 119 | 104 |
|
| 120 |
-#ifdef _WIN32 |
|
| 121 |
-XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes() |
|
| 122 |
-{
|
|
| 123 |
- this->uses32BitSamplesClampedTo16Bit = true; |
|
| 124 |
- this->xSF.reset(new XSFFile(filename, 8, 12)); |
|
| 125 |
-} |
|
| 126 |
-#endif |
|
| 127 |
- |
|
| 128 | 105 |
#ifdef _DEBUG |
| 129 | 106 |
static HANDLE soundViewThreadHandle = INVALID_HANDLE_VALUE; |
| 130 | 107 |
static bool killSoundViewThread; |
* 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().
| ... | ... |
@@ -8,17 +8,22 @@ |
| 8 | 8 |
* https://github.com/fincs/FSS |
| 9 | 9 |
*/ |
| 10 | 10 |
|
| 11 |
+#include <algorithm> |
|
| 12 |
+#include <bitset> |
|
| 11 | 13 |
#include <filesystem> |
| 12 | 14 |
#include <memory> |
| 13 |
-#include <cstdlib> |
|
| 14 |
-#include <ctime> |
|
| 15 |
+#include <string> |
|
| 16 |
+#include <vector> |
|
| 17 |
+#include <cstddef> |
|
| 18 |
+#include <cstdint> |
|
| 15 | 19 |
#include <zlib.h> |
| 16 |
-#include "convert.h" |
|
| 17 |
-#include "XSFPlayer_NCSF.h" |
|
| 18 |
-#include "XSFConfig_NCSF.h" |
|
| 19 | 20 |
#include "XSFCommon.h" |
| 21 |
+#include "XSFConfig_NCSF.h" |
|
| 22 |
+#include "XSFPlayer_NCSF.h" |
|
| 20 | 23 |
#include "SSEQPlayer/SDAT.h" |
| 21 | 24 |
#include "SSEQPlayer/Player.h" |
| 25 |
+#include "SSEQPlayer/common.h" |
|
| 26 |
+#include "SSEQPlayer/consts.h" |
|
| 22 | 27 |
|
| 23 | 28 |
const char *XSFPlayer::WinampDescription = "NCSF Decoder"; |
| 24 | 29 |
const char *XSFPlayer::WinampExts = "ncsf;minincsf\0DS Nitro Composer Sound Format files (*.ncsf;*.minincsf)\0"; |
| ... | ... |
@@ -37,9 +42,9 @@ XSFPlayer *XSFPlayer::Create(const std::wstring &fn) |
| 37 | 42 |
} |
| 38 | 43 |
#endif |
| 39 | 44 |
|
| 40 |
-void XSFPlayer_NCSF::MapNCSFSection(const std::vector<uint8_t> §ion) |
|
| 45 |
+void XSFPlayer_NCSF::MapNCSFSection(const std::vector<std::uint8_t> §ion) |
|
| 41 | 46 |
{
|
| 42 |
- uint32_t size = Get32BitsLE(§ion[8]), finalSize = size; |
|
| 47 |
+ std::uint32_t size = Get32BitsLE(§ion[8]), finalSize = size; |
|
| 43 | 48 |
if (this->sdatData.empty()) |
| 44 | 49 |
this->sdatData.resize(finalSize, 0); |
| 45 | 50 |
else if (this->sdatData.size() < size) |
| ... | ... |
@@ -183,12 +188,12 @@ bool XSFPlayer_NCSF::Load() |
| 183 | 188 |
return XSFPlayer::Load(); |
| 184 | 189 |
} |
| 185 | 190 |
|
| 186 |
-static inline int32_t muldiv7(int32_t val, uint8_t mul) |
|
| 191 |
+static inline std::int32_t muldiv7(std::int32_t val, std::uint8_t mul) |
|
| 187 | 192 |
{
|
| 188 | 193 |
return mul == 127 ? val : ((val * mul) >> 7); |
| 189 | 194 |
} |
| 190 | 195 |
|
| 191 |
-void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, unsigned samples) |
|
| 196 |
+void XSFPlayer_NCSF::GenerateSamples(std::vector<std::uint8_t> &buf, unsigned offset, unsigned samples) |
|
| 192 | 197 |
{
|
| 193 | 198 |
unsigned long mute = this->mutes.to_ulong(); |
| 194 | 199 |
|
| ... | ... |
@@ -196,22 +201,22 @@ void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, |
| 196 | 201 |
{
|
| 197 | 202 |
this->secondsIntoPlayback += this->secondsPerSample; |
| 198 | 203 |
|
| 199 |
- int32_t leftChannel = 0, rightChannel = 0; |
|
| 204 |
+ std::int32_t leftChannel = 0, rightChannel = 0; |
|
| 200 | 205 |
|
| 201 | 206 |
// I need to advance the sound channels here |
| 202 | 207 |
for (int i = 0; i < 16; ++i) |
| 203 | 208 |
{
|
| 204 | 209 |
Channel &chn = this->player.channels[i]; |
| 205 | 210 |
|
| 206 |
- if (chn.state > CS_NONE) |
|
| 211 |
+ if (chn.state > ChannelState::None) |
|
| 207 | 212 |
{
|
| 208 |
- int32_t sample = chn.GenerateSample(); |
|
| 213 |
+ std::int32_t sample = chn.GenerateSample(); |
|
| 209 | 214 |
chn.IncrementSample(); |
| 210 | 215 |
|
| 211 | 216 |
if (mute & BIT(i)) |
| 212 | 217 |
continue; |
| 213 | 218 |
|
| 214 |
- uint8_t datashift = chn.reg.volumeDiv; |
|
| 219 |
+ std::uint8_t datashift = chn.reg.volumeDiv; |
|
| 215 | 220 |
if (datashift == 3) |
| 216 | 221 |
datashift = 4; |
| 217 | 222 |
sample = muldiv7(sample, chn.reg.volumeMul) >> datashift; |
| ... | ... |
@@ -254,7 +259,7 @@ void XSFPlayer_NCSF::SetMutes(const std::bitset<16> &newMutes) |
| 254 | 259 |
} |
| 255 | 260 |
|
| 256 | 261 |
#ifdef _DEBUG |
| 257 |
-const Channel &XSFPlayer_NCSF::GetChannel(size_t chanNum) const |
|
| 262 |
+const Channel &XSFPlayer_NCSF::GetChannel(std::size_t chanNum) const |
|
| 258 | 263 |
{
|
| 259 | 264 |
return this->player.channels[chanNum]; |
| 260 | 265 |
} |
| ... | ... |
@@ -106,14 +106,14 @@ bool XSFPlayer_NCSF::LoadNCSF() |
| 106 | 106 |
return this->RecursiveLoadNCSF(this->xSF.get(), 1); |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
-XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer() |
|
| 109 |
+XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes() |
|
| 110 | 110 |
{
|
| 111 | 111 |
this->uses32BitSamplesClampedTo16Bit = true; |
| 112 | 112 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| 113 | 113 |
} |
| 114 | 114 |
|
| 115 | 115 |
#ifdef _WIN32 |
| 116 |
-XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
|
| 116 |
+XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes() |
|
| 117 | 117 |
{
|
| 118 | 118 |
this->uses32BitSamplesClampedTo16Bit = true; |
| 119 | 119 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| ... | ... |
@@ -8,6 +8,7 @@ |
| 8 | 8 |
* https://github.com/fincs/FSS |
| 9 | 9 |
*/ |
| 10 | 10 |
|
| 11 |
+#include <filesystem> |
|
| 11 | 12 |
#include <memory> |
| 12 | 13 |
#include <cstdlib> |
| 13 | 14 |
#include <ctime> |
| ... | ... |
@@ -67,9 +68,9 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 67 | 68 |
if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
| 68 | 69 |
{
|
| 69 | 70 |
#ifdef _WIN32 |
| 70 |
- auto libxSF = std::make_unique<XSFFile>(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib")), 8, 12);
|
|
| 71 |
+ auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue("_lib")).wstring(), 8, 12);
|
|
| 71 | 72 |
#else |
| 72 |
- auto libxSF = std::make_unique<XSFFile>(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib"), 8, 12);
|
|
| 73 |
+ auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue("_lib")).string(), 8, 12);
|
|
| 73 | 74 |
#endif |
| 74 | 75 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 75 | 76 |
return false; |
| ... | ... |
@@ -88,9 +89,9 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 88 | 89 |
{
|
| 89 | 90 |
found = true; |
| 90 | 91 |
#ifdef _WIN32 |
| 91 |
- auto libxSF = std::make_unique<XSFFile>(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag)), 8, 12); |
|
| 92 |
+ auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue(libTag)).wstring(), 8, 12); |
|
| 92 | 93 |
#else |
| 93 |
- auto libxSF = std::make_unique<XSFFile>(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag), 8, 12); |
|
| 94 |
+ auto libxSF = std::make_unique<XSFFile>((std::filesystem::path(xSFToLoad->GetFilename()).parent_path() / xSFToLoad->GetTagValue(libTag)).string(), 8, 12); |
|
| 94 | 95 |
#endif |
| 95 | 96 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 96 | 97 |
return false; |
(This also means the playback of songs with randomness in them will be deterministic now.)
| ... | ... |
@@ -166,8 +166,6 @@ bool XSFPlayer_NCSF::Load() |
| 166 | 166 |
soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr); |
| 167 | 167 |
#endif |
| 168 | 168 |
|
| 169 |
- std::srand(static_cast<unsigned>(std::time(nullptr))); |
|
| 170 |
- |
|
| 171 | 169 |
PseudoFile file; |
| 172 | 170 |
file.data = &this->sdatData; |
| 173 | 171 |
this->sdat.reset(new SDAT(file, this->sseq)); |
| ... | ... |
@@ -67,9 +67,9 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 67 | 67 |
if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
| 68 | 68 |
{
|
| 69 | 69 |
#ifdef _WIN32 |
| 70 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib")), 8, 12));
|
|
| 70 |
+ auto libxSF = std::make_unique<XSFFile>(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib")), 8, 12);
|
|
| 71 | 71 |
#else |
| 72 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib"), 8, 12));
|
|
| 72 |
+ auto libxSF = std::make_unique<XSFFile>(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib"), 8, 12);
|
|
| 73 | 73 |
#endif |
| 74 | 74 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 75 | 75 |
return false; |
| ... | ... |
@@ -88,9 +88,9 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 88 | 88 |
{
|
| 89 | 89 |
found = true; |
| 90 | 90 |
#ifdef _WIN32 |
| 91 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag)), 8, 12)); |
|
| 91 |
+ auto libxSF = std::make_unique<XSFFile>(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag)), 8, 12); |
|
| 92 | 92 |
#else |
| 93 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag), 8, 12)); |
|
| 93 |
+ auto libxSF = std::make_unique<XSFFile>(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag), 8, 12); |
|
| 94 | 94 |
#endif |
| 95 | 95 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 96 | 96 |
return false; |
| ... | ... |
@@ -43,7 +43,7 @@ void XSFPlayer_NCSF::MapNCSFSection(const std::vector<uint8_t> §ion) |
| 43 | 43 |
this->sdatData.resize(finalSize, 0); |
| 44 | 44 |
else if (this->sdatData.size() < size) |
| 45 | 45 |
this->sdatData.resize(finalSize); |
| 46 |
- memcpy(&this->sdatData[0], §ion[0], size); |
|
| 46 |
+ std::copy_n(§ion[0], size, &this->sdatData[0]); |
|
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 | 49 |
bool XSFPlayer_NCSF::MapNCSF(XSFFile *xSFToLoad) |
* Replace the (w)stringify functions with the standard std::to_(w)string functions.
* Replace convertTo with versions that use type_traits to determine which standard string conversion function to call, as well as handle enums specically.
| ... | ... |
@@ -83,7 +83,7 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 83 | 83 |
do |
| 84 | 84 |
{
|
| 85 | 85 |
found = false; |
| 86 |
- std::string libTag = "_lib" + stringify(n++); |
|
| 86 |
+ std::string libTag = "_lib" + std::to_string(n++); |
|
| 87 | 87 |
if (xSFToLoad->GetTagExists(libTag)) |
| 88 | 88 |
{
|
| 89 | 89 |
found = true; |
(I never remember to update these and besides, GitHub history can show when they were last modified.)
Backwards compatibility is kept by treating the lack of PLAYER info as
if all channels are able to be allocated.
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2014-10-18 |
|
| 4 |
+ * Last modification on 2014-10-25 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -173,6 +173,7 @@ bool XSFPlayer_NCSF::Load() |
| 173 | 173 |
file.data = &this->sdatData; |
| 174 | 174 |
this->sdat.reset(new SDAT(file, this->sseq)); |
| 175 | 175 |
auto *sseqToPlay = this->sdat->sseq.get(); |
| 176 |
+ this->player.allowedChannels = std::bitset<16>(this->sdat->player.channelMask); |
|
| 176 | 177 |
this->player.sseqVol = Cnv_Scale(sseqToPlay->info.vol); |
| 177 | 178 |
this->player.sampleRate = this->sampleRate; |
| 178 | 179 |
this->player.Setup(sseqToPlay); |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2014-10-13 |
|
| 4 |
+ * Last modification on 2014-10-18 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -173,10 +173,9 @@ bool XSFPlayer_NCSF::Load() |
| 173 | 173 |
file.data = &this->sdatData; |
| 174 | 174 |
this->sdat.reset(new SDAT(file, this->sseq)); |
| 175 | 175 |
auto *sseqToPlay = this->sdat->sseq.get(); |
| 176 |
- this->sseqVol = sseqToPlay->info.vol; |
|
| 176 |
+ this->player.sseqVol = Cnv_Scale(sseqToPlay->info.vol); |
|
| 177 | 177 |
this->player.sampleRate = this->sampleRate; |
| 178 | 178 |
this->player.Setup(sseqToPlay); |
| 179 |
- //this->player.masterVol = sseqToPlay->info.vol; |
|
| 180 | 179 |
this->player.Timer(); |
| 181 | 180 |
this->secondsPerSample = 1.0 / this->sampleRate; |
| 182 | 181 |
this->secondsIntoPlayback = 0; |
| ... | ... |
@@ -223,12 +222,6 @@ void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, |
| 223 | 222 |
} |
| 224 | 223 |
} |
| 225 | 224 |
|
| 226 |
- leftChannel = muldiv7(leftChannel, 127 - this->player.masterVol); |
|
| 227 |
- rightChannel = muldiv7(rightChannel, 127 - this->player.masterVol); |
|
| 228 |
- |
|
| 229 |
- //leftChannel = muldiv7(leftChannel, this->sseqVol); |
|
| 230 |
- //rightChannel = muldiv7(rightChannel, this->sseqVol); |
|
| 231 |
- |
|
| 232 | 225 |
buf[offset++] = leftChannel & 0xFF; |
| 233 | 226 |
buf[offset++] = (leftChannel >> 8) & 0xFF; |
| 234 | 227 |
buf[offset++] = (leftChannel >> 16) & 0xFF; |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2014-10-05 |
|
| 4 |
+ * Last modification on 2014-10-13 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -10,6 +10,8 @@ |
| 10 | 10 |
*/ |
| 11 | 11 |
|
| 12 | 12 |
#include <memory> |
| 13 |
+#include <cstdlib> |
|
| 14 |
+#include <ctime> |
|
| 13 | 15 |
#include <zlib.h> |
| 14 | 16 |
#include "convert.h" |
| 15 | 17 |
#include "XSFPlayer_NCSF.h" |
| ... | ... |
@@ -165,6 +167,8 @@ bool XSFPlayer_NCSF::Load() |
| 165 | 167 |
soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr); |
| 166 | 168 |
#endif |
| 167 | 169 |
|
| 170 |
+ std::srand(static_cast<unsigned>(std::time(nullptr))); |
|
| 171 |
+ |
|
| 168 | 172 |
PseudoFile file; |
| 169 | 173 |
file.data = &this->sdatData; |
| 170 | 174 |
this->sdat.reset(new SDAT(file, this->sseq)); |
Also commented out the code that uses the SSEQ's volume, it seems as if
the DS doesn't use it so I probably shouldn't be using it either.
| ... | ... |
@@ -222,8 +222,8 @@ void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, |
| 222 | 222 |
leftChannel = muldiv7(leftChannel, 127 - this->player.masterVol); |
| 223 | 223 |
rightChannel = muldiv7(rightChannel, 127 - this->player.masterVol); |
| 224 | 224 |
|
| 225 |
- leftChannel = muldiv7(leftChannel, this->sseqVol); |
|
| 226 |
- rightChannel = muldiv7(rightChannel, this->sseqVol); |
|
| 225 |
+ //leftChannel = muldiv7(leftChannel, this->sseqVol); |
|
| 226 |
+ //rightChannel = muldiv7(rightChannel, this->sseqVol); |
|
| 227 | 227 |
|
| 228 | 228 |
buf[offset++] = leftChannel & 0xFF; |
| 229 | 229 |
buf[offset++] = (leftChannel >> 8) & 0xFF; |
Also added a clone of DeSmuME's Sound View that is only build during a
debug build, which helped to identify the above issues.
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2014-09-24 |
|
| 4 |
+ * Last modification on 2014-10-05 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -13,6 +13,7 @@ |
| 13 | 13 |
#include <zlib.h> |
| 14 | 14 |
#include "convert.h" |
| 15 | 15 |
#include "XSFPlayer_NCSF.h" |
| 16 |
+#include "XSFConfig_NCSF.h" |
|
| 16 | 17 |
#include "XSFCommon.h" |
| 17 | 18 |
#include "SSEQPlayer/SDAT.h" |
| 18 | 19 |
#include "SSEQPlayer/Player.h" |
| ... | ... |
@@ -20,6 +21,8 @@ |
| 20 | 21 |
const char *XSFPlayer::WinampDescription = "NCSF Decoder"; |
| 21 | 22 |
const char *XSFPlayer::WinampExts = "ncsf;minincsf\0DS Nitro Composer Sound Format files (*.ncsf;*.minincsf)\0"; |
| 22 | 23 |
|
| 24 |
+extern XSFConfig *xSFConfig; |
|
| 25 |
+ |
|
| 23 | 26 |
XSFPlayer *XSFPlayer::Create(const std::string &fn) |
| 24 | 27 |
{
|
| 25 | 28 |
return new XSFPlayer_NCSF(fn); |
| ... | ... |
@@ -115,11 +118,53 @@ XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
| 115 | 118 |
} |
| 116 | 119 |
#endif |
| 117 | 120 |
|
| 121 |
+#ifdef _DEBUG |
|
| 122 |
+static HANDLE soundViewThreadHandle = INVALID_HANDLE_VALUE; |
|
| 123 |
+static bool killSoundViewThread; |
|
| 124 |
+ |
|
| 125 |
+static DWORD WINAPI soundViewThread(void *b) |
|
| 126 |
+{
|
|
| 127 |
+ auto xSFConfig_NCSF = static_cast<XSFConfig_NCSF *>(xSFConfig); |
|
| 128 |
+ xSFConfig_NCSF->CallSoundView(static_cast<XSFPlayer_NCSF *>(b), xSFConfig->GetHInstance(), nullptr); |
|
| 129 |
+ MSG msg; |
|
| 130 |
+ while (!killSoundViewThread) |
|
| 131 |
+ {
|
|
| 132 |
+ xSFConfig_NCSF->RefreshSoundView(); |
|
| 133 |
+ if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) |
|
| 134 |
+ {
|
|
| 135 |
+ TranslateMessage(&msg); |
|
| 136 |
+ DispatchMessageW(&msg); |
|
| 137 |
+ } |
|
| 138 |
+ } |
|
| 139 |
+ xSFConfig_NCSF->CloseSoundView(); |
|
| 140 |
+ return 0; |
|
| 141 |
+} |
|
| 142 |
+#endif |
|
| 143 |
+ |
|
| 144 |
+XSFPlayer_NCSF::~XSFPlayer_NCSF() |
|
| 145 |
+{
|
|
| 146 |
+#ifdef _DEBUG |
|
| 147 |
+ killSoundViewThread = true; |
|
| 148 |
+ if (WaitForSingleObject(soundViewThreadHandle, 2000) == WAIT_TIMEOUT) |
|
| 149 |
+ {
|
|
| 150 |
+ TerminateThread(soundViewThreadHandle, 0); |
|
| 151 |
+ static_cast<XSFConfig_NCSF *>(xSFConfig)->CloseSoundView(); |
|
| 152 |
+ } |
|
| 153 |
+ CloseHandle(soundViewThreadHandle); |
|
| 154 |
+ soundViewThreadHandle = INVALID_HANDLE_VALUE; |
|
| 155 |
+#endif |
|
| 156 |
+} |
|
| 157 |
+ |
|
| 118 | 158 |
bool XSFPlayer_NCSF::Load() |
| 119 | 159 |
{
|
| 120 | 160 |
if (!this->LoadNCSF()) |
| 121 | 161 |
return false; |
| 122 | 162 |
|
| 163 |
+#ifdef _DEBUG |
|
| 164 |
+ killSoundViewThread = false; |
|
| 165 |
+ soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr); |
|
| 166 |
+#endif |
|
| 167 |
+ |
|
| 123 | 168 |
PseudoFile file; |
| 124 | 169 |
file.data = &this->sdatData; |
| 125 | 170 |
this->sdat.reset(new SDAT(file, this->sseq)); |
| ... | ... |
@@ -211,3 +256,10 @@ void XSFPlayer_NCSF::SetMutes(const std::bitset<16> &newMutes) |
| 211 | 256 |
{
|
| 212 | 257 |
this->mutes = newMutes; |
| 213 | 258 |
} |
| 259 |
+ |
|
| 260 |
+#ifdef _DEBUG |
|
| 261 |
+const Channel &XSFPlayer_NCSF::GetChannel(size_t chanNum) const |
|
| 262 |
+{
|
|
| 263 |
+ return this->player.channels[chanNum]; |
|
| 264 |
+} |
|
| 265 |
+#endif |
* 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.
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2014-09-17 |
|
| 4 |
+ * Last modification on 2014-09-24 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -25,7 +25,7 @@ XSFPlayer *XSFPlayer::Create(const std::string &fn) |
| 25 | 25 |
return new XSFPlayer_NCSF(fn); |
| 26 | 26 |
} |
| 27 | 27 |
|
| 28 |
-#ifdef _MSC_VER |
|
| 28 |
+#ifdef _WIN32 |
|
| 29 | 29 |
XSFPlayer *XSFPlayer::Create(const std::wstring &fn) |
| 30 | 30 |
{
|
| 31 | 31 |
return new XSFPlayer_NCSF(fn); |
| ... | ... |
@@ -62,10 +62,10 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 62 | 62 |
{
|
| 63 | 63 |
if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
| 64 | 64 |
{
|
| 65 |
-#ifdef _MSC_VER |
|
| 66 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 8, 12));
|
|
| 65 |
+#ifdef _WIN32 |
|
| 66 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib")), 8, 12));
|
|
| 67 | 67 |
#else |
| 68 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 8, 12));
|
|
| 68 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib"), 8, 12));
|
|
| 69 | 69 |
#endif |
| 70 | 70 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 71 | 71 |
return false; |
| ... | ... |
@@ -83,10 +83,10 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 83 | 83 |
if (xSFToLoad->GetTagExists(libTag)) |
| 84 | 84 |
{
|
| 85 | 85 |
found = true; |
| 86 |
-#ifdef _MSC_VER |
|
| 87 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 8, 12)); |
|
| 86 |
+#ifdef _WIN32 |
|
| 87 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag)), 8, 12)); |
|
| 88 | 88 |
#else |
| 89 |
- auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 8, 12)); |
|
| 89 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag), 8, 12)); |
|
| 90 | 90 |
#endif |
| 91 | 91 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 92 | 92 |
return false; |
| ... | ... |
@@ -107,7 +107,7 @@ XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer() |
| 107 | 107 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| 108 | 108 |
} |
| 109 | 109 |
|
| 110 |
-#ifdef _MSC_VER |
|
| 110 |
+#ifdef _WIN32 |
|
| 111 | 111 |
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
| 112 | 112 |
{
|
| 113 | 113 |
this->uses32BitSamplesClampedTo16Bit = true; |
* [2SF] Used more up-to-date asmjit, despite the ugly looking code.
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-26 |
|
| 4 |
+ * Last modification on 2014-09-17 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -25,10 +25,12 @@ XSFPlayer *XSFPlayer::Create(const std::string &fn) |
| 25 | 25 |
return new XSFPlayer_NCSF(fn); |
| 26 | 26 |
} |
| 27 | 27 |
|
| 28 |
+#ifdef _MSC_VER |
|
| 28 | 29 |
XSFPlayer *XSFPlayer::Create(const std::wstring &fn) |
| 29 | 30 |
{
|
| 30 | 31 |
return new XSFPlayer_NCSF(fn); |
| 31 | 32 |
} |
| 33 |
+#endif |
|
| 32 | 34 |
|
| 33 | 35 |
void XSFPlayer_NCSF::MapNCSFSection(const std::vector<uint8_t> §ion) |
| 34 | 36 |
{
|
| ... | ... |
@@ -60,7 +62,7 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 60 | 62 |
{
|
| 61 | 63 |
if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
| 62 | 64 |
{
|
| 63 |
-#ifdef _WIN32 |
|
| 65 |
+#ifdef _MSC_VER |
|
| 64 | 66 |
auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 8, 12));
|
| 65 | 67 |
#else |
| 66 | 68 |
auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 8, 12));
|
| ... | ... |
@@ -81,7 +83,7 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 81 | 83 |
if (xSFToLoad->GetTagExists(libTag)) |
| 82 | 84 |
{
|
| 83 | 85 |
found = true; |
| 84 |
-#ifdef _WIN32 |
|
| 86 |
+#ifdef _MSC_VER |
|
| 85 | 87 |
auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 8, 12)); |
| 86 | 88 |
#else |
| 87 | 89 |
auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 8, 12)); |
| ... | ... |
@@ -105,11 +107,13 @@ XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer() |
| 105 | 107 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| 106 | 108 |
} |
| 107 | 109 |
|
| 110 |
+#ifdef _MSC_VER |
|
| 108 | 111 |
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
| 109 | 112 |
{
|
| 110 | 113 |
this->uses32BitSamplesClampedTo16Bit = true; |
| 111 | 114 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| 112 | 115 |
} |
| 116 |
+#endif |
|
| 113 | 117 |
|
| 114 | 118 |
bool XSFPlayer_NCSF::Load() |
| 115 | 119 |
{
|
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF 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 |
* |
| ... | ... |
@@ -101,11 +101,13 @@ bool XSFPlayer_NCSF::LoadNCSF() |
| 101 | 101 |
|
| 102 | 102 |
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer() |
| 103 | 103 |
{
|
| 104 |
+ this->uses32BitSamplesClampedTo16Bit = true; |
|
| 104 | 105 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| 105 | 106 |
} |
| 106 | 107 |
|
| 107 | 108 |
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
| 108 | 109 |
{
|
| 110 |
+ this->uses32BitSamplesClampedTo16Bit = true; |
|
| 109 | 111 |
this->xSF.reset(new XSFFile(filename, 8, 12)); |
| 110 | 112 |
} |
| 111 | 113 |
|
| ... | ... |
@@ -130,14 +132,6 @@ bool XSFPlayer_NCSF::Load() |
| 130 | 132 |
return XSFPlayer::Load(); |
| 131 | 133 |
} |
| 132 | 134 |
|
| 133 |
-template<typename T1, typename T2> static inline void clamp(T1 &valueToClamp, const T2 &minValue, const T2 &maxValue) |
|
| 134 |
-{
|
|
| 135 |
- if (valueToClamp < minValue) |
|
| 136 |
- valueToClamp = minValue; |
|
| 137 |
- else if (valueToClamp > maxValue) |
|
| 138 |
- valueToClamp = maxValue; |
|
| 139 |
-} |
|
| 140 |
- |
|
| 141 | 135 |
static inline int32_t muldiv7(int32_t val, uint8_t mul) |
| 142 | 136 |
{
|
| 143 | 137 |
return mul == 127 ? val : ((val * mul) >> 7); |
| ... | ... |
@@ -182,13 +176,14 @@ void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, |
| 182 | 176 |
leftChannel = muldiv7(leftChannel, this->sseqVol); |
| 183 | 177 |
rightChannel = muldiv7(rightChannel, this->sseqVol); |
| 184 | 178 |
|
| 185 |
- clamp(leftChannel, -0x8000, 0x7FFF); |
|
| 186 |
- clamp(rightChannel, -0x8000, 0x7FFF); |
|
| 187 |
- |
|
| 188 | 179 |
buf[offset++] = leftChannel & 0xFF; |
| 189 | 180 |
buf[offset++] = (leftChannel >> 8) & 0xFF; |
| 181 |
+ buf[offset++] = (leftChannel >> 16) & 0xFF; |
|
| 182 |
+ buf[offset++] = (leftChannel >> 24) & 0xFF; |
|
| 190 | 183 |
buf[offset++] = rightChannel & 0xFF; |
| 191 | 184 |
buf[offset++] = (rightChannel >> 8) & 0xFF; |
| 185 |
+ buf[offset++] = (rightChannel >> 16) & 0xFF; |
|
| 186 |
+ buf[offset++] = (rightChannel >> 24) & 0xFF; |
|
| 192 | 187 |
|
| 193 | 188 |
if (this->secondsIntoPlayback > this->secondsUntilNextClock) |
| 194 | 189 |
{
|
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-01 |
|
| 4 |
+ * Last modification on 2013-04-23 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -96,17 +96,17 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 96 | 96 |
|
| 97 | 97 |
bool XSFPlayer_NCSF::LoadNCSF() |
| 98 | 98 |
{
|
| 99 |
- return this->RecursiveLoadNCSF(this->xSF, 1); |
|
| 99 |
+ return this->RecursiveLoadNCSF(this->xSF.get(), 1); |
|
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 | 102 |
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer() |
| 103 | 103 |
{
|
| 104 |
- this->xSF = new XSFFile(filename, 8, 12); |
|
| 104 |
+ this->xSF.reset(new XSFFile(filename, 8, 12)); |
|
| 105 | 105 |
} |
| 106 | 106 |
|
| 107 | 107 |
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
| 108 | 108 |
{
|
| 109 |
- this->xSF = new XSFFile(filename, 8, 12); |
|
| 109 |
+ this->xSF.reset(new XSFFile(filename, 8, 12)); |
|
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 | 112 |
bool XSFPlayer_NCSF::Load() |
| ... | ... |
@@ -118,9 +118,10 @@ bool XSFPlayer_NCSF::Load() |
| 118 | 118 |
file.data = &this->sdatData; |
| 119 | 119 |
this->sdat.reset(new SDAT(file, this->sseq)); |
| 120 | 120 |
auto *sseqToPlay = this->sdat->sseq.get(); |
| 121 |
+ this->sseqVol = sseqToPlay->info.vol; |
|
| 121 | 122 |
this->player.sampleRate = this->sampleRate; |
| 122 | 123 |
this->player.Setup(sseqToPlay); |
| 123 |
- //this->player.masterVol = sseq->info.vol; |
|
| 124 |
+ //this->player.masterVol = sseqToPlay->info.vol; |
|
| 124 | 125 |
this->player.Timer(); |
| 125 | 126 |
this->secondsPerSample = 1.0 / this->sampleRate; |
| 126 | 127 |
this->secondsIntoPlayback = 0; |
| ... | ... |
@@ -178,6 +179,9 @@ void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, |
| 178 | 179 |
leftChannel = muldiv7(leftChannel, 127 - this->player.masterVol); |
| 179 | 180 |
rightChannel = muldiv7(rightChannel, 127 - this->player.masterVol); |
| 180 | 181 |
|
| 182 |
+ leftChannel = muldiv7(leftChannel, this->sseqVol); |
|
| 183 |
+ rightChannel = muldiv7(rightChannel, this->sseqVol); |
|
| 184 |
+ |
|
| 181 | 185 |
clamp(leftChannel, -0x8000, 0x7FFF); |
| 182 | 186 |
clamp(rightChannel, -0x8000, 0x7FFF); |
| 183 | 187 |
|
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* xSF - NCSF Player |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-03-30 |
|
| 4 |
+ * Last modification on 2013-04-01 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Partially based on the vio*sf framework |
| 7 | 7 |
* |
| ... | ... |
@@ -194,6 +194,11 @@ void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, |
| 194 | 194 |
} |
| 195 | 195 |
} |
| 196 | 196 |
|
| 197 |
+void XSFPlayer_NCSF::Terminate() |
|
| 198 |
+{
|
|
| 199 |
+ this->player.Stop(true); |
|
| 200 |
+} |
|
| 201 |
+ |
|
| 197 | 202 |
void XSFPlayer_NCSF::SetInterpolation(unsigned interpolation) |
| 198 | 203 |
{
|
| 199 | 204 |
this->player.interpolation = static_cast<Interpolation>(interpolation); |
| ... | ... |
@@ -61,9 +61,9 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 61 | 61 |
if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
| 62 | 62 |
{
|
| 63 | 63 |
#ifdef _WIN32 |
| 64 |
- auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 8, 12));
|
|
| 64 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 8, 12));
|
|
| 65 | 65 |
#else |
| 66 |
- auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 8, 12));
|
|
| 66 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 8, 12));
|
|
| 67 | 67 |
#endif |
| 68 | 68 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 69 | 69 |
return false; |
| ... | ... |
@@ -82,9 +82,9 @@ bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
| 82 | 82 |
{
|
| 83 | 83 |
found = true; |
| 84 | 84 |
#ifdef _WIN32 |
| 85 |
- auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 8, 12)); |
|
| 85 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 8, 12)); |
|
| 86 | 86 |
#else |
| 87 |
- auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 8, 12)); |
|
| 87 |
+ auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 8, 12)); |
|
| 88 | 88 |
#endif |
| 89 | 89 |
if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
| 90 | 90 |
return false; |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,205 @@ |
| 1 |
+/* |
|
| 2 |
+ * xSF - NCSF Player |
|
| 3 |
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
|
| 4 |
+ * Last modification on 2013-03-25 |
|
| 5 |
+ * |
|
| 6 |
+ * Partially based on the vio*sf framework |
|
| 7 |
+ * |
|
| 8 |
+ * Utilizes a modified FeOS Sound System for playback |
|
| 9 |
+ * https://github.com/fincs/FSS |
|
| 10 |
+ */ |
|
| 11 |
+ |
|
| 12 |
+#include <memory> |
|
| 13 |
+#include <zlib.h> |
|
| 14 |
+#include "convert.h" |
|
| 15 |
+#include "XSFPlayer_NCSF.h" |
|
| 16 |
+#include "XSFCommon.h" |
|
| 17 |
+#include "SSEQPlayer/SDAT.h" |
|
| 18 |
+#include "SSEQPlayer/Player.h" |
|
| 19 |
+ |
|
| 20 |
+const char *XSFPlayer::WinampDescription = "NCSF Decoder"; |
|
| 21 |
+const char *XSFPlayer::WinampExts = "ncsf;minincsf\0DS Nitro Composer Sound Format files (*.ncsf;*.minincsf)\0"; |
|
| 22 |
+ |
|
| 23 |
+XSFPlayer *XSFPlayer::Create(const std::string &fn) |
|
| 24 |
+{
|
|
| 25 |
+ return new XSFPlayer_NCSF(fn); |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+XSFPlayer *XSFPlayer::Create(const std::wstring &fn) |
|
| 29 |
+{
|
|
| 30 |
+ return new XSFPlayer_NCSF(fn); |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+void XSFPlayer_NCSF::MapNCSFSection(const std::vector<uint8_t> §ion) |
|
| 34 |
+{
|
|
| 35 |
+ uint32_t size = Get32BitsLE(§ion[8]), finalSize = size; |
|
| 36 |
+ if (this->sdatData.empty()) |
|
| 37 |
+ this->sdatData.resize(finalSize, 0); |
|
| 38 |
+ else if (this->sdatData.size() < size) |
|
| 39 |
+ this->sdatData.resize(finalSize); |
|
| 40 |
+ memcpy(&this->sdatData[0], §ion[0], size); |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+bool XSFPlayer_NCSF::MapNCSF(XSFFile *xSFToLoad) |
|
| 44 |
+{
|
|
| 45 |
+ if (!xSFToLoad->IsValidType(0x25)) |
|
| 46 |
+ return false; |
|
| 47 |
+ |
|
| 48 |
+ auto &reservedSection = xSFToLoad->GetReservedSection(), &programSection = xSFToLoad->GetProgramSection(); |
|
| 49 |
+ |
|
| 50 |
+ if (!reservedSection.empty()) |
|
| 51 |
+ this->sseq = Get32BitsLE(&reservedSection[0]); |
|
| 52 |
+ |
|
| 53 |
+ if (!programSection.empty()) |
|
| 54 |
+ this->MapNCSFSection(programSection); |
|
| 55 |
+ |
|
| 56 |
+ return true; |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+bool XSFPlayer_NCSF::RecursiveLoadNCSF(XSFFile *xSFToLoad, int level) |
|
| 60 |
+{
|
|
| 61 |
+ if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
|
|
| 62 |
+ {
|
|
| 63 |
+#ifdef _WIN32 |
|
| 64 |
+ auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 8, 12));
|
|
| 65 |
+#else |
|
| 66 |
+ auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 8, 12));
|
|
| 67 |
+#endif |
|
| 68 |
+ if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
|
| 69 |
+ return false; |
|
| 70 |
+ } |
|
| 71 |
+ |
|
| 72 |
+ if (!this->MapNCSF(xSFToLoad)) |
|
| 73 |
+ return false; |
|
| 74 |
+ |
|
| 75 |
+ unsigned n = 2; |
|
| 76 |
+ bool found; |
|
| 77 |
+ do |
|
| 78 |
+ {
|
|
| 79 |
+ found = false; |
|
| 80 |
+ std::string libTag = "_lib" + stringify(n++); |
|
| 81 |
+ if (xSFToLoad->GetTagExists(libTag)) |
|
| 82 |
+ {
|
|
| 83 |
+ found = true; |
|
| 84 |
+#ifdef _WIN32 |
|
| 85 |
+ auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 8, 12)); |
|
| 86 |
+#else |
|
| 87 |
+ auto libxSF = std::auto_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 8, 12)); |
|
| 88 |
+#endif |
|
| 89 |
+ if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1)) |
|
| 90 |
+ return false; |
|
| 91 |
+ } |
|
| 92 |
+ } while (found); |
|
| 93 |
+ |
|
| 94 |
+ return true; |
|
| 95 |
+} |
|
| 96 |
+ |
|
| 97 |
+bool XSFPlayer_NCSF::LoadNCSF() |
|
| 98 |
+{
|
|
| 99 |
+ return this->RecursiveLoadNCSF(this->xSF, 1); |
|
| 100 |
+} |
|
| 101 |
+ |
|
| 102 |
+XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer() |
|
| 103 |
+{
|
|
| 104 |
+ this->xSF = new XSFFile(filename, 8, 12); |
|
| 105 |
+} |
|
| 106 |
+ |
|
| 107 |
+XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer() |
|
| 108 |
+{
|
|
| 109 |
+ this->xSF = new XSFFile(filename, 8, 12); |
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+bool XSFPlayer_NCSF::Load() |
|
| 113 |
+{
|
|
| 114 |
+ if (!this->LoadNCSF()) |
|
| 115 |
+ return false; |
|
| 116 |
+ |
|
| 117 |
+ PseudoFile file; |
|
| 118 |
+ file.data = &this->sdatData; |
|
| 119 |
+ this->sdat.reset(new SDAT(file, this->sseq)); |
|
| 120 |
+ auto *sseqToPlay = this->sdat->sseq.get(); |
|
| 121 |
+ this->player.sampleRate = this->sampleRate; |
|
| 122 |
+ this->player.Setup(sseqToPlay); |
|
| 123 |
+ //this->player.masterVol = sseq->info.vol; |
|
| 124 |
+ this->player.Timer(); |
|
| 125 |
+ this->secondsPerSample = 1.0 / this->sampleRate; |
|
| 126 |
+ this->secondsIntoPlayback = 0; |
|
| 127 |
+ this->secondsUntilNextClock = SecondsPerClockCycle; |
|
| 128 |
+ |
|
| 129 |
+ return XSFPlayer::Load(); |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+template<typename T1, typename T2> static inline void clamp(T1 &valueToClamp, const T2 &minValue, const T2 &maxValue) |
|
| 133 |
+{
|
|
| 134 |
+ if (valueToClamp < minValue) |
|
| 135 |
+ valueToClamp = minValue; |
|
| 136 |
+ else if (valueToClamp > maxValue) |
|
| 137 |
+ valueToClamp = maxValue; |
|
| 138 |
+} |
|
| 139 |
+ |
|
| 140 |
+static inline int32_t muldiv7(int32_t val, uint8_t mul) |
|
| 141 |
+{
|
|
| 142 |
+ return mul == 127 ? val : ((val * mul) >> 7); |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+void XSFPlayer_NCSF::GenerateSamples(std::vector<uint8_t> &buf, unsigned offset, unsigned samples) |
|
| 146 |
+{
|
|
| 147 |
+ unsigned long mute = this->mutes.to_ulong(); |
|
| 148 |
+ |
|
| 149 |
+ for (unsigned smpl = 0; smpl < samples; ++smpl) |
|
| 150 |
+ {
|
|
| 151 |
+ this->secondsIntoPlayback += this->secondsPerSample; |
|
| 152 |
+ |
|
| 153 |
+ int32_t leftChannel = 0, rightChannel = 0; |
|
| 154 |
+ |
|
| 155 |
+ // I need to advance the sound channels here |
|
| 156 |
+ for (int i = 0; i < 16; ++i) |
|
| 157 |
+ {
|
|
| 158 |
+ Channel &chn = this->player.channels[i]; |
|
| 159 |
+ |
|
| 160 |
+ if (chn.state > CS_NONE) |
|
| 161 |
+ {
|
|
| 162 |
+ int32_t sample = chn.GenerateSample(); |
|
| 163 |
+ chn.IncrementSample(); |
|
| 164 |
+ |
|
| 165 |
+ if (mute & BIT(i)) |
|
| 166 |
+ continue; |
|
| 167 |
+ |
|
| 168 |
+ uint8_t datashift = chn.reg.volumeDiv; |
|
| 169 |
+ if (datashift == 3) |
|
| 170 |
+ datashift = 4; |
|
| 171 |
+ sample = muldiv7(sample, chn.reg.volumeMul) >> datashift; |
|
| 172 |
+ |
|
| 173 |
+ leftChannel += muldiv7(sample, 127 - chn.reg.panning); |
|
| 174 |
+ rightChannel += muldiv7(sample, chn.reg.panning); |
|
| 175 |
+ } |
|
| 176 |
+ } |
|
| 177 |
+ |
|
| 178 |
+ leftChannel = muldiv7(leftChannel, 127 - this->player.masterVol); |
|
| 179 |
+ rightChannel = muldiv7(rightChannel, 127 - this->player.masterVol); |
|
| 180 |
+ |
|
| 181 |
+ clamp(leftChannel, -0x8000, 0x7FFF); |
|
| 182 |
+ clamp(rightChannel, -0x8000, 0x7FFF); |
|
| 183 |
+ |
|
| 184 |
+ buf[offset++] = leftChannel & 0xFF; |
|
| 185 |
+ buf[offset++] = (leftChannel >> 8) & 0xFF; |
|
| 186 |
+ buf[offset++] = rightChannel & 0xFF; |
|
| 187 |
+ buf[offset++] = (rightChannel >> 8) & 0xFF; |
|
| 188 |
+ |
|
| 189 |
+ if (this->secondsIntoPlayback > this->secondsUntilNextClock) |
|
| 190 |
+ {
|
|
| 191 |
+ this->player.Timer(); |
|
| 192 |
+ this->secondsUntilNextClock += SecondsPerClockCycle; |
|
| 193 |
+ } |
|
| 194 |
+ } |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+void XSFPlayer_NCSF::SetInterpolation(unsigned interpolation) |
|
| 198 |
+{
|
|
| 199 |
+ this->player.interpolation = static_cast<Interpolation>(interpolation); |
|
| 200 |
+} |
|
| 201 |
+ |
|
| 202 |
+void XSFPlayer_NCSF::SetMutes(const std::bitset<16> &newMutes) |
|
| 203 |
+{
|
|
| 204 |
+ this->mutes = newMutes; |
|
| 205 |
+} |