summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2024-11-21 21:40:38 -0600
committerKiritoDv <kiritodev01@gmail.com>2024-11-21 21:40:38 -0600
commita9662a158ff7764ecbefd1b88280d3854f3c4fea (patch)
tree0390161cd5d7cf7e34a28fa3a150533253465fb4 /src
parent1537229c694c0a91ec37fb7389bdcf3e3968cd71 (diff)
Added sample extraction to aiff
Diffstat (limited to 'src')
-rw-r--r--src/Companion.h2
-rw-r--r--src/factories/naudio/v0/AIFCDecode.cpp22
-rw-r--r--src/factories/naudio/v1/AudioContext.cpp1
-rw-r--r--src/factories/naudio/v1/AudioContext.h2
-rw-r--r--src/factories/naudio/v1/AudioConverter.cpp160
-rw-r--r--src/factories/naudio/v1/AudioConverter.h38
-rw-r--r--src/factories/naudio/v1/AudioTableFactory.h2
-rw-r--r--src/factories/naudio/v1/BookFactory.cpp4
-rw-r--r--src/factories/naudio/v1/BookFactory.h2
-rw-r--r--src/factories/naudio/v1/DrumFactory.h2
-rw-r--r--src/factories/naudio/v1/EnvelopeFactory.h2
-rw-r--r--src/factories/naudio/v1/InstrumentFactory.h2
-rw-r--r--src/factories/naudio/v1/LoopFactory.h2
-rw-r--r--src/factories/naudio/v1/SampleFactory.cpp21
-rw-r--r--src/factories/naudio/v1/SampleFactory.h7
-rw-r--r--src/factories/naudio/v1/SoundFontFactory.h2
16 files changed, 254 insertions, 17 deletions
diff --git a/src/Companion.h b/src/Companion.h
index f169786..eb51783 100644
--- a/src/Companion.h
+++ b/src/Companion.h
@@ -127,7 +127,7 @@ public:
bool IsDebug() const { return this->gConfig.debug; }
N64::Cartridge* GetCartridge() const { return this->gCartridge.get(); }
- std::vector<uint8_t> GetRomData() { return this->gRomData; }
+ std::vector<uint8_t>& GetRomData() { return this->gRomData; }
std::string GetOutputPath() { return this->gConfig.outputPath; }
GBIVersion GetGBIVersion() const { return this->gConfig.gbi.version; }
diff --git a/src/factories/naudio/v0/AIFCDecode.cpp b/src/factories/naudio/v0/AIFCDecode.cpp
index e627ad0..b1c9329 100644
--- a/src/factories/naudio/v0/AIFCDecode.cpp
+++ b/src/factories/naudio/v0/AIFCDecode.cpp
@@ -176,11 +176,11 @@ s32 readaifccodebook(LUS::BinaryReader& fhandle, s32 ****table, s16 *order, s16
BSWAP16(*order);
checked_fread(npredictors, sizeof(s16), 1, fhandle);
BSWAP16(*npredictors);
- *table = static_cast<s32 ***>(malloc(*npredictors * sizeof(s32 **)));
+ *table = new s32**[*npredictors];
for (s32 i = 0; i < *npredictors; i++) {
- (*table)[i] = static_cast<s32 **>(malloc(8 * sizeof(s32 *)));
+ (*table)[i] = new s32*[8];
for (s32 j = 0; j < 8; j++) {
- (*table)[i][j] = static_cast<s32 *>(malloc((*order + 8) * sizeof(s32)));
+ (*table)[i][j] = new s32[*order + 8];
}
}
@@ -401,7 +401,7 @@ void write_aiff(std::vector<char> data, LUS::BinaryWriter& writer) {
ALADPCMloop *aloops = nullptr;
s16 npredictors = -1;
s32 ***coefTable = nullptr;
- s32 state[16];
+ s32 state[16] = {0};
s32 soundPointer = -1;
s32 currPos = 0;
s32 nSamples = 0;
@@ -525,12 +525,12 @@ void write_aiff(std::vector<char> data, LUS::BinaryWriter& writer) {
reader.Seek(soundPointer, LUS::SeekOffsetType::Start);
while (currPos < nSamples) {
- u8 input[9];
- u8 encoded[9];
- s32 lastState[16];
- s32 decoded[16];
- s16 guess[16];
- s16 origGuess[16];
+ u8 input[9] = {0};
+ u8 encoded[9] = {0};
+ s32 lastState[16] = {0};
+ s32 decoded[16] = {0};
+ s16 guess[16] = {0};
+ s16 origGuess[16] = {0};
memcpy(lastState, state, sizeof(lastState));
checked_fread(input, 9, 1, reader);
@@ -550,7 +550,7 @@ void write_aiff(std::vector<char> data, LUS::BinaryWriter& writer) {
my_encodeframe(encoded, guess, state, coefTable, order, npredictors);
// If it doesn't match, randomly round numbers until it does.
- if (memcmp(input, encoded, 9) != 0) {
+ if (0 && memcmp(input, encoded, 9) != 0) {
s32 scale = 1 << (input[0] >> 4);
do {
permute(guess, decoded, scale);
diff --git a/src/factories/naudio/v1/AudioContext.cpp b/src/factories/naudio/v1/AudioContext.cpp
index 76741c9..1c27598 100644
--- a/src/factories/naudio/v1/AudioContext.cpp
+++ b/src/factories/naudio/v1/AudioContext.cpp
@@ -60,6 +60,7 @@ TunedSample AudioContext::LoadTunedSample(LUS::BinaryReader& reader, uint32_t pa
node["type"] = "NAUDIO:V1:SAMPLE";
node["parent"] = parent;
node["offset"] = parent + sampleAddr;
+ node["tuning"] = tuning;
node["sampleBankId"] = sampleBankId;
Companion::Instance->AddAsset(node);
diff --git a/src/factories/naudio/v1/AudioContext.h b/src/factories/naudio/v1/AudioContext.h
index f1ab111..84e5337 100644
--- a/src/factories/naudio/v1/AudioContext.h
+++ b/src/factories/naudio/v1/AudioContext.h
@@ -33,4 +33,6 @@ public:
REGISTER(Code, AudioDummyExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/AudioConverter.cpp b/src/factories/naudio/v1/AudioConverter.cpp
new file mode 100644
index 0000000..2c541dd
--- /dev/null
+++ b/src/factories/naudio/v1/AudioConverter.cpp
@@ -0,0 +1,160 @@
+#include "AudioConverter.h"
+
+#include <factories/naudio/v1/BookFactory.h>
+#include <factories/naudio/v1/LoopFactory.h>
+#include <factories/naudio/v1/AudioContext.h>
+#include <factories/naudio/v1/SampleFactory.h>
+#include <factories/BaseFactory.h>
+#include <Companion.h>
+#include <cassert>
+
+void AIFCWriter::End(std::string chunk, LUS::BinaryWriter& writer) {
+ auto buffer = writer.ToVector();
+ this->Chunks.push_back({
+ chunk, buffer
+ });
+
+ this->totalSize += ALIGN(buffer.size(), 2) + 8;
+}
+
+void AIFCWriter::Close(LUS::BinaryWriter& out){
+ out.SetEndianness(Torch::Endianness::Big);
+
+ out.Write(AIFCMagicValues::FORM);
+ out.Write((uint32_t) (this->totalSize + 4));
+ out.Write(AIFCMagicValues::AIFC);
+
+ for(auto& chunk : this->Chunks){
+ out.Write((char*) chunk.id.data(), chunk.id.size());
+ out.Write((uint32_t) chunk.data.size());
+ out.Write((char*) chunk.data.data(), chunk.data.size());
+
+ if(chunk.data.size() % 2 == 1) {
+ out.Write((uint8_t) 0);
+ }
+ }
+}
+
+// Function to serialize double to 80-bit extended-precision
+void SerializeF80(double num, LUS::BinaryWriter &writer) {
+ // Convert the input double to a uint64_t representation
+ std::uint64_t f64;
+ std::memcpy(&f64, &num, sizeof(double));
+
+ // Extract the sign bit
+ std::uint64_t f64_sign_bit = f64 & (1ULL << 63);
+
+ // Handle the special case: zero
+ if (num == 0.0) {
+ if (f64_sign_bit) {
+ writer.Write(static_cast<uint16_t>(0x8000)); // Sign bit set
+ } else {
+ writer.Write(static_cast<uint16_t>(0x0000)); // No sign bit
+ }
+ writer.Write(static_cast<uint64_t>(0x0000000000000000)); // Zero mantissa
+ return;
+ }
+
+ // Extract the exponent and mantissa
+ std::uint64_t exponent = (f64 >> 52) & 0x7FF; // Exponent bits
+ assert(exponent != 0); // Ensure not denormal
+ assert(exponent != 0x7FF); // Ensure not infinity/NaN
+
+ exponent -= 1023; // Adjust bias for 64-bit
+
+ std::uint64_t f64_mantissa_bits = f64 & ((1ULL << 52) - 1); // Mantissa bits
+
+ // Construct the 80-bit extended-precision fields
+ std::uint64_t f80_sign_bit = f64_sign_bit << (80 - 64); // Shift sign
+ std::uint64_t f80_exponent = (exponent + 0x3FFF) & 0x7FFF; // Adjust bias
+ std::uint64_t f80_mantissa_bits = (1ULL << 63) | (f64_mantissa_bits << (63 - 52)); // Add implicit bit
+
+ // Combine components into the 80-bit representation
+ uint16_t high = static_cast<uint16_t>(f80_sign_bit >> 48) | static_cast<uint16_t>(f80_exponent);
+ uint64_t low = f80_mantissa_bits;
+
+ // Write the result in big-endian order
+ writer.Write(high);
+ writer.Write(low);
+}
+
+void AudioConverter::SampleToAIFC(NSampleData* sample, LUS::BinaryWriter &out) {
+ auto loop = std::static_pointer_cast<ADPCMLoopData>(Companion::Instance->GetParseDataByAddr(sample->loop)->data.value());
+ auto book = std::static_pointer_cast<ADPCMBookData>(Companion::Instance->GetParseDataByAddr(sample->book)->data.value());
+ auto entry = AudioContext::tableData[AudioTableType::SAMPLE_TABLE]->entries[sample->sampleBankId];
+ auto buffer = AudioContext::data[AudioTableType::SAMPLE_TABLE];
+ auto sampleData = buffer.data() + entry.addr + sample->sampleAddr;
+ auto aifc = AIFCWriter();
+ std::vector<uint8_t> data(sampleData, sampleData + sample->size);
+
+ uint32_t num_frames = data.size() * 16 / 9;
+ uint32_t sample_rate = 0;
+
+ if (sample->tuning <= 0.5f) {
+ sample_rate = 16000;
+ } else if (sample->tuning <= 1.0f) {
+ sample_rate = 32000;
+ } else if (sample->tuning <= 1.5f) {
+ sample_rate = 48000;
+ } else if (sample->tuning <= 2.5f) {
+ sample_rate = 80000;
+ } else {
+ sample_rate = 16000 * sample->tuning;
+ }
+
+ int16_t num_channels = 1;
+ int16_t sample_size = 16;
+
+ // COMM Chunk
+ auto comm = aifc.Start();
+ comm.Write(num_channels);
+ comm.Write(num_frames);
+ comm.Write(sample_size);
+ SerializeF80(sample_rate, comm);
+ comm.Write(AIFCMagicValues::VAPC);
+ comm.Write((char*) "\x0bVADPCM ~4-1", 12);
+ aifc.End("COMM", comm);
+
+ // INST Chunk
+ auto inst = aifc.Start();
+ for(size_t i = 0; i < 5; i++){
+ inst.Write((int32_t) 0);
+ }
+ aifc.End("INST", inst);
+
+ // VADPCMCODES Chunk
+ auto vcodes = aifc.Start();
+ vcodes.Write((char*) "stoc\x0bVADPCMCODES", 16);
+ vcodes.Write((int16_t) 1);
+ vcodes.Write((int16_t) book->order);
+ vcodes.Write((int16_t) book->numPredictors);
+
+ for(auto page : book->book){
+ vcodes.Write(page);
+ }
+ aifc.End("APPL", vcodes);
+
+ // SSND Chunk
+ auto ssnd = aifc.Start();
+ ssnd.Write((uint64_t) 0);
+ ssnd.Write((char*) data.data(), data.size());
+ aifc.End("SSND", ssnd);
+
+ // VADPCMLOOPS
+ if(loop->count != 0){
+ auto vloops = aifc.Start();
+ vloops.Write((char*) "stoc\x0bVADPCMLOOPS", 16);
+ vloops.Write((uint16_t) 1);
+ vloops.Write((uint16_t) 1);
+ vloops.Write(loop->start);
+ vloops.Write(loop->end);
+ vloops.Write(loop->count);
+
+ for(size_t i = 0; i < 16; i++){
+ vloops.Write(loop->predictorState[i]);
+ }
+ aifc.End("APPL", vloops);
+ }
+
+ aifc.Close(out);
+} \ No newline at end of file
diff --git a/src/factories/naudio/v1/AudioConverter.h b/src/factories/naudio/v1/AudioConverter.h
new file mode 100644
index 0000000..ef87a0d
--- /dev/null
+++ b/src/factories/naudio/v1/AudioConverter.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include <factories/naudio/v1/SampleFactory.h>
+
+enum AIFCMagicValues {
+ FORM = (uint32_t) 0x464f524d,
+ AIFC = (uint32_t) 0x41494643,
+ VAPC = (uint32_t) 0x56415043,
+ AAPL = (uint32_t) 0x4150504c
+};
+
+#define NONE 0xFFFF
+#define ALIGN(val, al) (size_t) ((val + (al - 1)) & -al)
+
+class AudioConverter {
+public:
+ static void SampleToAIFC(NSampleData* tSample, LUS::BinaryWriter &out);
+};
+
+struct AIFCChunk {
+ std::string id;
+ std::vector<char> data;
+};
+
+class AIFCWriter {
+public:
+ std::vector<AIFCChunk> Chunks;
+ size_t totalSize = 0;
+
+ LUS::BinaryWriter Start(){
+ auto writer = LUS::BinaryWriter();
+ writer.SetEndianness(Torch::Endianness::Big);
+ return writer;
+ }
+ void End(std::string chunk, LUS::BinaryWriter& writer);
+ void Close(LUS::BinaryWriter& out);
+}; \ No newline at end of file
diff --git a/src/factories/naudio/v1/AudioTableFactory.h b/src/factories/naudio/v1/AudioTableFactory.h
index 1479b87..5d3042d 100644
--- a/src/factories/naudio/v1/AudioTableFactory.h
+++ b/src/factories/naudio/v1/AudioTableFactory.h
@@ -51,4 +51,6 @@ public:
REGISTER(Code, AudioTableCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/BookFactory.cpp b/src/factories/naudio/v1/BookFactory.cpp
index 96d1e53..a501bf5 100644
--- a/src/factories/naudio/v1/BookFactory.cpp
+++ b/src/factories/naudio/v1/BookFactory.cpp
@@ -46,10 +46,6 @@ std::optional<std::shared_ptr<IParsedData>> ADPCMBookFactory::parse(std::vector<
book->numPredictors = reader.ReadInt32();
size_t length = 8 * book->order * book->numPredictors;
- if(length > 0x40){
- return std::nullopt;
- }
-
for(size_t i = 0; i < length; i++){
book->book.push_back(reader.ReadInt16());
}
diff --git a/src/factories/naudio/v1/BookFactory.h b/src/factories/naudio/v1/BookFactory.h
index a761f22..1ee83ea 100644
--- a/src/factories/naudio/v1/BookFactory.h
+++ b/src/factories/naudio/v1/BookFactory.h
@@ -32,4 +32,6 @@ public:
REGISTER(Code, ADPCMBookCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/DrumFactory.h b/src/factories/naudio/v1/DrumFactory.h
index e417e9a..34c2afd 100644
--- a/src/factories/naudio/v1/DrumFactory.h
+++ b/src/factories/naudio/v1/DrumFactory.h
@@ -34,4 +34,6 @@ public:
REGISTER(Code, DrumCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/EnvelopeFactory.h b/src/factories/naudio/v1/EnvelopeFactory.h
index a75d031..53e1b42 100644
--- a/src/factories/naudio/v1/EnvelopeFactory.h
+++ b/src/factories/naudio/v1/EnvelopeFactory.h
@@ -38,4 +38,6 @@ public:
REGISTER(Code, EnvelopeCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/InstrumentFactory.h b/src/factories/naudio/v1/InstrumentFactory.h
index 9d6ccf0..9af9295 100644
--- a/src/factories/naudio/v1/InstrumentFactory.h
+++ b/src/factories/naudio/v1/InstrumentFactory.h
@@ -37,4 +37,6 @@ public:
REGISTER(Code, InstrumentCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/LoopFactory.h b/src/factories/naudio/v1/LoopFactory.h
index e281946..72f2f7d 100644
--- a/src/factories/naudio/v1/LoopFactory.h
+++ b/src/factories/naudio/v1/LoopFactory.h
@@ -33,4 +33,6 @@ public:
REGISTER(Code, ADPCMLoopCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};
diff --git a/src/factories/naudio/v1/SampleFactory.cpp b/src/factories/naudio/v1/SampleFactory.cpp
index dec7ada..aa00782 100644
--- a/src/factories/naudio/v1/SampleFactory.cpp
+++ b/src/factories/naudio/v1/SampleFactory.cpp
@@ -1,6 +1,7 @@
#include "SampleFactory.h"
-#include "utils/Decompressor.h"
+#include "AudioConverter.h"
#include "Companion.h"
+#include <factories/naudio/v0/AIFCDecode.h>
ExportResult NSampleHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
const auto symbol = GetSafeNode(node, "symbol", entryName);
@@ -41,9 +42,26 @@ ExportResult NSampleBinaryExporter::Export(std::ostream &write, std::shared_ptr<
return std::nullopt;
}
+ExportResult NSampleModdingExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto aiff = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<NSampleData>(raw);
+ *replacement += ".aiff";
+
+ auto aifc = LUS::BinaryWriter();
+ AudioConverter::SampleToAIFC(data.get(), aifc);
+ auto cnv = aifc.ToVector();
+
+ if(!cnv.empty()){
+ write_aiff(cnv, aiff);
+ aiff.Finish(write);
+ }
+ return std::nullopt;
+}
+
std::optional<std::shared_ptr<IParsedData>> NSampleFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
auto offset = GetSafeNode<uint32_t>(node, "offset");
auto parent = GetSafeNode<uint32_t>(node, "parent");
+ auto tuning = GetSafeNode<float>(node, "tuning", 1.0f);
auto sampleBankId = GetSafeNode<uint32_t>(node, "sampleBankId");
auto entry = AudioContext::tables[AudioTableType::FONT_TABLE].at(parent);
@@ -74,6 +92,7 @@ std::optional<std::shared_ptr<IParsedData>> NSampleFactory::parse(std::vector<ui
Companion::Instance->AddAsset(book);
sample->sampleAddr = addr;
+ sample->tuning = tuning;
sample->sampleBankId = sampleBankId;
return sample;
diff --git a/src/factories/naudio/v1/SampleFactory.h b/src/factories/naudio/v1/SampleFactory.h
index d4ed44f..c95cb7a 100644
--- a/src/factories/naudio/v1/SampleFactory.h
+++ b/src/factories/naudio/v1/SampleFactory.h
@@ -14,6 +14,7 @@ public:
uint32_t loop;
uint32_t book;
uint32_t sampleBankId;
+ float tuning;
};
class NSampleHeaderExporter : public BaseExporter {
@@ -28,6 +29,10 @@ class NSampleCodeExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
+class NSampleModdingExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
class NSampleFactory : public BaseFactory {
public:
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
@@ -36,6 +41,8 @@ public:
REGISTER(Header, NSampleHeaderExporter)
REGISTER(Binary, NSampleBinaryExporter)
REGISTER(Code, NSampleCodeExporter)
+ REGISTER(Modding, NSampleModdingExporter)
};
}
+ bool SupportModdedAssets() override { return true; }
};
diff --git a/src/factories/naudio/v1/SoundFontFactory.h b/src/factories/naudio/v1/SoundFontFactory.h
index 8bb73e4..256f2ce 100644
--- a/src/factories/naudio/v1/SoundFontFactory.h
+++ b/src/factories/naudio/v1/SoundFontFactory.h
@@ -34,4 +34,6 @@ public:
REGISTER(Code, SoundFontCodeExporter)
};
}
+
+ bool HasModdedDependencies() override { return true; }
};