diff options
| author | KiritoDv <kiritodev01@gmail.com> | 2026-05-11 15:16:08 -0600 |
|---|---|---|
| committer | KiritoDv <kiritodev01@gmail.com> | 2026-05-11 15:16:08 -0600 |
| commit | 9b3eef94e58065273d17a802ac26e13ffa49a19f (patch) | |
| tree | c1666df292519c2146bcca9a5ae7298ea5105af8 | |
| parent | 86a69ba5547df01550616f22d599d20b00bea17c (diff) | |
Trying to get rid of duplicated audio on sf64
| -rw-r--r-- | src/factories/naudio/v1/AudioContext.cpp | 10 | ||||
| -rw-r--r-- | src/factories/naudio/v1/AudioContext.h | 9 | ||||
| -rw-r--r-- | src/factories/naudio/v1/SampleFactory.cpp | 24 |
3 files changed, 41 insertions, 2 deletions
diff --git a/src/factories/naudio/v1/AudioContext.cpp b/src/factories/naudio/v1/AudioContext.cpp index 82d034a..45beef5 100644 --- a/src/factories/naudio/v1/AudioContext.cpp +++ b/src/factories/naudio/v1/AudioContext.cpp @@ -4,6 +4,8 @@ std::unordered_map<AudioTableType, TableEntry> AudioContext::tables; NAudioDrivers AudioContext::driver = NAudioDrivers::UNKNOWN; +std::unordered_map<uint64_t, std::string> AudioContext::sampleDedup; +std::unordered_map<uint32_t, std::string> AudioContext::sampleAddrRemap; std::optional<std::shared_ptr<IParsedData>> AudioContextFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) { auto driver = GetSafeNode<std::string>(node, "driver"); @@ -83,6 +85,14 @@ uint64_t AudioContext::GetPathByAddr(uint32_t addr) { return 0; } + // If this ROM address belongs to a duplicate SampleData struct, return the + // canonical's hash so instruments/drums reference the canonical entry directly. + auto remapIt = sampleAddrRemap.find(addr); + if (remapIt != sampleAddrRemap.end()) { + SPDLOG_INFO("Remapping duplicate 0x{:X} to canonical {}", addr, remapIt->second); + return CRC64(remapIt->second.c_str()); + } + auto dec = Companion::Instance->GetNodeByAddr(addr); if (dec.has_value()) { std::string path = std::get<0>(dec.value()); diff --git a/src/factories/naudio/v1/AudioContext.h b/src/factories/naudio/v1/AudioContext.h index 415d1f1..05e5516 100644 --- a/src/factories/naudio/v1/AudioContext.h +++ b/src/factories/naudio/v1/AudioContext.h @@ -3,6 +3,8 @@ #include "AudioTableFactory.h" #include "factories/naudio/v0/AudioHeaderFactory.h" #include "factories/BaseFactory.h" +#include <unordered_map> +#include <string> struct TunedSample { uint32_t sample; @@ -25,6 +27,13 @@ class AudioContext { public: static std::unordered_map<AudioTableType, TableEntry> tables; static NAudioDrivers driver; + // Key: (sampleBankId << 32) | sampleAddr → canonical archive path. + // Populated during parse so all dedup decisions are made before any export runs. + static std::unordered_map<uint64_t, std::string> sampleDedup; + // Key: ROM offset of a duplicate SampleData struct → canonical archive path. + // Used by GetPathByAddr() so instrument/drum export writes the canonical hash + // instead of the duplicate's hash, making redirect entries permanently unreferenced. + static std::unordered_map<uint32_t, std::string> sampleAddrRemap; static LUS::BinaryReader MakeReader(AudioTableType type, uint32_t offset); static TunedSample LoadTunedSample(LUS::BinaryReader& reader, uint32_t parent, uint32_t sampleBankId); diff --git a/src/factories/naudio/v1/SampleFactory.cpp b/src/factories/naudio/v1/SampleFactory.cpp index 2faafe2..4616d3f 100644 --- a/src/factories/naudio/v1/SampleFactory.cpp +++ b/src/factories/naudio/v1/SampleFactory.cpp @@ -28,9 +28,10 @@ ExportResult NSampleCodeExporter::Export(std::ostream& write, std::shared_ptr<IP ExportResult NSampleBinaryExporter::Export(std::ostream& write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node& node, std::string* replacement) { - auto writer = LUS::BinaryWriter(); + // parse() returns nullopt for duplicates, so Export() is only reached for + // canonical samples — no redirect check needed here. auto data = std::static_pointer_cast<NSampleData>(raw); - + auto writer = LUS::BinaryWriter(); WriteHeader(writer, Torch::ResourceType::Sample, 1); writer.Write((uint8_t)data->codec); writer.Write((uint8_t)data->medium); @@ -190,5 +191,24 @@ std::optional<std::shared_ptr<IParsedData>> NSampleFactory::parse(std::vector<ui sample->sampleBankId = sampleBankId; sample->sampleRate = sampleRate; + // Build dedup maps at parse time so GetPathByAddr() has full information + // before any instrument/drum export runs. + if (addr != 0) { + uint64_t key = ((uint64_t)sampleBankId << 32) | (uint64_t)addr; + auto it = AudioContext::sampleDedup.find(key); + if (it == AudioContext::sampleDedup.end()) { + // First time we see this audio data: this struct is the canonical. + auto pathDec = Companion::Instance->GetNodeByAddr(offset); + if (pathDec.has_value()) { + AudioContext::sampleDedup[key] = std::get<0>(pathDec.value()); + } + } else { + // Duplicate: map this ROM offset → canonical path for GetPathByAddr(), + // then return nullopt so the Companion produces no archive entry for it. + AudioContext::sampleAddrRemap[offset] = it->second; + return std::nullopt; + } + } + return sample; } |
