From 3a825d1440998362b647dca0219ee7657e866eb3 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 26 Nov 2023 12:47:34 +0100 Subject: [PATCH] First iteration for dumping t6 sound aliases --- src/Common/Game/T6/T6_Assets.h | 20 +- .../ObjContainer/SoundBank/SoundBank.cpp | 11 + .../ObjContainer/SoundBank/SoundBank.h | 2 + .../T6/AssetDumpers/AssetDumperSndBank.cpp | 350 ++++++++++++++---- 4 files changed, 303 insertions(+), 80 deletions(-) diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index 410d12d2..93e06d1b 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -5619,16 +5619,16 @@ namespace T6 int16_t fadeIn; int16_t fadeOut; int16_t dopplerScale; - char minPriorityThreshold; - char maxPriorityThreshold; - char probability; - char occlusionLevel; - char minPriority; - char maxPriority; - char pan; - char limitCount; - char entityLimitCount; - char duckGroup; + uint8_t minPriorityThreshold; + uint8_t maxPriorityThreshold; + uint8_t probability; + uint8_t occlusionLevel; + uint8_t minPriority; + uint8_t maxPriority; + uint8_t pan; + uint8_t limitCount; + uint8_t entityLimitCount; + uint8_t duckGroup; }; struct type_align(4) pathlink_s diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp index 3ab25c3a..c2802aa8 100644 --- a/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp @@ -297,6 +297,17 @@ bool SoundBank::VerifyChecksum(const SoundAssetBankChecksum& checksum) const return m_initialized && memcmp(checksum.checksumBytes, m_header.checksumChecksum.checksumBytes, sizeof(SoundAssetBankChecksum)) == 0; } +bool SoundBank::GetEntry(const unsigned id, SoundAssetBankEntry& entry) const +{ + const auto foundEntry = m_entries_by_id.find(id); + + if (foundEntry == m_entries_by_id.end()) + return false; + + entry = m_entries[foundEntry->second]; + return true; +} + SoundBankEntryInputStream SoundBank::GetEntryStream(const unsigned id) const { const auto foundEntry = m_entries_by_id.find(id); diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h index 1d71d032..0bb45bae 100644 --- a/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h @@ -42,6 +42,8 @@ public: _NODISCARD const std::vector& GetDependencies() const; _NODISCARD bool VerifyChecksum(const SoundAssetBankChecksum& checksum) const; + + bool GetEntry(unsigned id, SoundAssetBankEntry& entry) const; _NODISCARD SoundBankEntryInputStream GetEntryStream(unsigned int id) const; static ObjContainerRepository Repository; diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp index ce606f0a..e556629e 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include using namespace T6; @@ -97,6 +99,21 @@ namespace 96000, 192000, }; + + constexpr const char* EXTENSION_BY_FORMAT[SND_ASSET_FORMAT_COUNT]{ + ".wav", // SND_ASSET_FORMAT_PCMS16 + ".wav", // SND_ASSET_FORMAT_PCMS24 + ".wav", // SND_ASSET_FORMAT_PCMS32 + ".wav", // SND_ASSET_FORMAT_IEEE + ".xma", // SND_ASSET_FORMAT_XMA4 + ".mp3", // SND_ASSET_FORMAT_MP3 + ".wav", // SND_ASSET_FORMAT_MSADPCM + ".wma", // SND_ASSET_FORMAT_WMA + ".flac", // SND_ASSET_FORMAT_FLAC + ".wav", // SND_ASSET_FORMAT_WIIUADPCM + ".mpc", // SND_ASSET_FORMAT_MPC + }; + } // namespace class AssetDumperSndBank::Internal @@ -143,9 +160,23 @@ class AssetDumperSndBank::Internal return nullptr; } - static std::unique_ptr OpenAliasOutputFile(const SndBank* sndBank) + std::unique_ptr OpenAliasOutputFile(const SndBank* sndBank) const { - return nullptr; + std::ostringstream ss; + + const char* name; + if (sndBank->streamAssetBank.zone) + name = sndBank->streamAssetBank.zone; + else if (sndBank->loadAssetBank.zone) + name = sndBank->loadAssetBank.zone; + else if (sndBank->loadedAssets.zone) + name = sndBank->loadedAssets.zone; + else + name = sndBank->name; + + ss << "soundaliases/" << name << "_aliases.csv"; + + return m_context.OpenAssetFile(ss.str()); } static void WriteAliasFileHeader(CsvOutputStream& stream) @@ -158,83 +189,249 @@ class AssetDumperSndBank::Internal stream.NextRow(); } - static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias) + void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias) const { + SoundAssetBankEntry entry; + std::string extension; + if (FindSoundBankEntry(alias->assetId, entry)) + { + assert(entry.format < SND_ASSET_FORMAT_COUNT); + if (entry.format < SND_ASSET_FORMAT_COUNT) + extension = EXTENSION_BY_FORMAT[entry.format]; + } + // name - stream.WriteColumn(alias->name); + WriteColumnNullSafe(stream, alias->name); // file - stream.WriteColumn(alias->assetFileName); + if (alias->assetFileName) + stream.WriteColumn(GetAssetFilename(alias->assetFileName, extension)); + else + stream.WriteColumn(""); - // "# template", // template stream.WriteColumn(""); // loadspec stream.WriteColumn(""); - // "# secondary", - // "# group", - // "# vol_min", - // "# vol_max", - // "# team_vol_mod", - // "# dist_min", - // "# dist_max", - // "# dist_reverb_max", - // "# volume_falloff_curve", - // "# reverb_falloff_curve", - // "# volume_min_falloff_curve", - // "# reverb_min_falloff_curve", - // "# limit_count", - // "# limit_type", - // "# entity_limit_count", - // "# entity_limit_type", - // "# pitch_min", - // "# pitch_max", - // "# team_pitch_mod", - // "# min_priority", - // "# max_priority", - // "# min_priority_threshold", - // "# max_priority_threshold", - // "# spatialized", - // "# type", - // "# loop", - // "# randomize_type", - // "# probability", - // "# start_delay", - // "# reverb_send", - // "# duck", - // "# pan", - // "# center_send", - // "# envelop_min", - // "# envelop_max", - // "# envelop_percentage", - // "# occlusion_level", - // "# occlusion_wet_dry", - // "# is_big", - // "# distance_lpf", - // "# move_type", - // "# move_time", - // "# real_delay", - // "# subtitle", - // "# mature", - // "# doppler", - // "# futz", - // "# context_type", - // "# context_value", - // "# compression", - // "# timescale", - // "# music", - // "# fade_in", - // "# fade_out", - // "# pc_format", - // "# pause", - // "# stop_on_death", - // "# bus", - // "# snapshot", + // secondary + WriteColumnNullSafe(stream, alias->secondaryname); + + // group + stream.WriteColumn(""); + + // vol_min + WriteColumnFloat16(stream, alias->volMin); + + // vol_max + WriteColumnFloat16(stream, alias->volMax); + + // team_vol_mod + stream.WriteColumn(""); + + // dist_min + WriteColumnFloat16(stream, alias->distMin); + + // dist_max + WriteColumnFloat16(stream, alias->distMax); + + // dist_reverb_max + WriteColumnFloat16(stream, alias->distReverbMax); + + // volume_falloff_curve + stream.WriteColumn(""); + + // reverb_falloff_curve + stream.WriteColumn(""); + + // volume_min_falloff_curve + stream.WriteColumn(""); + + // reverb_min_falloff_curve + stream.WriteColumn(""); + + // limit_count + WriteColumnUnsignedNumeric(stream, alias->limitCount); + + // limit_type + stream.WriteColumn(""); + + // entity_limit_count + WriteColumnUnsignedNumeric(stream, alias->entityLimitCount); + + // entity_limit_type + stream.WriteColumn(""); + + // pitch_min + WriteColumnFloat16(stream, alias->pitchMin); + + // pitch_max + WriteColumnFloat16(stream, alias->pitchMax); + + // team_pitch_mod + stream.WriteColumn(""); + + // min_priority + WriteColumnUnsignedNumeric(stream, alias->minPriority); + + // max_priority + WriteColumnUnsignedNumeric(stream, alias->maxPriority); + + // min_priority_threshold + WriteColumnUnsignedNumeric(stream, alias->minPriorityThreshold); + + // max_priority_threshold + WriteColumnUnsignedNumeric(stream, alias->maxPriorityThreshold); + + // spatialized + stream.WriteColumn(""); + + // type + stream.WriteColumn(""); + + // loop + stream.WriteColumn(""); + + // randomize_type + stream.WriteColumn(""); + + // probability + WriteColumnUnsignedNumeric(stream, alias->probability); + + // start_delay + WriteColumnUnsignedNumeric(stream, alias->startDelay); + + // reverb_send + WriteColumnUnsignedNumeric(stream, alias->reverbSend); + + // duck + WriteColumnUnsignedNumeric(stream, alias->duck); + + // pan + WriteColumnUnsignedNumeric(stream, alias->pan); + + // center_send + WriteColumnUnsignedNumeric(stream, alias->centerSend); + + // envelop_min + WriteColumnUnsignedNumeric(stream, alias->envelopMin); + + // envelop_max + WriteColumnUnsignedNumeric(stream, alias->envelopMax); + + // envelop_percentage + WriteColumnUnsignedNumeric(stream, alias->envelopPercentage); + + // occlusion_level + WriteColumnFloat8(stream, alias->occlusionLevel); + + // occlusion_wet_dry + stream.WriteColumn(""); + + // is_big + stream.WriteColumn(""); + + // distance_lpf + stream.WriteColumn(""); + + // move_type + stream.WriteColumn(""); + + // move_time + stream.WriteColumn(""); + + // real_delay + stream.WriteColumn(""); + + // subtitle + WriteColumnNullSafe(stream, alias->subtitle); + + // mature + stream.WriteColumn(""); + + // doppler + stream.WriteColumn(""); + + // futz + WriteColumnUnsignedNumeric(stream, alias->futzPatch); + + // context_type + stream.WriteColumn(""); + + // context_value + stream.WriteColumn(""); + + // compression + stream.WriteColumn(""); + + // timescale + stream.WriteColumn(""); + + // music + stream.WriteColumn(""); + + // fade_in + WriteColumnSignedNumeric(stream, alias->fadeIn); + + // fade_out + WriteColumnSignedNumeric(stream, alias->fadeOut); + + // pc_format + stream.WriteColumn(""); + + // pause + stream.WriteColumn(""); + + // stop_on_death + stream.WriteColumn(""); + + // bus + stream.WriteColumn(""); + + // snapshot + stream.WriteColumn(""); + + stream.NextRow(); } - static void DumpSndBankAliases(const SndBank* sndBank) + static void WriteColumnNullSafe(CsvOutputStream& stream, const char* value) + { + if (value) + stream.WriteColumn(value); + else + stream.WriteColumn(""); + } + + static void WriteColumnFloat8(CsvOutputStream& stream, const uint8_t value) + { + std::ostringstream ss; + + ss << std::setprecision(6) << std::fixed << (static_cast(value) / static_cast(std::numeric_limits::max())); + + stream.WriteColumn(ss.str()); + } + + static void WriteColumnFloat16(CsvOutputStream& stream, const uint16_t value) + { + std::ostringstream ss; + + ss << std::setprecision(6) << std::fixed << (static_cast(value) / static_cast(std::numeric_limits::max())); + + stream.WriteColumn(ss.str()); + } + + static void WriteColumnSignedNumeric(CsvOutputStream& stream, const int value) + { + stream.WriteColumn(std::to_string(value)); + } + + static void WriteColumnUnsignedNumeric(CsvOutputStream& stream, const unsigned int value) + { + stream.WriteColumn(std::to_string(value)); + } + + void DumpSndBankAliases(const SndBank* sndBank) const { const auto outputFile = OpenAliasOutputFile(sndBank); @@ -258,6 +455,17 @@ class AssetDumperSndBank::Internal } } + static bool FindSoundBankEntry(const unsigned assetId, SoundAssetBankEntry& entry) + { + for (const auto* soundBank : SoundBank::Repository) + { + if (soundBank->GetEntry(assetId, entry)) + return true; + } + + return false; + } + static SoundBankEntryInputStream FindSoundDataInSoundBanks(const unsigned assetId) { for (const auto* soundBank : SoundBank::Repository) @@ -272,7 +480,8 @@ class AssetDumperSndBank::Internal void DumpSoundFilePcm(const char* assetFileName, const SoundBankEntryInputStream& soundFile, const unsigned bitsPerSample) const { - const auto outFile = OpenAssetOutputFile(assetFileName, ".wav"); + assert(soundFile.m_entry.format < SND_ASSET_FORMAT_COUNT); + const auto outFile = OpenAssetOutputFile(assetFileName, EXTENSION_BY_FORMAT[soundFile.m_entry.format]); if (!outFile) { std::cerr << "Failed to open sound output file: \"" << assetFileName << "\"\n"; @@ -297,9 +506,10 @@ class AssetDumperSndBank::Internal } } - void DumpSoundFilePassthrough(const char* assetFileName, const SoundBankEntryInputStream& soundFile, const std::string& extension) const + void DumpSoundFilePassthrough(const char* assetFileName, const SoundBankEntryInputStream& soundFile) const { - const auto outFile = OpenAssetOutputFile(assetFileName, extension); + assert(soundFile.m_entry.format < SND_ASSET_FORMAT_COUNT); + const auto outFile = OpenAssetOutputFile(assetFileName, EXTENSION_BY_FORMAT[soundFile.m_entry.format]); if (!outFile) { std::cerr << "Failed to open sound output file: \"" << assetFileName << "\"\n"; @@ -328,7 +538,7 @@ class AssetDumperSndBank::Internal break; case SND_ASSET_FORMAT_FLAC: - DumpSoundFilePassthrough(alias.assetFileName, soundFile, ".flac"); + DumpSoundFilePassthrough(alias.assetFileName, soundFile); break; case SND_ASSET_FORMAT_PCMS24: