diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp index b72dabfa8..feb83783a 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp @@ -4,6 +4,7 @@ #include "ObjContainer/SoundBank/SoundBank.h" #include "Sound/WavWriter.h" #include "Utils/ClassUtils.h" +#include "nlohmann/json.hpp" #include #include @@ -15,71 +16,89 @@ namespace fs = std::filesystem; namespace { const std::string ALIAS_HEADERS[]{ - "# name", - "# file", - "# template", - "# loadspec", - "# 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", + "name", + "file", + "template", + "loadspec", + "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", }; + const std::string REVERB_HEADERS[]{"name", + "smoothing", + "earlyTime", + "lateTime", + "earlyGain", + "lateGain", + "returnGain", + "earlyLpf", + "lateLpf", + "inputLpf", + "dampLpf", + "wallReflect", + "dryGain", + "earlySize", + "lateSize", + "diffusion", + "returnHighpass"}; + const std::string PREFIXES_TO_DROP[]{ "raw/", "devraw/", @@ -96,6 +115,119 @@ namespace 96000, 192000, }; + + const std::string GROUPS_ENUM[]{"grp_reference", + "grp_master", + "grp_wpn_lfe", + "grp_lfe", + "grp_hdrfx", + "grp_music", + "grp_voice", + "grp_set_piece", + "grp_igc", + "grp_mp_game", + "grp_explosion", + "grp_player_impacts", + "grp_scripted_moment", + "grp_menu", + "grp_whizby", + "grp_weapon", + "grp_vehicle", + "grp_impacts", + "grp_foley", + "grp_destructible", + "grp_physics", + "grp_ambience", + "grp_alerts", + "grp_air", + "grp_bink", + "grp_announcer", + ""}; + + const std::string CURVES_ENUM[]{"default", + "defaultmin", + "allon", + "alloff", + "rcurve0", + "rcurve1", + "rcurve2", + "rcurve3", + "rcurve4", + "rcurve5", + "steep", + "sindelay", + "cosdelay", + "sin", + "cos", + "rev60", + "rev65", + ""}; + + const std::unordered_map CURVES_MAP{ + {4135636924, CURVES_ENUM[0] }, // "default" + {1298231670, CURVES_ENUM[1] }, // "defaultmin" + {2783299419, CURVES_ENUM[2] }, // "allon" + {2598309331, CURVES_ENUM[3] }, // "alloff" + {2462421902, CURVES_ENUM[4] }, // "rcurve0" + {2462421903, CURVES_ENUM[5] }, // "rcurve1" + {2462421904, CURVES_ENUM[6] }, // "rcurve2" + {2462421905, CURVES_ENUM[7] }, // "rcurve3" + {2462421906, CURVES_ENUM[8] }, // "rcurve4" + {2462421907, CURVES_ENUM[9] }, // "rcurve5" + {3711863914, CURVES_ENUM[10]}, // "steep" + {4107033168, CURVES_ENUM[11]}, // "sindelay" + {932232097, CURVES_ENUM[12]}, // "cosdelay" + {818663411, CURVES_ENUM[13]}, // "sin" + {686872930, CURVES_ENUM[14]}, // "cos" + {3885755896, CURVES_ENUM[15]}, // "rev60" + {3885755901, CURVES_ENUM[16]}, // "rev65" + }; + + const std::string DUCK_GROUPS_ENUM[]{ + "snp_alerts_gameplay", + "snp_ambience", + "snp_claw", + "snp_destructible", + "snp_dying", + "snp_dying_ice", + "snp_evt_2d", + "snp_explosion", + "snp_foley", + "snp_grenade", + "snp_hdrfx", + "snp_igc", + "snp_impacts", + "snp_menu", + "snp_movie", + "snp_music", + "snp_never_duck", + "snp_player_dead", + "snp_player_impacts", + "snp_scripted_moment", + "snp_set_piece", + "snp_special", + "snp_vehicle", + "snp_vehicle_interior", + "snp_voice", + "snp_weapon_decay_1p", + "snp_whizby", + "snp_wpn_1p", + "snp_wpn_3p", + "snp_wpn_turret", + "snp_x2", + "snp_x3", + }; + + const std::string LOOP_TYPES_ENUM[]{"nonlooping", "looping"}; + + const std::string LIMIT_TYPES_ENUM[]{"none", "oldest", "reject", "priority"}; + + const std::string MOVE_TYPES_ENUM[]{"none", "left_player", "center_player", "right_player", "random", "left_shot", "center_shot", "right_shot"}; + + const std::string LOAD_TYPES_ENUM[]{"unknown", "loaded", "streamed", "primed"}; + + const std::string BUS_IDS_ENUM[]{ + "bus_reverb", "bus_fx", "bus_voice", "bus_pfutz", "bus_hdrfx", "bus_ui", "bus_reference", "bus_music", "bus_movie", "bus_reference", ""}; } // namespace class AssetDumperSndBank::Internal @@ -142,14 +274,19 @@ class AssetDumperSndBank::Internal return nullptr; } - static std::unique_ptr OpenAliasOutputFile(const SndBank* sndBank) + static void WriteAliasFileHeader(CsvOutputStream& stream) { - return nullptr; + for (const auto& headerField : ALIAS_HEADERS) + { + stream.WriteColumn(headerField); + } + + stream.NextRow(); } - static void WriteAliasFileHeader(CsvOutputStream& stream) + static void WriteReverbFileHeader(CsvOutputStream& stream) { - for (const auto& headerField : ALIAS_HEADERS) + for (const auto& headerField : REVERB_HEADERS) { stream.WriteColumn(headerField); } @@ -157,7 +294,20 @@ class AssetDumperSndBank::Internal stream.NextRow(); } - static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias) + static const char* FindNameForDuck(unsigned int id, const SndDuck* ducks, unsigned int duckCount) + { + for (auto i = 0u; i < duckCount; i++) + { + if (id == ducks[i].id) + { + return ducks[i].name; + } + } + + return ""; + } + + static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias, const SndBank* bank) { // name stream.WriteColumn(alias->name); @@ -165,96 +315,188 @@ class AssetDumperSndBank::Internal // file stream.WriteColumn(alias->assetFileName); - // "# 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 + stream.WriteColumn((alias->secondaryname && *alias->secondaryname) ? alias->secondaryname : ""); - static void DumpSndBankAliases(const SndBank* sndBank) - { - const auto outputFile = OpenAliasOutputFile(sndBank); + // group + stream.WriteColumn(GROUPS_ENUM[std::min((alias->flags0 >> 17) & 0x1F, 26u)]); - if (outputFile == nullptr) - { - std::cout << "Failed to open sound alias output file for: \"" << sndBank->name << "\"" << std::endl; - return; - } + // vol_min + stream.WriteColumn(std::to_string(alias->volMin)); - CsvOutputStream csvStream(*outputFile); - WriteAliasFileHeader(csvStream); + // vol_max + stream.WriteColumn(std::to_string(alias->volMax)); - for (auto i = 0u; i < sndBank->aliasCount; i++) - { - const auto& aliasList = sndBank->alias[i]; - for (auto j = 0; j < aliasList.count; j++) - { - const auto& alias = aliasList.head[j]; - WriteAliasToFile(csvStream, &alias); - } - } + // team_vol_mod + stream.WriteColumn(""); + + // dist_min + stream.WriteColumn(std::to_string(alias->distMin)); + + // dist_max + stream.WriteColumn(std::to_string(alias->distMax)); + + // dist_reverb_max + stream.WriteColumn(std::to_string(alias->distReverbMax)); + + // volume_falloff_curve + stream.WriteColumn(CURVES_ENUM[std::min((alias->flags1 >> 14) & 0x1F, 17u)]); + + // reverb_falloff_curve + stream.WriteColumn(CURVES_ENUM[std::min((alias->flags1 >> 20) & 0x1F, 17u)]); + + // volume_min_falloff_curve + stream.WriteColumn(CURVES_ENUM[std::min((alias->flags1 >> 2) & 0x1F, 17u)]); + + // reverb_min_falloff_curve" + stream.WriteColumn(CURVES_ENUM[std::min((alias->flags1 >> 8) & 0x1F, 17u)]); + + // limit_count + stream.WriteColumn(std::to_string(alias->limitCount)); + + // limit_type + stream.WriteColumn(LIMIT_TYPES_ENUM[(alias->flags0 >> 25) & 0x3]); + + // entity_limit_count + stream.WriteColumn(std::to_string(alias->entityLimitCount)); + + // entity_limit_type + stream.WriteColumn(LIMIT_TYPES_ENUM[(alias->flags0 >> 27) & 0x3]); + + // pitch_min + stream.WriteColumn(std::to_string(alias->pitchMin)); + + // pitch_max + stream.WriteColumn(std::to_string(alias->pitchMax)); + + // team_pitch_mod + stream.WriteColumn(""); + + // min_priority + stream.WriteColumn(std::to_string(alias->minPriority)); + + // max_priority + stream.WriteColumn(std::to_string(alias->maxPriority)); + + // min_priority_threshold + stream.WriteColumn(std::to_string(alias->minPriorityThreshold)); + + // max_priority_threshold + stream.WriteColumn(std::to_string(alias->maxPriorityThreshold)); + + // spatialized + stream.WriteColumn(""); + + // type + stream.WriteColumn(std::to_string(alias->contextType)); + + // loop + stream.WriteColumn((alias->flags0 & 0x1) == 0 ? "nonlooping" : "looping"); + + // randomize_type + stream.WriteColumn(LIMIT_TYPES_ENUM[(alias->flags0 >> 15) & 0x3]); + + // probability", + stream.WriteColumn(std::to_string(alias->probability)); + + // start_delay", + stream.WriteColumn(std::to_string(alias->startDelay)); + + // reverb_send", + stream.WriteColumn(std::to_string(alias->reverbSend)); + + // duck", + stream.WriteColumn(FindNameForDuck(alias->duck, bank->ducks, bank->duckCount)); + + // pan", + stream.WriteColumn(((alias->flags0 >> 6) & 0x1) == 0 ? "2d" : "3d"); + + // center_send", + stream.WriteColumn(std::to_string(alias->centerSend)); + + // envelop_min", + stream.WriteColumn(std::to_string(alias->envelopMin)); + + // envelop_max", + stream.WriteColumn(std::to_string(alias->envelopMax)); + + // envelop_percentage", + stream.WriteColumn(std::to_string(alias->envelopPercentage)); + + // occlusion_level", + stream.WriteColumn(std::to_string(alias->occlusionLevel)); + + // occlusion_wet_dry", + stream.WriteColumn(""); + + // is_big", + stream.WriteColumn(((alias->flags0 >> 4) & 0x1) == 0 ? "no" : "yes"); + + // distance_lpf" + stream.WriteColumn(((alias->flags0 >> 2) & 0x1) == 0 ? "no" : "yes"); + + // move_type", + stream.WriteColumn(MOVE_TYPES_ENUM[std::min((alias->flags0 >> 22) & 0x7, 7u)]); + + // move_time", + stream.WriteColumn(std::to_string(alias->fluxTime)); + + // real_delay", + stream.WriteColumn(""); + + // subtitle", + stream.WriteColumn((alias->subtitle && *alias->subtitle) ? alias->subtitle : ""); + + // mature", + stream.WriteColumn(""); + + // doppler", + stream.WriteColumn(((alias->flags0 >> 1) & 0x1) == 0 ? "no" : "yes"); + + // futz", + stream.WriteColumn(""); + + // context_type", + stream.WriteColumn(std::to_string(alias->contextType)); + + // context_value", + stream.WriteColumn(std::to_string(alias->contextValue)); + + // compression", + stream.WriteColumn(""); + + // timescale", + stream.WriteColumn(((alias->flags0 >> 8) & 0x1) == 0 ? "no" : "yes"); + + // music", + stream.WriteColumn(((alias->flags0 >> 10) & 0x1) == 0 ? "no" : "yes"); + + // fade_in", + stream.WriteColumn(std::to_string(alias->fadeIn)); + + // fade_out", + stream.WriteColumn(std::to_string(alias->fadeOut)); + + // pc_format", + stream.WriteColumn(""); + + // pause", + stream.WriteColumn(((alias->flags0 >> 5) & 0x1) == 0 ? "no" : "yes"); + + // stop_on_death", + stream.WriteColumn(((alias->flags0 >> 7) & 0x1) == 0 ? "no" : "yes"); + + // bus", + stream.WriteColumn(BUS_IDS_ENUM[std::min((alias->flags0 >> 13) & 0xF, 10u)]); + + // snapshot", + stream.WriteColumn(""); } static SoundBankEntryInputStream FindSoundDataInSoundBanks(const unsigned assetId) @@ -353,10 +595,20 @@ class AssetDumperSndBank::Internal } } - void DumpSoundData(const SndBank* sndBank) const + void DumpSndBankAliases(const SndBank* sndBank) const { std::unordered_set dumpedAssets; + const auto outFile = OpenAssetOutputFile("soundbank\\" + std::string(sndBank->name) + ".aliases", ".csv"); + if (!outFile) + { + std::cerr << "Failed to open sound alias output file: \"" << sndBank->name << "\"\n"; + return; + } + + CsvOutputStream csvStream(*outFile); + WriteAliasFileHeader(csvStream); + for (auto i = 0u; i < sndBank->aliasCount; i++) { const auto& aliasList = sndBank->alias[i]; @@ -368,17 +620,130 @@ class AssetDumperSndBank::Internal { DumpSndAlias(alias); dumpedAssets.emplace(alias.assetId); + + WriteAliasToFile(csvStream, &alias, sndBank); + csvStream.NextRow(); } } } } + void DumpSoundRadverb(const SndBank* sndBank) const + { + if (sndBank->radverbCount <= 0) + { + return; + } + + const auto outFile = OpenAssetOutputFile("soundbank\\" + std::string(sndBank->name) + ".reverbs", ".csv"); + if (!outFile) + { + std::cerr << "Failed to open sound reverb output file: \"" << sndBank->name << "\"\n"; + return; + } + + CsvOutputStream csvStream(*outFile); + WriteReverbFileHeader(csvStream); + + for (auto i = 0u; i < sndBank->radverbCount; i++) + { + const auto& reverb = sndBank->radverbs[i]; + csvStream.WriteColumn(reverb.name); + csvStream.WriteColumn(std::to_string(reverb.smoothing)); + csvStream.WriteColumn(std::to_string(reverb.earlyTime)); + csvStream.WriteColumn(std::to_string(reverb.lateTime)); + csvStream.WriteColumn(std::to_string(reverb.earlyGain)); + csvStream.WriteColumn(std::to_string(reverb.lateGain)); + csvStream.WriteColumn(std::to_string(reverb.returnGain)); + csvStream.WriteColumn(std::to_string(reverb.earlyLpf)); + csvStream.WriteColumn(std::to_string(reverb.lateLpf)); + csvStream.WriteColumn(std::to_string(reverb.inputLpf)); + csvStream.WriteColumn(std::to_string(reverb.dampLpf)); + csvStream.WriteColumn(std::to_string(reverb.wallReflect)); + csvStream.WriteColumn(std::to_string(reverb.dryGain)); + csvStream.WriteColumn(std::to_string(reverb.earlySize)); + csvStream.WriteColumn(std::to_string(reverb.lateSize)); + csvStream.WriteColumn(std::to_string(reverb.diffusion)); + csvStream.WriteColumn(std::to_string(reverb.returnHighpass)); + csvStream.NextRow(); + } + } + + void DumpSoundDucks(const SndBank* sndBank) const + { + if (sndBank->duckCount <= 0) + { + return; + } + + const auto outFile = OpenAssetOutputFile("soundbank\\" + std::string(sndBank->name) + ".ducklist", ".csv"); + if (!outFile) + { + std::cerr << "Failed to open sound reverb output file: \"" << sndBank->name << "\"\n"; + return; + } + + CsvOutputStream csvStream(*outFile); + csvStream.WriteColumn("name"); + csvStream.NextRow(); + + for (auto i = 0u; i < sndBank->duckCount; i++) + { + const auto& duck = sndBank->ducks[i]; + csvStream.WriteColumn(duck.name); + csvStream.NextRow(); + + const auto duckFile = OpenAssetOutputFile("soundbank\\ducks\\" + std::string(duck.name), ".duk"); + if (!outFile) + { + std::cerr << "Failed to open sound duck output file: \"" << duck.name << "\"\n"; + return; + } + + nlohmann::json duckObj{}; + duckObj["fadeIn"] = duck.fadeIn; + duckObj["fadeOut"] = duck.fadeOut; + duckObj["startDelay"] = duck.startDelay; + duckObj["distance"] = duck.distance; + duckObj["length"] = duck.length; + duckObj["fadeInCurveId"] = duck.fadeInCurve; + duckObj["fadeOutCurveId"] = duck.fadeOutCurve; + duckObj["updateWhilePaused"] = duck.updateWhilePaused; + + auto fadeInItr = CURVES_MAP.find(duck.fadeInCurve); + if (fadeInItr != CURVES_MAP.end()) + { + duckObj["fadeInCurve"] = fadeInItr->second; + } + + auto fadeOutItr = CURVES_MAP.find(duck.fadeOutCurve); + if (fadeOutItr != CURVES_MAP.end()) + { + duckObj["fadeOutCurve"] = fadeOutItr->second; + } + + auto values = std::vector{}; + for (auto i = 0u; i < 32u; i++) + { + values.push_back({ + {"duckGroup", DUCK_GROUPS_ENUM[i]}, + {"attenuation", duck.attenuation[i]}, + {"filter", duck.filter[i] } + }); + } + + duckObj["values"] = values; + *duckFile << duckObj.dump(4) << std::endl; + } + } + void DumpSndBank(const XAssetInfo* sndBankInfo) const { const auto* sndBank = sndBankInfo->Asset(); DumpSndBankAliases(sndBank); - DumpSoundData(sndBank); + DumpSoundRadverb(sndBank); + DumpSoundDucks(sndBank); } public: diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.cpp new file mode 100644 index 000000000..fee44dfed --- /dev/null +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.cpp @@ -0,0 +1,337 @@ +#include "AssetDumperSndDriverGlobals.h" + +#include "Csv/CsvStream.h" +#include "ObjContainer/SoundBank/SoundBank.h" +#include "Utils/ClassUtils.h" + +#include +#include +#include + +using namespace T6; +namespace fs = std::filesystem; + +class AssetDumperSndDriverGlobals::Internal +{ + AssetDumpingContext& m_context; + + inline static const std::string GROUPS_HEADERS[]{"name", "attenuationSp", "attenuationMp", "category", "parent", "id"}; + + inline static const std::string GROUPS_CATEGORIES[]{"sfx", "music", "void", "ui", "cinematic", "id"}; + + inline static const std::string CURVE_HEADERS[]{ + "name", "x0", "y0", "x1", "y1", "x2", "y2", "x3", "y3", "x4", "y4", "x5", "y5", "x6", "y6", "x7", "y7", "id"}; + + inline static const std::string PAN_HEADERS[]{"name", "front", "back", "center", "lfe", "left", "right", "id"}; + + inline static const std::string MASTER_HEADERS[]{ + "name", "lowE", "lowG", "lowF", "lowQ", "peak1E", "peak1G", "peak1F", "peak1Q", "peak2E", "peak2G", + "peak2F", "peak2Q", "hiE", "hiG", "hiF", "hiQ", "eqG", "compE", "compPG", "compMG", "compT", + "compR", "compTA", "compTR", "limitE", "limitPG", "limitMG", "limitT", "limitR", "limitTA", "limitTR", "busReverbG", + "busFxG", "busVoiceG", "busPfutzG", "busHdrfxG", "busUiG", "busMusicG", "busMovieG", "busVcsG", "busReverbE", "busFxE", "busVoiceE", + "busPfutzE", "busHdrfxE", "busUiE", "busMusicE", "busMovieE", "hdrfxCompE", "voiceEqE", "voiceCompE", "id"}; + + inline static const std::string SIDECHAIN_HEADERS[]{"name", "g", "f", "q", "ta", "tr", "tf", "id"}; + + inline static const std::string FUTZ_HEADERS[]{"name", + "bpfF", + "bpfQ", + "lsG", + "lsF", + "lsQ", + "dist", + "preG", + "postG", + "th", + "tg", + "clippre", + "clippost", + "blend", + "startAliasId", + "stopAliasId", + "loopAliasId", + "id"}; + + std::unique_ptr OpenAssetFile(const std::string& filename) + { + auto outputFile = this->m_context.OpenAssetFile(filename); + if (outputFile == nullptr) + { + std::cout << "Failed to open sound driver globals output file for: \"" << filename << "\"" << std::endl; + } + + return outputFile; + } + + static void WriteFileHeader(CsvOutputStream& stream, const std::string* headers, size_t count) + { + for (auto i = 0u; i < count; i++) + { + stream.WriteColumn(headers[i]); + } + + stream.NextRow(); + } + + void DumpSndVolumesGroups(const SndVolumeGroup* groups, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\group.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, GROUPS_HEADERS, 6); + + for (auto i = 0u; i < count; i++) + { + const auto& group = groups[i]; + csvStream.WriteColumn(group.name); + csvStream.WriteColumn(std::to_string(group.attenuationSp)); + csvStream.WriteColumn(std::to_string(group.attenuationMp)); + csvStream.WriteColumn(GROUPS_CATEGORIES[group.category]); + csvStream.WriteColumn(group.parentName); + csvStream.WriteColumn(std::to_string(group.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndCurves(const SndCurve* curves, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\curves.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, CURVE_HEADERS, 18); + + for (auto i = 0u; i < count; i++) + { + const auto& curve = curves[i]; + csvStream.WriteColumn(curve.name); + + for (auto j = 0u; j < 8; j++) + { + csvStream.WriteColumn(std::to_string(curve.points[j].x)); + csvStream.WriteColumn(std::to_string(curve.points[j].y)); + } + + csvStream.WriteColumn(std::to_string(curve.id)); + + csvStream.NextRow(); + } + } + } + + void DumpSndPans(const SndPan* pans, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\pan.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, PAN_HEADERS, 8); + + for (auto i = 0u; i < count; i++) + { + const auto& pan = pans[i]; + csvStream.WriteColumn(pan.name); + csvStream.WriteColumn(std::to_string(pan.front)); + csvStream.WriteColumn(std::to_string(pan.back)); + csvStream.WriteColumn(std::to_string(pan.center)); + csvStream.WriteColumn(std::to_string(pan.lfe)); + csvStream.WriteColumn(std::to_string(pan.left)); + csvStream.WriteColumn(std::to_string(pan.right)); + csvStream.WriteColumn(std::to_string(pan.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndDuckGroups(const SndDuckGroup* duckGroups, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\duck_groups.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + csvStream.WriteColumn("name"); + csvStream.NextRow(); + + for (auto i = 0u; i < count; i++) + { + const auto& duckGroup = duckGroups[i]; + csvStream.WriteColumn(duckGroup.name); + csvStream.WriteColumn(std::to_string(duckGroup.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndMasters(const SndMaster* masters, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\master.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, MASTER_HEADERS, 53); + + for (auto i = 0u; i < count; i++) + { + const auto& master = masters[i]; + csvStream.WriteColumn(master.name); + csvStream.WriteColumn(std::to_string(master.lowE)); + csvStream.WriteColumn(std::to_string(master.lowG)); + csvStream.WriteColumn(std::to_string(master.lowF)); + csvStream.WriteColumn(std::to_string(master.lowQ)); + csvStream.WriteColumn(std::to_string(master.peak1E)); + csvStream.WriteColumn(std::to_string(master.peak1G)); + csvStream.WriteColumn(std::to_string(master.peak1F)); + csvStream.WriteColumn(std::to_string(master.peak1Q)); + csvStream.WriteColumn(std::to_string(master.peak2E)); + csvStream.WriteColumn(std::to_string(master.peak2G)); + csvStream.WriteColumn(std::to_string(master.peak2F)); + csvStream.WriteColumn(std::to_string(master.peak2Q)); + csvStream.WriteColumn(std::to_string(master.hiE)); + csvStream.WriteColumn(std::to_string(master.hiG)); + csvStream.WriteColumn(std::to_string(master.hiF)); + csvStream.WriteColumn(std::to_string(master.hiQ)); + csvStream.WriteColumn(std::to_string(master.eqG)); + csvStream.WriteColumn(std::to_string(master.compE)); + csvStream.WriteColumn(std::to_string(master.compPG)); + csvStream.WriteColumn(std::to_string(master.compMG)); + csvStream.WriteColumn(std::to_string(master.compT)); + csvStream.WriteColumn(std::to_string(master.compR)); + csvStream.WriteColumn(std::to_string(master.compTA)); + csvStream.WriteColumn(std::to_string(master.compTR)); + csvStream.WriteColumn(std::to_string(master.limitE)); + csvStream.WriteColumn(std::to_string(master.limitPG)); + csvStream.WriteColumn(std::to_string(master.limitMG)); + csvStream.WriteColumn(std::to_string(master.limitT)); + csvStream.WriteColumn(std::to_string(master.limitR)); + csvStream.WriteColumn(std::to_string(master.limitTA)); + csvStream.WriteColumn(std::to_string(master.limitTR)); + csvStream.WriteColumn(std::to_string(master.busReverbG)); + csvStream.WriteColumn(std::to_string(master.busFxG)); + csvStream.WriteColumn(std::to_string(master.busVoiceG)); + csvStream.WriteColumn(std::to_string(master.busPfutzG)); + csvStream.WriteColumn(std::to_string(master.busHdrfxG)); + csvStream.WriteColumn(std::to_string(master.busUiG)); + csvStream.WriteColumn(std::to_string(master.busMusicG)); + csvStream.WriteColumn(std::to_string(master.busMovieG)); + csvStream.WriteColumn(std::to_string(master.busVcsG)); + csvStream.WriteColumn(std::to_string(master.busReverbE)); + csvStream.WriteColumn(std::to_string(master.busFxE)); + csvStream.WriteColumn(std::to_string(master.busVoiceE)); + csvStream.WriteColumn(std::to_string(master.busPfutzE)); + csvStream.WriteColumn(std::to_string(master.busHdrfxE)); + csvStream.WriteColumn(std::to_string(master.busUiE)); + csvStream.WriteColumn(std::to_string(master.busMusicE)); + csvStream.WriteColumn(std::to_string(master.busMovieE)); + csvStream.WriteColumn(std::to_string(master.hdrfxCompE)); + csvStream.WriteColumn(std::to_string(master.voiceEqE)); + csvStream.WriteColumn(std::to_string(master.voiceCompE)); + csvStream.WriteColumn(std::to_string(master.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndSidechainDucks(const SndSidechainDuck* sidechains, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\sidechain_duck.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, SIDECHAIN_HEADERS, 8); + + for (auto i = 0u; i < count; i++) + { + const auto& sidechain = sidechains[i]; + csvStream.WriteColumn(sidechain.name); + csvStream.WriteColumn(std::to_string(sidechain.g)); + csvStream.WriteColumn(std::to_string(sidechain.f)); + csvStream.WriteColumn(std::to_string(sidechain.q)); + csvStream.WriteColumn(std::to_string(sidechain.ta)); + csvStream.WriteColumn(std::to_string(sidechain.tr)); + csvStream.WriteColumn(std::to_string(sidechain.tf)); + csvStream.WriteColumn(std::to_string(sidechain.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndFutz(const SndFutz* futzes, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank\\globals\\futz.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, FUTZ_HEADERS, 18); + + for (auto i = 0u; i < count; i++) + { + const auto& futz = futzes[i]; + csvStream.WriteColumn(futz.name); + csvStream.WriteColumn(std::to_string(futz.bpfF)); + csvStream.WriteColumn(std::to_string(futz.bpfQ)); + csvStream.WriteColumn(std::to_string(futz.lsG)); + csvStream.WriteColumn(std::to_string(futz.lsF)); + csvStream.WriteColumn(std::to_string(futz.lsQ)); + csvStream.WriteColumn(std::to_string(futz.dist)); + csvStream.WriteColumn(std::to_string(futz.preG)); + csvStream.WriteColumn(std::to_string(futz.postG)); + csvStream.WriteColumn(std::to_string(futz.th)); + csvStream.WriteColumn(std::to_string(futz.tg)); + csvStream.WriteColumn(std::to_string(futz.clippre)); + csvStream.WriteColumn(std::to_string(futz.clippost)); + csvStream.WriteColumn(std::to_string(futz.blend)); + csvStream.WriteColumn(std::to_string(futz.startAliasId)); + csvStream.WriteColumn(std::to_string(futz.stopAliasId)); + csvStream.WriteColumn(std::to_string(futz.loopAliasId)); + csvStream.WriteColumn(std::to_string(futz.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndDriverGlobals(const XAssetInfo* sndDriverGlobalsInfo) + { + const auto* sndDriverGlobals = sndDriverGlobalsInfo->Asset(); + + DumpSndVolumesGroups(sndDriverGlobals->groups, sndDriverGlobals->groupCount); + DumpSndCurves(sndDriverGlobals->curves, sndDriverGlobals->curveCount); + DumpSndPans(sndDriverGlobals->pans, sndDriverGlobals->panCount); + DumpSndDuckGroups(sndDriverGlobals->duckGroups, sndDriverGlobals->duckGroupCount); + // DumpSndContexts(sndDriverGlobals->contexts, sndDriverGlobals->contextCount); + DumpSndMasters(sndDriverGlobals->masters, sndDriverGlobals->masterCount); + DumpSndSidechainDucks(sndDriverGlobals->voiceDucks, sndDriverGlobals->voiceDuckCount); + DumpSndFutz(sndDriverGlobals->futzes, sndDriverGlobals->futzCount); + } + +public: + explicit Internal(AssetDumpingContext& context) + : m_context(context) + { + } + + void DumpPool(AssetPool* pool) + { + for (const auto* assetInfo : *pool) + { + if (!assetInfo->m_name.empty() && assetInfo->m_name[0] == ',') + continue; + + DumpSndDriverGlobals(assetInfo); + } + } +}; + +void AssetDumperSndDriverGlobals::DumpPool(AssetDumpingContext& context, AssetPool* pool) +{ + Internal internal(context); + internal.DumpPool(pool); +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.h new file mode 100644 index 000000000..18f0cf896 --- /dev/null +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace T6 +{ + class AssetDumperSndDriverGlobals final : public IAssetDumper + { + class Internal; + + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace T6 diff --git a/src/ObjWriting/Game/T6/ZoneDumperT6.cpp b/src/ObjWriting/Game/T6/ZoneDumperT6.cpp index c01fe85b5..6f96586c9 100644 --- a/src/ObjWriting/Game/T6/ZoneDumperT6.cpp +++ b/src/ObjWriting/Game/T6/ZoneDumperT6.cpp @@ -11,6 +11,7 @@ #include "AssetDumpers/AssetDumperSlug.h" #include "AssetDumpers/AssetDumperSndBank.h" #include "AssetDumpers/AssetDumperStringTable.h" +#include "AssetDumpers/AssetDumperSndDriverGlobals.h" #include "AssetDumpers/AssetDumperTracer.h" #include "AssetDumpers/AssetDumperVehicle.h" #include "AssetDumpers/AssetDumperWeapon.h" @@ -66,7 +67,7 @@ bool ZoneDumper::DumpZone(AssetDumpingContext& context) const DUMP_ASSET_POOL(AssetDumperWeaponAttachment, m_attachment, ASSET_TYPE_ATTACHMENT) DUMP_ASSET_POOL(AssetDumperWeaponAttachmentUnique, m_attachment_unique, ASSET_TYPE_ATTACHMENT_UNIQUE) // DUMP_ASSET_POOL(AssetDumperWeaponCamo, m_camo, ASSET_TYPE_WEAPON_CAMO) - // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) + DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) diff --git a/thirdparty/catch2 b/thirdparty/catch2 index dacbf4fd6..caffe79a3 160000 --- a/thirdparty/catch2 +++ b/thirdparty/catch2 @@ -1 +1 @@ -Subproject commit dacbf4fd6c80d726b3d87e77c91bcacdd4fc57c0 +Subproject commit caffe79a3172495f6a4b09de88e81e9aa67b8323 diff --git a/thirdparty/json b/thirdparty/json index 3780b41dd..6eab7a2b1 160000 --- a/thirdparty/json +++ b/thirdparty/json @@ -1 +1 @@ -Subproject commit 3780b41dd070436f3f55327b0a88f27a52e2dfa8 +Subproject commit 6eab7a2b187b10b2494e39c1961750bfd1bda500 diff --git a/thirdparty/zlib b/thirdparty/zlib index 643e17b74..ac8f12c97 160000 --- a/thirdparty/zlib +++ b/thirdparty/zlib @@ -1 +1 @@ -Subproject commit 643e17b7498d12ab8d15565662880579692f769d +Subproject commit ac8f12c97d1afd9bafa9c710f827d40a407d3266