* 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().
| ... | ... |
@@ -6,7 +6,11 @@ |
| 6 | 6 |
* http://www.feshrine.net/hacking/doc/nds-sdat.html |
| 7 | 7 |
*/ |
| 8 | 8 |
|
| 9 |
+#include <vector> |
|
| 10 |
+#include <cstddef> |
|
| 11 |
+#include <cstdint> |
|
| 9 | 12 |
#include "SWAV.h" |
| 13 |
+#include "common.h" |
|
| 10 | 14 |
|
| 11 | 15 |
static int ima_index_table[] = |
| 12 | 16 |
{
|
| ... | ... |
@@ -31,9 +35,9 @@ SWAV::SWAV() : waveType(0), loop(0), sampleRate(0), time(0), loopOffset(0), nonL |
| 31 | 35 |
{
|
| 32 | 36 |
} |
| 33 | 37 |
|
| 34 |
-static inline void DecodeADPCMNibble(int32_t nibble, int32_t &stepIndex, int32_t &predictedValue) |
|
| 38 |
+static inline void DecodeADPCMNibble(std::int32_t nibble, std::int32_t &stepIndex, std::int32_t &predictedValue) |
|
| 35 | 39 |
{
|
| 36 |
- int32_t step = ima_step_table[stepIndex]; |
|
| 40 |
+ std::int32_t step = ima_step_table[stepIndex]; |
|
| 37 | 41 |
|
| 38 | 42 |
stepIndex += ima_index_table[nibble]; |
| 39 | 43 |
|
| ... | ... |
@@ -42,7 +46,7 @@ static inline void DecodeADPCMNibble(int32_t nibble, int32_t &stepIndex, int32_t |
| 42 | 46 |
else if (stepIndex > 88) |
| 43 | 47 |
stepIndex = 88; |
| 44 | 48 |
|
| 45 |
- int32_t diff = step >> 3; |
|
| 49 |
+ std::int32_t diff = step >> 3; |
|
| 46 | 50 |
|
| 47 | 51 |
if (nibble & 4) |
| 48 | 52 |
diff += step; |
| ... | ... |
@@ -61,15 +65,15 @@ static inline void DecodeADPCMNibble(int32_t nibble, int32_t &stepIndex, int32_t |
| 61 | 65 |
predictedValue = 0x7FFF; |
| 62 | 66 |
} |
| 63 | 67 |
|
| 64 |
-void SWAV::DecodeADPCM(const uint8_t *origData, uint32_t len) |
|
| 68 |
+void SWAV::DecodeADPCM(const std::uint8_t *origData, std::uint32_t len) |
|
| 65 | 69 |
{
|
| 66 |
- int32_t predictedValue = origData[0] | (origData[1] << 8); |
|
| 67 |
- int32_t stepIndex = origData[2] | (origData[3] << 8); |
|
| 70 |
+ std::int32_t predictedValue = origData[0] | (origData[1] << 8); |
|
| 71 |
+ std::int32_t stepIndex = origData[2] | (origData[3] << 8); |
|
| 68 | 72 |
auto finalData = &this->data[0]; |
| 69 | 73 |
|
| 70 |
- for (uint32_t i = 0; i < len; ++i) |
|
| 74 |
+ for (std::uint32_t i = 0; i < len; ++i) |
|
| 71 | 75 |
{
|
| 72 |
- int32_t nibble = origData[i + 4] & 0x0F; |
|
| 76 |
+ std::int32_t nibble = origData[i + 4] & 0x0F; |
|
| 73 | 77 |
DecodeADPCMNibble(nibble, stepIndex, predictedValue); |
| 74 | 78 |
finalData[2 * i] = predictedValue; |
| 75 | 79 |
|
| ... | ... |
@@ -81,14 +85,14 @@ void SWAV::DecodeADPCM(const uint8_t *origData, uint32_t len) |
| 81 | 85 |
|
| 82 | 86 |
void SWAV::Read(PseudoFile &file) |
| 83 | 87 |
{
|
| 84 |
- this->waveType = file.ReadLE<uint8_t>(); |
|
| 85 |
- this->loop = file.ReadLE<uint8_t>(); |
|
| 86 |
- this->sampleRate = file.ReadLE<uint16_t>(); |
|
| 87 |
- this->time = file.ReadLE<uint16_t>(); |
|
| 88 |
- this->loopOffset = file.ReadLE<uint16_t>(); |
|
| 89 |
- this->nonLoopLength = file.ReadLE<uint32_t>(); |
|
| 90 |
- uint32_t size = (this->loopOffset + this->nonLoopLength) * 4; |
|
| 91 |
- auto origData = std::vector<uint8_t>(size); |
|
| 88 |
+ this->waveType = file.ReadLE<std::uint8_t>(); |
|
| 89 |
+ this->loop = file.ReadLE<std::uint8_t>(); |
|
| 90 |
+ this->sampleRate = file.ReadLE<std::uint16_t>(); |
|
| 91 |
+ this->time = file.ReadLE<std::uint16_t>(); |
|
| 92 |
+ this->loopOffset = file.ReadLE<std::uint16_t>(); |
|
| 93 |
+ this->nonLoopLength = file.ReadLE<std::uint32_t>(); |
|
| 94 |
+ std::uint32_t size = (this->loopOffset + this->nonLoopLength) * 4; |
|
| 95 |
+ auto origData = std::vector<std::uint8_t>(size); |
|
| 92 | 96 |
file.ReadLE(origData); |
| 93 | 97 |
|
| 94 | 98 |
// Convert data accordingly |
| ... | ... |
@@ -96,7 +100,7 @@ void SWAV::Read(PseudoFile &file) |
| 96 | 100 |
{
|
| 97 | 101 |
// PCM 8-bit -> PCM signed 16-bit |
| 98 | 102 |
this->data.resize(size, 0); |
| 99 |
- for (size_t i = 0; i < size; ++i) |
|
| 103 |
+ for (std::size_t i = 0; i < size; ++i) |
|
| 100 | 104 |
this->data[i] = origData[i] << 8; |
| 101 | 105 |
this->loopOffset *= 4; |
| 102 | 106 |
this->nonLoopLength *= 4; |
| ... | ... |
@@ -105,8 +109,8 @@ void SWAV::Read(PseudoFile &file) |
| 105 | 109 |
{
|
| 106 | 110 |
// PCM signed 16-bit, no conversion |
| 107 | 111 |
this->data.resize(size / 2, 0); |
| 108 |
- for (size_t i = 0; i < size / 2; ++i) |
|
| 109 |
- this->data[i] = ReadLE<int16_t>(&origData[2 * i]); |
|
| 112 |
+ for (std::size_t i = 0; i < size / 2; ++i) |
|
| 113 |
+ this->data[i] = ReadLE<std::int16_t>(&origData[2 * i]); |
|
| 110 | 114 |
this->loopOffset *= 2; |
| 111 | 115 |
this->nonLoopLength *= 2; |
| 112 | 116 |
} |
(I never remember to update these and besides, GitHub history can show when they were last modified.)
| ... | ... |
@@ -1,7 +1,6 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* SSEQ Player - SDAT SWAV (Waveform/Sample) structure |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-12 |
|
| 5 | 4 |
* |
| 6 | 5 |
* Nintendo DS Nitro Composer (SDAT) Specification document found at |
| 7 | 6 |
* http://www.feshrine.net/hacking/doc/nds-sdat.html |
Also a minor optimization when reading the SWAVs.
| ... | ... |
@@ -96,8 +96,8 @@ void SWAV::Read(PseudoFile &file) |
| 96 | 96 |
if (!this->waveType) |
| 97 | 97 |
{
|
| 98 | 98 |
// PCM 8-bit -> PCM signed 16-bit |
| 99 |
- this->data.resize(origData.size(), 0); |
|
| 100 |
- for (size_t i = 0, len = origData.size(); i < len; ++i) |
|
| 99 |
+ this->data.resize(size, 0); |
|
| 100 |
+ for (size_t i = 0; i < size; ++i) |
|
| 101 | 101 |
this->data[i] = origData[i] << 8; |
| 102 | 102 |
this->loopOffset *= 4; |
| 103 | 103 |
this->nonLoopLength *= 4; |
| ... | ... |
@@ -105,8 +105,8 @@ void SWAV::Read(PseudoFile &file) |
| 105 | 105 |
else if (this->waveType == 1) |
| 106 | 106 |
{
|
| 107 | 107 |
// PCM signed 16-bit, no conversion |
| 108 |
- this->data.resize(origData.size() / 2, 0); |
|
| 109 |
- for (size_t i = 0, len = origData.size() / 2; i < len; ++i) |
|
| 108 |
+ this->data.resize(size / 2, 0); |
|
| 109 |
+ for (size_t i = 0; i < size / 2; ++i) |
|
| 110 | 110 |
this->data[i] = ReadLE<int16_t>(&origData[2 * i]); |
| 111 | 111 |
this->loopOffset *= 2; |
| 112 | 112 |
this->nonLoopLength *= 2; |
| ... | ... |
@@ -114,9 +114,10 @@ void SWAV::Read(PseudoFile &file) |
| 114 | 114 |
else if (this->waveType == 2) |
| 115 | 115 |
{
|
| 116 | 116 |
// IMA ADPCM -> PCM signed 16-bit |
| 117 |
- this->data.resize((origData.size() - 4) * 2, 0); |
|
| 118 |
- this->DecodeADPCM(&origData[0], origData.size() - 4); |
|
| 119 |
- --this->loopOffset; |
|
| 117 |
+ this->data.resize((size - 4) * 2, 0); |
|
| 118 |
+ this->DecodeADPCM(&origData[0], size - 4); |
|
| 119 |
+ if (this->loopOffset) |
|
| 120 |
+ --this->loopOffset; |
|
| 120 | 121 |
this->loopOffset *= 8; |
| 121 | 122 |
this->nonLoopLength *= 8; |
| 122 | 123 |
} |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* SSEQ Player - SDAT SWAV (Waveform/Sample) structure |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-04-10 |
|
| 4 |
+ * Last modification on 2013-04-12 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Nintendo DS Nitro Composer (SDAT) Specification document found at |
| 7 | 7 |
* http://www.feshrine.net/hacking/doc/nds-sdat.html |
| ... | ... |
@@ -62,20 +62,21 @@ static inline void DecodeADPCMNibble(int32_t nibble, int32_t &stepIndex, int32_t |
| 62 | 62 |
predictedValue = 0x7FFF; |
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 |
-void SWAV::DecodeADPCM(const std::vector<uint8_t> &origData) |
|
| 65 |
+void SWAV::DecodeADPCM(const uint8_t *origData, uint32_t len) |
|
| 66 | 66 |
{
|
| 67 | 67 |
int32_t predictedValue = origData[0] | (origData[1] << 8); |
| 68 | 68 |
int32_t stepIndex = origData[2] | (origData[3] << 8); |
| 69 |
+ auto finalData = &this->data[0]; |
|
| 69 | 70 |
|
| 70 |
- for (int i = 0, len = origData.size() - 4; i < len; ++i) |
|
| 71 |
+ for (uint32_t i = 0; i < len; ++i) |
|
| 71 | 72 |
{
|
| 72 | 73 |
int32_t nibble = origData[i + 4] & 0x0F; |
| 73 | 74 |
DecodeADPCMNibble(nibble, stepIndex, predictedValue); |
| 74 |
- this->data[2 * i] = predictedValue; |
|
| 75 |
+ finalData[2 * i] = predictedValue; |
|
| 75 | 76 |
|
| 76 | 77 |
nibble = (origData[i + 4] >> 4) & 0x0F; |
| 77 | 78 |
DecodeADPCMNibble(nibble, stepIndex, predictedValue); |
| 78 |
- this->data[2 * i + 1] = predictedValue; |
|
| 79 |
+ finalData[2 * i + 1] = predictedValue; |
|
| 79 | 80 |
} |
| 80 | 81 |
} |
| 81 | 82 |
|
| ... | ... |
@@ -114,7 +115,7 @@ void SWAV::Read(PseudoFile &file) |
| 114 | 115 |
{
|
| 115 | 116 |
// IMA ADPCM -> PCM signed 16-bit |
| 116 | 117 |
this->data.resize((origData.size() - 4) * 2, 0); |
| 117 |
- this->DecodeADPCM(origData); |
|
| 118 |
+ this->DecodeADPCM(&origData[0], origData.size() - 4); |
|
| 118 | 119 |
--this->loopOffset; |
| 119 | 120 |
this->loopOffset *= 8; |
| 120 | 121 |
this->nonLoopLength *= 8; |
| ... | ... |
@@ -1,7 +1,7 @@ |
| 1 | 1 |
/* |
| 2 | 2 |
* SSEQ Player - SDAT SWAV (Waveform/Sample) structure |
| 3 | 3 |
* By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
| 4 |
- * Last modification on 2013-03-25 |
|
| 4 |
+ * Last modification on 2013-04-10 |
|
| 5 | 5 |
* |
| 6 | 6 |
* Nintendo DS Nitro Composer (SDAT) Specification document found at |
| 7 | 7 |
* http://www.feshrine.net/hacking/doc/nds-sdat.html |
| ... | ... |
@@ -28,7 +28,7 @@ static int ima_step_table[] = |
| 28 | 28 |
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 |
| 29 | 29 |
}; |
| 30 | 30 |
|
| 31 |
-SWAV::SWAV() : waveType(0), loop(0), sampleRate(0), time(0), loopOffset(0), nonLoopLength(0), data() |
|
| 31 |
+SWAV::SWAV() : waveType(0), loop(0), sampleRate(0), time(0), loopOffset(0), nonLoopLength(0), data(), dataptr(nullptr) |
|
| 32 | 32 |
{
|
| 33 | 33 |
} |
| 34 | 34 |
|
| ... | ... |
@@ -119,4 +119,5 @@ void SWAV::Read(PseudoFile &file) |
| 119 | 119 |
this->loopOffset *= 8; |
| 120 | 120 |
this->nonLoopLength *= 8; |
| 121 | 121 |
} |
| 122 |
+ this->dataptr = &this->data[0]; |
|
| 122 | 123 |
} |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,122 @@ |
| 1 |
+/* |
|
| 2 |
+ * SSEQ Player - SDAT SWAV (Waveform/Sample) structure |
|
| 3 |
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com] |
|
| 4 |
+ * Last modification on 2013-03-25 |
|
| 5 |
+ * |
|
| 6 |
+ * Nintendo DS Nitro Composer (SDAT) Specification document found at |
|
| 7 |
+ * http://www.feshrine.net/hacking/doc/nds-sdat.html |
|
| 8 |
+ */ |
|
| 9 |
+ |
|
| 10 |
+#include "SWAV.h" |
|
| 11 |
+ |
|
| 12 |
+static int ima_index_table[] = |
|
| 13 |
+{
|
|
| 14 |
+ -1, -1, -1, -1, 2, 4, 6, 8, |
|
| 15 |
+ -1, -1, -1, -1, 2, 4, 6, 8 |
|
| 16 |
+}; |
|
| 17 |
+ |
|
| 18 |
+static int ima_step_table[] = |
|
| 19 |
+{
|
|
| 20 |
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, |
|
| 21 |
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, |
|
| 22 |
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, |
|
| 23 |
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, |
|
| 24 |
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, |
|
| 25 |
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, |
|
| 26 |
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, |
|
| 27 |
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, |
|
| 28 |
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 |
|
| 29 |
+}; |
|
| 30 |
+ |
|
| 31 |
+SWAV::SWAV() : waveType(0), loop(0), sampleRate(0), time(0), loopOffset(0), nonLoopLength(0), data() |
|
| 32 |
+{
|
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+static inline void DecodeADPCMNibble(int32_t nibble, int32_t &stepIndex, int32_t &predictedValue) |
|
| 36 |
+{
|
|
| 37 |
+ int32_t step = ima_step_table[stepIndex]; |
|
| 38 |
+ |
|
| 39 |
+ stepIndex += ima_index_table[nibble]; |
|
| 40 |
+ |
|
| 41 |
+ if (stepIndex < 0) |
|
| 42 |
+ stepIndex = 0; |
|
| 43 |
+ else if (stepIndex > 88) |
|
| 44 |
+ stepIndex = 88; |
|
| 45 |
+ |
|
| 46 |
+ int32_t diff = step >> 3; |
|
| 47 |
+ |
|
| 48 |
+ if (nibble & 4) |
|
| 49 |
+ diff += step; |
|
| 50 |
+ if (nibble & 2) |
|
| 51 |
+ diff += step >> 1; |
|
| 52 |
+ if (nibble & 1) |
|
| 53 |
+ diff += step >> 2; |
|
| 54 |
+ if (nibble & 8) |
|
| 55 |
+ predictedValue -= diff; |
|
| 56 |
+ else |
|
| 57 |
+ predictedValue += diff; |
|
| 58 |
+ |
|
| 59 |
+ if (predictedValue < -0x8000) |
|
| 60 |
+ predictedValue = -0x8000; |
|
| 61 |
+ else if (predictedValue > 0x7FFF) |
|
| 62 |
+ predictedValue = 0x7FFF; |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+void SWAV::DecodeADPCM(const std::vector<uint8_t> &origData) |
|
| 66 |
+{
|
|
| 67 |
+ int32_t predictedValue = origData[0] | (origData[1] << 8); |
|
| 68 |
+ int32_t stepIndex = origData[2] | (origData[3] << 8); |
|
| 69 |
+ |
|
| 70 |
+ for (int i = 0, len = origData.size() - 4; i < len; ++i) |
|
| 71 |
+ {
|
|
| 72 |
+ int32_t nibble = origData[i + 4] & 0x0F; |
|
| 73 |
+ DecodeADPCMNibble(nibble, stepIndex, predictedValue); |
|
| 74 |
+ this->data[2 * i] = predictedValue; |
|
| 75 |
+ |
|
| 76 |
+ nibble = (origData[i + 4] >> 4) & 0x0F; |
|
| 77 |
+ DecodeADPCMNibble(nibble, stepIndex, predictedValue); |
|
| 78 |
+ this->data[2 * i + 1] = predictedValue; |
|
| 79 |
+ } |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+void SWAV::Read(PseudoFile &file) |
|
| 83 |
+{
|
|
| 84 |
+ this->waveType = file.ReadLE<uint8_t>(); |
|
| 85 |
+ this->loop = file.ReadLE<uint8_t>(); |
|
| 86 |
+ this->sampleRate = file.ReadLE<uint16_t>(); |
|
| 87 |
+ this->time = file.ReadLE<uint16_t>(); |
|
| 88 |
+ this->loopOffset = file.ReadLE<uint16_t>(); |
|
| 89 |
+ this->nonLoopLength = file.ReadLE<uint32_t>(); |
|
| 90 |
+ uint32_t size = (this->loopOffset + this->nonLoopLength) * 4; |
|
| 91 |
+ auto origData = std::vector<uint8_t>(size); |
|
| 92 |
+ file.ReadLE(origData); |
|
| 93 |
+ |
|
| 94 |
+ // Convert data accordingly |
|
| 95 |
+ if (!this->waveType) |
|
| 96 |
+ {
|
|
| 97 |
+ // PCM 8-bit -> PCM signed 16-bit |
|
| 98 |
+ this->data.resize(origData.size(), 0); |
|
| 99 |
+ for (size_t i = 0, len = origData.size(); i < len; ++i) |
|
| 100 |
+ this->data[i] = origData[i] << 8; |
|
| 101 |
+ this->loopOffset *= 4; |
|
| 102 |
+ this->nonLoopLength *= 4; |
|
| 103 |
+ } |
|
| 104 |
+ else if (this->waveType == 1) |
|
| 105 |
+ {
|
|
| 106 |
+ // PCM signed 16-bit, no conversion |
|
| 107 |
+ this->data.resize(origData.size() / 2, 0); |
|
| 108 |
+ for (size_t i = 0, len = origData.size() / 2; i < len; ++i) |
|
| 109 |
+ this->data[i] = ReadLE<int16_t>(&origData[2 * i]); |
|
| 110 |
+ this->loopOffset *= 2; |
|
| 111 |
+ this->nonLoopLength *= 2; |
|
| 112 |
+ } |
|
| 113 |
+ else if (this->waveType == 2) |
|
| 114 |
+ {
|
|
| 115 |
+ // IMA ADPCM -> PCM signed 16-bit |
|
| 116 |
+ this->data.resize((origData.size() - 4) * 2, 0); |
|
| 117 |
+ this->DecodeADPCM(origData); |
|
| 118 |
+ --this->loopOffset; |
|
| 119 |
+ this->loopOffset *= 8; |
|
| 120 |
+ this->nonLoopLength *= 8; |
|
| 121 |
+ } |
|
| 122 |
+} |