mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
commit
53cde27d7f
@ -6182,7 +6182,43 @@ namespace T6
|
|||||||
SA_LOADED = 0x1,
|
SA_LOADED = 0x1,
|
||||||
SA_STREAMED = 0x2,
|
SA_STREAMED = 0x2,
|
||||||
SA_PRIMED = 0x3,
|
SA_PRIMED = 0x3,
|
||||||
SA_COUNT = 0x4,
|
|
||||||
|
SA_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SndLimitType
|
||||||
|
{
|
||||||
|
SND_LIMIT_NONE = 0x0,
|
||||||
|
SND_LIMIT_OLDEST = 0x1,
|
||||||
|
SND_LIMIT_REJECT = 0x2,
|
||||||
|
SND_LIMIT_PRIORITY = 0x3,
|
||||||
|
|
||||||
|
SND_LIMIT_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SndBus
|
||||||
|
{
|
||||||
|
SND_BUS_REVERB = 0x0,
|
||||||
|
SND_BUS_FX = 0x1,
|
||||||
|
SND_BUS_VOICE = 0x2,
|
||||||
|
SND_BUS_PFUTZ = 0x3,
|
||||||
|
SND_BUS_HDRFX = 0x4,
|
||||||
|
SND_BUS_UI = 0x5,
|
||||||
|
SND_BUS_MUSIC = 0x6,
|
||||||
|
SND_BUS_MOVIE = 0x7,
|
||||||
|
SND_BUS_REFERENCE = 0x8,
|
||||||
|
|
||||||
|
SND_BUS_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SndRandomizeType
|
||||||
|
{
|
||||||
|
SND_RANDOMIZE_INSTANCE = 0x0,
|
||||||
|
SND_RANDOMIZE_ENTITY_VOLUME = 0x1,
|
||||||
|
SND_RANDOMIZE_ENTITY_PITCH = 0x2,
|
||||||
|
SND_RANDOMIZE_ENTITY_VARIANT = 0x4,
|
||||||
|
|
||||||
|
SND_RANDOMIZE_ENTITY_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SndAliasFlags
|
struct SndAliasFlags
|
||||||
@ -6248,16 +6284,16 @@ namespace T6
|
|||||||
int16_t fadeIn;
|
int16_t fadeIn;
|
||||||
int16_t fadeOut;
|
int16_t fadeOut;
|
||||||
int16_t dopplerScale;
|
int16_t dopplerScale;
|
||||||
char minPriorityThreshold;
|
uint8_t minPriorityThreshold;
|
||||||
char maxPriorityThreshold;
|
uint8_t maxPriorityThreshold;
|
||||||
char probability;
|
uint8_t probability;
|
||||||
char occlusionLevel;
|
uint8_t occlusionLevel;
|
||||||
char minPriority;
|
uint8_t minPriority;
|
||||||
char maxPriority;
|
uint8_t maxPriority;
|
||||||
char pan;
|
uint8_t pan;
|
||||||
char limitCount;
|
uint8_t limitCount;
|
||||||
char entityLimitCount;
|
uint8_t entityLimitCount;
|
||||||
char duckGroup;
|
uint8_t duckGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef __zonecodegenerator
|
#ifndef __zonecodegenerator
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace T6
|
namespace T6
|
||||||
{
|
{
|
||||||
inline const std::string SOUND_GROUPS[]{
|
// From SndDriverGlobals
|
||||||
|
inline constexpr const char* SOUND_GROUPS[]{
|
||||||
|
// clang-format off
|
||||||
"grp_reference",
|
"grp_reference",
|
||||||
"grp_master",
|
"grp_master",
|
||||||
"grp_wpn_lfe",
|
"grp_wpn_lfe",
|
||||||
@ -30,10 +35,11 @@ namespace T6
|
|||||||
"grp_air",
|
"grp_air",
|
||||||
"grp_bink",
|
"grp_bink",
|
||||||
"grp_announcer",
|
"grp_announcer",
|
||||||
"",
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const std::string SOUND_CURVES[]{
|
// From SndDriverGlobals
|
||||||
|
inline constexpr const char* SOUND_CURVES[]{
|
||||||
"default",
|
"default",
|
||||||
"defaultmin",
|
"defaultmin",
|
||||||
"allon",
|
"allon",
|
||||||
@ -51,10 +57,10 @@ namespace T6
|
|||||||
"cos",
|
"cos",
|
||||||
"rev60",
|
"rev60",
|
||||||
"rev65",
|
"rev65",
|
||||||
"",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const std::string SOUND_DUCK_GROUPS[]{
|
// From SndDriverGlobals
|
||||||
|
inline constexpr const char* SOUND_DUCK_GROUPS[]{
|
||||||
"snp_alerts_gameplay",
|
"snp_alerts_gameplay",
|
||||||
"snp_ambience",
|
"snp_ambience",
|
||||||
"snp_claw",
|
"snp_claw",
|
||||||
@ -89,14 +95,16 @@ namespace T6
|
|||||||
"snp_x3",
|
"snp_x3",
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const std::string SOUND_LIMIT_TYPES[]{
|
inline constexpr const char* SOUND_LIMIT_TYPES[]{
|
||||||
"none",
|
"none",
|
||||||
"oldest",
|
"oldest",
|
||||||
"reject",
|
"reject",
|
||||||
"priority",
|
"priority",
|
||||||
};
|
};
|
||||||
|
static_assert(std::extent_v<decltype(SOUND_LIMIT_TYPES)> == SND_LIMIT_COUNT);
|
||||||
|
|
||||||
inline const std::string SOUND_MOVE_TYPES[]{
|
// From executable
|
||||||
|
inline constexpr const char* SOUND_MOVE_TYPES[]{
|
||||||
"none",
|
"none",
|
||||||
"left_player",
|
"left_player",
|
||||||
"center_player",
|
"center_player",
|
||||||
@ -107,31 +115,32 @@ namespace T6
|
|||||||
"right_shot",
|
"right_shot",
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const std::string SOUND_LOAD_TYPES[]{
|
inline constexpr const char* SOUND_LOAD_TYPES[]{
|
||||||
"unknown",
|
"unknown",
|
||||||
"loaded",
|
"loaded",
|
||||||
"streamed",
|
"streamed",
|
||||||
"primed",
|
"primed",
|
||||||
};
|
};
|
||||||
|
static_assert(std::extent_v<decltype(SOUND_LOAD_TYPES)> == SA_COUNT);
|
||||||
|
|
||||||
inline const std::string SOUND_BUS_IDS[]{
|
inline constexpr const char* SOUND_BUS_IDS[]{
|
||||||
"bus_reverb",
|
"bus_reverb",
|
||||||
"bus_fx",
|
"bus_fx",
|
||||||
"bus_voice",
|
"bus_voice",
|
||||||
"bus_pfutz",
|
"bus_pfutz",
|
||||||
"bus_hdrfx",
|
"bus_hdrfx",
|
||||||
"bus_ui",
|
"bus_ui",
|
||||||
"bus_reference",
|
|
||||||
"bus_music",
|
"bus_music",
|
||||||
"bus_movie",
|
"bus_movie",
|
||||||
"bus_reference",
|
"bus_reference",
|
||||||
"",
|
|
||||||
};
|
};
|
||||||
|
static_assert(std::extent_v<decltype(SOUND_BUS_IDS)> == SND_BUS_COUNT);
|
||||||
|
|
||||||
inline const std::string SOUND_RANDOMIZE_TYPES[]{
|
// From executable
|
||||||
|
inline constexpr const char* SOUND_RANDOMIZE_TYPES[]{
|
||||||
|
"",
|
||||||
"volume",
|
"volume",
|
||||||
"pitch",
|
"pitch",
|
||||||
"variant",
|
"variant",
|
||||||
"",
|
|
||||||
};
|
};
|
||||||
} // namespace T6
|
} // namespace T6
|
||||||
|
@ -72,7 +72,7 @@ bool AssetLoaderSoundBank::CanLoadFromRaw() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetValueIndex(const std::string& value, const std::string* lookupTable, size_t len)
|
size_t GetValueIndex(const std::string& value, const char* const* lookupTable, const size_t len)
|
||||||
{
|
{
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
return 0;
|
return 0;
|
||||||
@ -141,33 +141,33 @@ bool LoadSoundAlias(MemoryManager* memory, SndAlias* alias, const ParsedCsvRow&
|
|||||||
|
|
||||||
alias->duck = Common::SND_HashName(row.GetValue("duck").data());
|
alias->duck = Common::SND_HashName(row.GetValue("duck").data());
|
||||||
|
|
||||||
alias->volMin = row.GetValueInt<uint16_t>("vol_min");
|
alias->volMin = row.GetValueInt<decltype(alias->volMin)>("vol_min");
|
||||||
alias->volMax = row.GetValueInt<uint16_t>("vol_max");
|
alias->volMax = row.GetValueInt<decltype(alias->volMax)>("vol_max");
|
||||||
alias->distMin = row.GetValueInt<uint16_t>("dist_min");
|
alias->distMin = row.GetValueInt<decltype(alias->distMin)>("dist_min");
|
||||||
alias->distMax = row.GetValueInt<uint16_t>("dist_max");
|
alias->distMax = row.GetValueInt<decltype(alias->distMax)>("dist_max");
|
||||||
alias->distReverbMax = row.GetValueInt<uint16_t>("dist_reverb_max");
|
alias->distReverbMax = row.GetValueInt<decltype(alias->distReverbMax)>("dist_reverb_max");
|
||||||
alias->limitCount = row.GetValueInt<uint8_t>("limit_count");
|
alias->limitCount = row.GetValueInt<decltype(alias->limitCount)>("limit_count");
|
||||||
alias->entityLimitCount = row.GetValueInt<uint8_t>("entity_limit_count");
|
alias->entityLimitCount = row.GetValueInt<decltype(alias->entityLimitCount)>("entity_limit_count");
|
||||||
alias->pitchMin = row.GetValueInt<uint16_t>("pitch_min");
|
alias->pitchMin = row.GetValueInt<decltype(alias->pitchMin)>("pitch_min");
|
||||||
alias->pitchMax = row.GetValueInt<uint16_t>("pitch_max");
|
alias->pitchMax = row.GetValueInt<decltype(alias->pitchMax)>("pitch_max");
|
||||||
alias->minPriority = row.GetValueInt<uint8_t>("min_priority");
|
alias->minPriority = row.GetValueInt<decltype(alias->minPriority)>("min_priority");
|
||||||
alias->maxPriority = row.GetValueInt<uint8_t>("max_priority");
|
alias->maxPriority = row.GetValueInt<decltype(alias->maxPriority)>("max_priority");
|
||||||
alias->minPriorityThreshold = row.GetValueInt<uint8_t>("min_priority_threshold");
|
alias->minPriorityThreshold = row.GetValueInt<decltype(alias->minPriorityThreshold)>("min_priority_threshold");
|
||||||
alias->maxPriorityThreshold = row.GetValueInt<uint8_t>("max_priority_threshold");
|
alias->maxPriorityThreshold = row.GetValueInt<decltype(alias->maxPriorityThreshold)>("max_priority_threshold");
|
||||||
alias->probability = row.GetValueInt<uint8_t>("probability");
|
alias->probability = row.GetValueInt<decltype(alias->probability)>("probability");
|
||||||
alias->startDelay = row.GetValueInt<uint16_t>("start_delay");
|
alias->startDelay = row.GetValueInt<decltype(alias->startDelay)>("start_delay");
|
||||||
alias->reverbSend = row.GetValueInt<uint16_t>("reverb_send");
|
alias->reverbSend = row.GetValueInt<decltype(alias->reverbSend)>("reverb_send");
|
||||||
alias->centerSend = row.GetValueInt<uint16_t>("center_send");
|
alias->centerSend = row.GetValueInt<decltype(alias->centerSend)>("center_send");
|
||||||
alias->envelopMin = row.GetValueInt<uint16_t>("envelop_min");
|
alias->envelopMin = row.GetValueInt<decltype(alias->envelopMin)>("envelop_min");
|
||||||
alias->envelopMax = row.GetValueInt<uint16_t>("envelop_max");
|
alias->envelopMax = row.GetValueInt<decltype(alias->envelopMax)>("envelop_max");
|
||||||
alias->envelopPercentage = row.GetValueInt<uint16_t>("envelop_percentage");
|
alias->envelopPercentage = row.GetValueInt<decltype(alias->envelopPercentage)>("envelop_percentage");
|
||||||
alias->occlusionLevel = row.GetValueInt<uint8_t>("occlusion_level");
|
alias->occlusionLevel = row.GetValueInt<decltype(alias->occlusionLevel)>("occlusion_level");
|
||||||
alias->fluxTime = row.GetValueInt<uint16_t>("move_time");
|
alias->fluxTime = row.GetValueInt<decltype(alias->fluxTime)>("move_time");
|
||||||
alias->futzPatch = row.GetValueInt<unsigned int>("futz");
|
alias->futzPatch = row.GetValueInt<decltype(alias->futzPatch)>("futz");
|
||||||
alias->contextType = row.GetValueInt<unsigned int>("context_type");
|
alias->contextType = row.GetValueInt<decltype(alias->contextType)>("context_type");
|
||||||
alias->contextValue = row.GetValueInt<unsigned int>("context_value");
|
alias->contextValue = row.GetValueInt<decltype(alias->contextValue)>("context_value");
|
||||||
alias->fadeIn = row.GetValueInt<int16_t>("fade_in");
|
alias->fadeIn = row.GetValueInt<decltype(alias->fadeIn)>("fade_in");
|
||||||
alias->fadeOut = row.GetValueInt<int16_t>("fade_out");
|
alias->fadeOut = row.GetValueInt<decltype(alias->fadeOut)>("fade_out");
|
||||||
|
|
||||||
alias->flags.looping = row.GetValue("loop") == "looping";
|
alias->flags.looping = row.GetValue("loop") == "looping";
|
||||||
alias->flags.panType = row.GetValue("pan") == "3d";
|
alias->flags.panType = row.GetValue("pan") == "3d";
|
||||||
@ -179,7 +179,8 @@ bool LoadSoundAlias(MemoryManager* memory, SndAlias* alias, const ParsedCsvRow&
|
|||||||
alias->flags.pauseable = row.GetValue("pause") == "yes";
|
alias->flags.pauseable = row.GetValue("pause") == "yes";
|
||||||
alias->flags.stopOnDeath = row.GetValue("stop_on_death") == "yes";
|
alias->flags.stopOnDeath = row.GetValue("stop_on_death") == "yes";
|
||||||
|
|
||||||
alias->duckGroup = static_cast<char>(GetValueIndex(row.GetValue("duck_group"), SOUND_DUCK_GROUPS, std::extent_v<decltype(SOUND_DUCK_GROUPS)>));
|
alias->duckGroup =
|
||||||
|
static_cast<decltype(alias->duckGroup)>(GetValueIndex(row.GetValue("duck_group"), SOUND_DUCK_GROUPS, std::extent_v<decltype(SOUND_DUCK_GROUPS)>));
|
||||||
alias->flags.volumeGroup = GetValueIndex(row.GetValue("group"), SOUND_GROUPS, std::extent_v<decltype(SOUND_GROUPS)>);
|
alias->flags.volumeGroup = GetValueIndex(row.GetValue("group"), SOUND_GROUPS, std::extent_v<decltype(SOUND_GROUPS)>);
|
||||||
alias->flags.fluxType = GetValueIndex(row.GetValue("move_type"), SOUND_MOVE_TYPES, std::extent_v<decltype(SOUND_MOVE_TYPES)>);
|
alias->flags.fluxType = GetValueIndex(row.GetValue("move_type"), SOUND_MOVE_TYPES, std::extent_v<decltype(SOUND_MOVE_TYPES)>);
|
||||||
alias->flags.loadType = GetValueIndex(row.GetValue("type"), SOUND_LOAD_TYPES, std::extent_v<decltype(SOUND_LOAD_TYPES)>);
|
alias->flags.loadType = GetValueIndex(row.GetValue("type"), SOUND_LOAD_TYPES, std::extent_v<decltype(SOUND_LOAD_TYPES)>);
|
||||||
|
@ -5,12 +5,16 @@
|
|||||||
#include "Sound/FlacDecoder.h"
|
#include "Sound/FlacDecoder.h"
|
||||||
#include "Sound/WavTypes.h"
|
#include "Sound/WavTypes.h"
|
||||||
#include "Utils/FileUtils.h"
|
#include "Utils/FileUtils.h"
|
||||||
|
#include "Utils/StringUtils.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
std::unordered_map<unsigned int, unsigned char> INDEX_FOR_FRAMERATE{
|
std::unordered_map<unsigned int, unsigned char> INDEX_FOR_FRAMERATE{
|
||||||
{8000, 0},
|
{8000, 0},
|
||||||
{12000, 1},
|
{12000, 1},
|
||||||
@ -32,6 +36,30 @@ class SoundBankWriterImpl : public SoundBankWriter
|
|||||||
|
|
||||||
inline static const std::string PAD_DATA = std::string(16, '\x00');
|
inline static const std::string PAD_DATA = std::string(16, '\x00');
|
||||||
|
|
||||||
|
class SoundBankEntryInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SoundBankEntryInfo()
|
||||||
|
: m_sound_id(0u),
|
||||||
|
m_looping(false),
|
||||||
|
m_streamed(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundBankEntryInfo(std::string filePath, const unsigned int soundId, const bool looping, const bool streamed)
|
||||||
|
: m_file_path(std::move(filePath)),
|
||||||
|
m_sound_id(soundId),
|
||||||
|
m_looping(looping),
|
||||||
|
m_streamed(streamed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string m_file_path;
|
||||||
|
unsigned int m_sound_id;
|
||||||
|
bool m_looping;
|
||||||
|
bool m_streamed;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SoundBankWriterImpl(std::string fileName, std::ostream& stream, ISearchPath* assetSearchPath)
|
explicit SoundBankWriterImpl(std::string fileName, std::ostream& stream, ISearchPath* assetSearchPath)
|
||||||
: m_file_name(std::move(fileName)),
|
: m_file_name(std::move(fileName)),
|
||||||
@ -118,6 +146,100 @@ public:
|
|||||||
Write(&header, sizeof(header));
|
Write(&header, sizeof(header));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LoadWavFile(const SearchPathOpenFile& file, const SoundBankEntryInfo& sound, std::unique_ptr<char[]>& soundData, size_t& soundSize)
|
||||||
|
{
|
||||||
|
WavHeader header{};
|
||||||
|
file.m_stream->read(reinterpret_cast<char*>(&header), sizeof(WavHeader));
|
||||||
|
|
||||||
|
soundSize = static_cast<size_t>(file.m_length - sizeof(WavHeader));
|
||||||
|
const auto frameCount = soundSize / (header.formatChunk.nChannels * (header.formatChunk.wBitsPerSample / 8));
|
||||||
|
const auto frameRateIndex = INDEX_FOR_FRAMERATE[header.formatChunk.nSamplesPerSec];
|
||||||
|
|
||||||
|
SoundAssetBankEntry entry{
|
||||||
|
sound.m_sound_id,
|
||||||
|
soundSize,
|
||||||
|
static_cast<size_t>(m_current_offset),
|
||||||
|
frameCount,
|
||||||
|
frameRateIndex,
|
||||||
|
static_cast<unsigned char>(header.formatChunk.nChannels),
|
||||||
|
sound.m_looping,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
m_entries.push_back(entry);
|
||||||
|
|
||||||
|
soundData = std::make_unique<char[]>(soundSize);
|
||||||
|
file.m_stream->read(soundData.get(), soundSize);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadFlacFile(
|
||||||
|
const SearchPathOpenFile& file, const std::string& filePath, const SoundBankEntryInfo& sound, std::unique_ptr<char[]>& soundData, size_t& soundSize)
|
||||||
|
{
|
||||||
|
soundSize = static_cast<size_t>(file.m_length);
|
||||||
|
|
||||||
|
soundData = std::make_unique<char[]>(soundSize);
|
||||||
|
file.m_stream->read(soundData.get(), soundSize);
|
||||||
|
|
||||||
|
flac::FlacMetaData metaData;
|
||||||
|
if (flac::GetFlacMetaData(soundData.get(), soundSize, metaData))
|
||||||
|
{
|
||||||
|
const auto frameRateIndex = INDEX_FOR_FRAMERATE[metaData.m_sample_rate];
|
||||||
|
SoundAssetBankEntry entry{
|
||||||
|
sound.m_sound_id,
|
||||||
|
soundSize,
|
||||||
|
static_cast<size_t>(m_current_offset),
|
||||||
|
static_cast<unsigned>(metaData.m_total_samples),
|
||||||
|
frameRateIndex,
|
||||||
|
metaData.m_number_of_channels,
|
||||||
|
sound.m_looping,
|
||||||
|
8,
|
||||||
|
};
|
||||||
|
|
||||||
|
m_entries.push_back(entry);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << std::format("Unable to decode .flac file for sound {}\n", filePath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadFileByExtension(const std::string& filePath, const SoundBankEntryInfo& sound, std::unique_ptr<char[]>& soundData, size_t& soundSize)
|
||||||
|
{
|
||||||
|
auto extension = fs::path(filePath).extension().string();
|
||||||
|
utils::MakeStringLowerCase(extension);
|
||||||
|
if (extension.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto file = m_asset_search_path->Open(filePath);
|
||||||
|
if (!file.IsOpen())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (extension == ".wav")
|
||||||
|
return LoadWavFile(file, sound, soundData, soundSize);
|
||||||
|
|
||||||
|
if (extension == ".flac")
|
||||||
|
return LoadFlacFile(file, filePath, sound, soundData, soundSize);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuessFilenameAndLoadFile(const std::string& filePath, const SoundBankEntryInfo& sound, std::unique_ptr<char[]>& soundData, size_t& soundSize)
|
||||||
|
{
|
||||||
|
fs::path pathWithExtension = fs::path(filePath).replace_extension(".wav");
|
||||||
|
auto file = m_asset_search_path->Open(pathWithExtension.string());
|
||||||
|
if (file.IsOpen())
|
||||||
|
return LoadWavFile(file, sound, soundData, soundSize);
|
||||||
|
|
||||||
|
pathWithExtension = fs::path(filePath).replace_extension(".flac");
|
||||||
|
file = m_asset_search_path->Open(pathWithExtension.string());
|
||||||
|
if (file.IsOpen())
|
||||||
|
return LoadFlacFile(file, pathWithExtension.string(), sound, soundData, soundSize);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool WriteEntries()
|
bool WriteEntries()
|
||||||
{
|
{
|
||||||
GoTo(DATA_OFFSET);
|
GoTo(DATA_OFFSET);
|
||||||
@ -125,87 +247,23 @@ public:
|
|||||||
for (auto& sound : m_sounds)
|
for (auto& sound : m_sounds)
|
||||||
{
|
{
|
||||||
const auto& soundFilePath = sound.m_file_path;
|
const auto& soundFilePath = sound.m_file_path;
|
||||||
const auto soundId = sound.m_sound_id;
|
|
||||||
|
|
||||||
size_t soundSize;
|
size_t soundSize;
|
||||||
std::unique_ptr<char[]> soundData;
|
std::unique_ptr<char[]> soundData;
|
||||||
|
|
||||||
// try to find a wav file for the sound path
|
if (!LoadFileByExtension(soundFilePath, sound, soundData, soundSize) && !GuessFilenameAndLoadFile(soundFilePath, sound, soundData, soundSize))
|
||||||
const auto wavFile = m_asset_search_path->Open(soundFilePath + ".wav");
|
|
||||||
if (wavFile.IsOpen())
|
|
||||||
{
|
{
|
||||||
WavHeader header{};
|
std::cerr << std::format("Unable to find a compatible file for sound {}\n", soundFilePath);
|
||||||
wavFile.m_stream->read(reinterpret_cast<char*>(&header), sizeof(WavHeader));
|
return false;
|
||||||
|
|
||||||
soundSize = static_cast<size_t>(wavFile.m_length - sizeof(WavHeader));
|
|
||||||
const auto frameCount = soundSize / (header.formatChunk.nChannels * (header.formatChunk.wBitsPerSample / 8));
|
|
||||||
const auto frameRateIndex = INDEX_FOR_FRAMERATE[header.formatChunk.nSamplesPerSec];
|
|
||||||
|
|
||||||
SoundAssetBankEntry entry{
|
|
||||||
soundId,
|
|
||||||
soundSize,
|
|
||||||
static_cast<size_t>(m_current_offset),
|
|
||||||
frameCount,
|
|
||||||
frameRateIndex,
|
|
||||||
static_cast<unsigned char>(header.formatChunk.nChannels),
|
|
||||||
sound.m_looping,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
m_entries.push_back(entry);
|
|
||||||
|
|
||||||
soundData = std::make_unique<char[]>(soundSize);
|
|
||||||
wavFile.m_stream->read(soundData.get(), soundSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if there is no wav file, try flac file
|
|
||||||
const auto flacFile = m_asset_search_path->Open(soundFilePath + ".flac");
|
|
||||||
if (flacFile.IsOpen())
|
|
||||||
{
|
|
||||||
soundSize = static_cast<size_t>(flacFile.m_length);
|
|
||||||
|
|
||||||
soundData = std::make_unique<char[]>(soundSize);
|
|
||||||
flacFile.m_stream->read(soundData.get(), soundSize);
|
|
||||||
|
|
||||||
flac::FlacMetaData metaData;
|
|
||||||
if (flac::GetFlacMetaData(soundData.get(), soundSize, metaData))
|
|
||||||
{
|
|
||||||
const auto frameRateIndex = INDEX_FOR_FRAMERATE[metaData.m_sample_rate];
|
|
||||||
SoundAssetBankEntry entry{
|
|
||||||
soundId,
|
|
||||||
soundSize,
|
|
||||||
static_cast<size_t>(m_current_offset),
|
|
||||||
static_cast<unsigned>(metaData.m_total_samples),
|
|
||||||
frameRateIndex,
|
|
||||||
metaData.m_number_of_channels,
|
|
||||||
sound.m_looping,
|
|
||||||
8,
|
|
||||||
};
|
|
||||||
|
|
||||||
m_entries.push_back(entry);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Unable to decode .flac file for sound " << soundFilePath << "\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Unable to find a compatible file for sound " << soundFilePath << "\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto lastEntry = m_entries.rbegin();
|
const auto lastEntry = m_entries.rbegin();
|
||||||
if (!sound.m_streamed && lastEntry->frameRateIndex != 6)
|
if (!sound.m_streamed && lastEntry->frameRateIndex != 6)
|
||||||
{
|
{
|
||||||
std::cout << "WARNING: Loaded sound \"" << soundFilePath
|
std::cout << std::format("WARNING: Loaded sound \"{}\" should have a framerate of 48000 but doesn't. This sound may not work on all games!\n",
|
||||||
<< "\" should have a framerate of 48000 but doesn't. This sound may not work on all games!\n";
|
soundFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate checksum
|
|
||||||
SoundAssetBankChecksum checksum{};
|
SoundAssetBankChecksum checksum{};
|
||||||
|
|
||||||
const auto md5Crypt = Crypto::CreateMD5();
|
const auto md5Crypt = Crypto::CreateMD5();
|
||||||
@ -278,30 +336,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class SoundBankEntryInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SoundBankEntryInfo()
|
|
||||||
: m_sound_id(0u),
|
|
||||||
m_looping(false),
|
|
||||||
m_streamed(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundBankEntryInfo(std::string filePath, const unsigned int soundId, const bool looping, const bool streamed)
|
|
||||||
: m_file_path(std::move(filePath)),
|
|
||||||
m_sound_id(soundId),
|
|
||||||
m_looping(looping),
|
|
||||||
m_streamed(streamed)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_file_path;
|
|
||||||
unsigned int m_sound_id;
|
|
||||||
bool m_looping;
|
|
||||||
bool m_streamed;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string m_file_name;
|
std::string m_file_name;
|
||||||
std::ostream& m_stream;
|
std::ostream& m_stream;
|
||||||
ISearchPath* m_asset_search_path;
|
ISearchPath* m_asset_search_path;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ namespace
|
|||||||
{
|
{
|
||||||
std::unordered_map<unsigned int, std::string> result;
|
std::unordered_map<unsigned int, std::string> result;
|
||||||
for (auto i = 0u; i < std::extent_v<decltype(SOUND_CURVES)>; i++)
|
for (auto i = 0u; i < std::extent_v<decltype(SOUND_CURVES)>; i++)
|
||||||
result.emplace(T6::Common::SND_HashName(SOUND_CURVES[i].data()), SOUND_CURVES[i]);
|
result.emplace(T6::Common::SND_HashName(SOUND_CURVES[i]), SOUND_CURVES[i]);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +196,7 @@ class AssetDumperSndBank::Internal
|
|||||||
stream.NextRow();
|
stream.NextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* FindNameForDuck(unsigned int id, const SndBank* bank)
|
static const char* FindNameForDuck(const unsigned int id, const SndBank* bank)
|
||||||
{
|
{
|
||||||
for (auto i = 0u; i < bank->duckCount; i++)
|
for (auto i = 0u; i < bank->duckCount; i++)
|
||||||
{
|
{
|
||||||
@ -208,13 +209,30 @@ class AssetDumperSndBank::Internal
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias, const SndBank* bank)
|
static const char* ExtensionForSndFormat(const snd_asset_format format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case SND_ASSET_FORMAT_PCMS16:
|
||||||
|
return ".wav";
|
||||||
|
|
||||||
|
case SND_ASSET_FORMAT_FLAC:
|
||||||
|
return ".flac";
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias, const std::optional<snd_asset_format> maybeFormat, const SndBank* bank)
|
||||||
{
|
{
|
||||||
// name
|
// name
|
||||||
stream.WriteColumn(alias->name);
|
stream.WriteColumn(alias->name);
|
||||||
|
|
||||||
// file
|
// file
|
||||||
stream.WriteColumn(alias->assetFileName ? alias->assetFileName : "");
|
const auto* extension = maybeFormat ? ExtensionForSndFormat(*maybeFormat) : "";
|
||||||
|
stream.WriteColumn(alias->assetFileName ? std::format("{}{}", alias->assetFileName, extension) : "");
|
||||||
|
|
||||||
// template
|
// template
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
@ -255,7 +273,7 @@ class AssetDumperSndBank::Internal
|
|||||||
// volume_min_falloff_curve
|
// volume_min_falloff_curve
|
||||||
stream.WriteColumn(SOUND_CURVES[alias->flags.volumeMinFalloffCurve]);
|
stream.WriteColumn(SOUND_CURVES[alias->flags.volumeMinFalloffCurve]);
|
||||||
|
|
||||||
// reverb_min_falloff_curve"
|
// reverb_min_falloff_curve
|
||||||
stream.WriteColumn(SOUND_CURVES[alias->flags.reverbMinFalloffCurve]);
|
stream.WriteColumn(SOUND_CURVES[alias->flags.reverbMinFalloffCurve]);
|
||||||
|
|
||||||
// limit_count
|
// limit_count
|
||||||
@ -303,103 +321,103 @@ class AssetDumperSndBank::Internal
|
|||||||
// randomize_type
|
// randomize_type
|
||||||
stream.WriteColumn(SOUND_RANDOMIZE_TYPES[std::min(alias->flags.randomizeType, 3u)]);
|
stream.WriteColumn(SOUND_RANDOMIZE_TYPES[std::min(alias->flags.randomizeType, 3u)]);
|
||||||
|
|
||||||
// probability",
|
// probability
|
||||||
stream.WriteColumn(std::to_string(alias->probability));
|
stream.WriteColumn(std::to_string(alias->probability));
|
||||||
|
|
||||||
// start_delay",
|
// start_delay
|
||||||
stream.WriteColumn(std::to_string(alias->startDelay));
|
stream.WriteColumn(std::to_string(alias->startDelay));
|
||||||
|
|
||||||
// reverb_send",
|
// reverb_send
|
||||||
stream.WriteColumn(std::to_string(alias->reverbSend));
|
stream.WriteColumn(std::to_string(alias->reverbSend));
|
||||||
|
|
||||||
// duck",
|
// duck
|
||||||
stream.WriteColumn(FindNameForDuck(alias->duck, bank));
|
stream.WriteColumn(FindNameForDuck(alias->duck, bank));
|
||||||
|
|
||||||
// duck_group",
|
// duck_group
|
||||||
stream.WriteColumn(SOUND_DUCK_GROUPS[alias->duckGroup]);
|
stream.WriteColumn(SOUND_DUCK_GROUPS[alias->duckGroup]);
|
||||||
|
|
||||||
// pan",
|
// pan
|
||||||
stream.WriteColumn(alias->flags.panType == SA_PAN_2D ? "2d" : "3d");
|
stream.WriteColumn(alias->flags.panType == SA_PAN_2D ? "2d" : "3d");
|
||||||
|
|
||||||
// center_send",
|
// center_send
|
||||||
stream.WriteColumn(std::to_string(alias->centerSend));
|
stream.WriteColumn(std::to_string(alias->centerSend));
|
||||||
|
|
||||||
// envelop_min",
|
// envelop_min
|
||||||
stream.WriteColumn(std::to_string(alias->envelopMin));
|
stream.WriteColumn(std::to_string(alias->envelopMin));
|
||||||
|
|
||||||
// envelop_max",
|
// envelop_max
|
||||||
stream.WriteColumn(std::to_string(alias->envelopMax));
|
stream.WriteColumn(std::to_string(alias->envelopMax));
|
||||||
|
|
||||||
// envelop_percentage",
|
// envelop_percentage
|
||||||
stream.WriteColumn(std::to_string(alias->envelopPercentage));
|
stream.WriteColumn(std::to_string(alias->envelopPercentage));
|
||||||
|
|
||||||
// occlusion_level",
|
// occlusion_level
|
||||||
stream.WriteColumn(std::to_string(alias->occlusionLevel));
|
stream.WriteColumn(std::to_string(alias->occlusionLevel));
|
||||||
|
|
||||||
// occlusion_wet_dry",
|
// occlusion_wet_dry
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
|
|
||||||
// is_big",
|
// is_big
|
||||||
stream.WriteColumn(alias->flags.isBig ? "yes" : "no");
|
stream.WriteColumn(alias->flags.isBig ? "yes" : "no");
|
||||||
|
|
||||||
// distance_lpf"
|
// distance_lpf
|
||||||
stream.WriteColumn(alias->flags.distanceLpf ? "yes" : "no");
|
stream.WriteColumn(alias->flags.distanceLpf ? "yes" : "no");
|
||||||
|
|
||||||
// move_type",
|
// move_type
|
||||||
stream.WriteColumn(SOUND_MOVE_TYPES[alias->flags.fluxType]);
|
stream.WriteColumn(SOUND_MOVE_TYPES[alias->flags.fluxType]);
|
||||||
|
|
||||||
// move_time",
|
// move_time
|
||||||
stream.WriteColumn(std::to_string(alias->fluxTime));
|
stream.WriteColumn(std::to_string(alias->fluxTime));
|
||||||
|
|
||||||
// real_delay",
|
// real_delay
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
|
|
||||||
// subtitle",
|
// subtitle
|
||||||
stream.WriteColumn((alias->subtitle && *alias->subtitle) ? alias->subtitle : "");
|
stream.WriteColumn((alias->subtitle && *alias->subtitle) ? alias->subtitle : "");
|
||||||
|
|
||||||
// mature",
|
// mature
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
|
|
||||||
// doppler",
|
// doppler
|
||||||
stream.WriteColumn(alias->flags.doppler ? "yes" : "no");
|
stream.WriteColumn(alias->flags.doppler ? "yes" : "no");
|
||||||
|
|
||||||
// futz",
|
// futz
|
||||||
stream.WriteColumn(std::to_string(alias->futzPatch));
|
stream.WriteColumn(std::to_string(alias->futzPatch));
|
||||||
|
|
||||||
// context_type",
|
// context_type
|
||||||
stream.WriteColumn(std::to_string(alias->contextType));
|
stream.WriteColumn(std::to_string(alias->contextType));
|
||||||
|
|
||||||
// context_value",
|
// context_value
|
||||||
stream.WriteColumn(std::to_string(alias->contextValue));
|
stream.WriteColumn(std::to_string(alias->contextValue));
|
||||||
|
|
||||||
// compression",
|
// compression
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
|
|
||||||
// timescale",
|
// timescale
|
||||||
stream.WriteColumn(alias->flags.timescale ? "yes" : "no");
|
stream.WriteColumn(alias->flags.timescale ? "yes" : "no");
|
||||||
|
|
||||||
// music",
|
// music
|
||||||
stream.WriteColumn(alias->flags.isMusic ? "yes" : "no");
|
stream.WriteColumn(alias->flags.isMusic ? "yes" : "no");
|
||||||
|
|
||||||
// fade_in",
|
// fade_in
|
||||||
stream.WriteColumn(std::to_string(alias->fadeIn));
|
stream.WriteColumn(std::to_string(alias->fadeIn));
|
||||||
|
|
||||||
// fade_out",
|
// fade_out
|
||||||
stream.WriteColumn(std::to_string(alias->fadeOut));
|
stream.WriteColumn(std::to_string(alias->fadeOut));
|
||||||
|
|
||||||
// pc_format",
|
// pc_format
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
|
|
||||||
// pause",
|
// pause
|
||||||
stream.WriteColumn(alias->flags.pauseable ? "yes" : "no");
|
stream.WriteColumn(alias->flags.pauseable ? "yes" : "no");
|
||||||
|
|
||||||
// stop_on_death",
|
// stop_on_death
|
||||||
stream.WriteColumn(alias->flags.stopOnDeath ? "yes" : "no");
|
stream.WriteColumn(alias->flags.stopOnDeath ? "yes" : "no");
|
||||||
|
|
||||||
// bus",
|
// bus
|
||||||
stream.WriteColumn(SOUND_BUS_IDS[alias->flags.busType]);
|
stream.WriteColumn(SOUND_BUS_IDS[alias->flags.busType]);
|
||||||
|
|
||||||
// snapshot",
|
// snapshot
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +438,7 @@ class AssetDumperSndBank::Internal
|
|||||||
const auto outFile = OpenAssetOutputFile(assetFileName, ".wav");
|
const auto outFile = OpenAssetOutputFile(assetFileName, ".wav");
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open sound output file: \"" << assetFileName << "\"\n";
|
std::cerr << std::format("Failed to open sound output file: \"{}\"\n", assetFileName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,7 +465,7 @@ class AssetDumperSndBank::Internal
|
|||||||
const auto outFile = OpenAssetOutputFile(assetFileName, extension);
|
const auto outFile = OpenAssetOutputFile(assetFileName, extension);
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open sound output file: \"" << assetFileName << "\"\n";
|
std::cerr << std::format("Failed to open sound output file: \"{}\"\n", assetFileName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,7 +478,7 @@ class AssetDumperSndBank::Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpSndAlias(const SndAlias& alias) const
|
std::optional<snd_asset_format> DumpSndAlias(const SndAlias& alias) const
|
||||||
{
|
{
|
||||||
const auto soundFile = FindSoundDataInSoundBanks(alias.assetId);
|
const auto soundFile = FindSoundDataInSoundBanks(alias.assetId);
|
||||||
if (soundFile.IsOpen())
|
if (soundFile.IsOpen())
|
||||||
@ -484,29 +502,30 @@ class AssetDumperSndBank::Internal
|
|||||||
case SND_ASSET_FORMAT_WMA:
|
case SND_ASSET_FORMAT_WMA:
|
||||||
case SND_ASSET_FORMAT_WIIUADPCM:
|
case SND_ASSET_FORMAT_WIIUADPCM:
|
||||||
case SND_ASSET_FORMAT_MPC:
|
case SND_ASSET_FORMAT_MPC:
|
||||||
std::cerr << "Cannot dump sound (Unsupported sound format " << format << "): \"" << alias.assetFileName << "\"\n";
|
std::cerr << std::format("Cannot dump sound (Unknown sound format {}): \"{}\"\n", static_cast<unsigned>(format), alias.assetFileName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
std::cerr << "Cannot dump sound (Unknown sound format " << format << "): \"" << alias.assetFileName << "\"\n";
|
std::cerr << std::format("Cannot dump sound (Unknown sound format {}): \"{}\"\n", static_cast<unsigned>(format), alias.assetFileName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return format;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
std::cerr << std::format("Could not find data for sound \"{}\"\n", alias.assetFileName);
|
||||||
std::cerr << "Could not find data for sound \"" << alias.assetFileName << "\"\n";
|
return {};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpSndBankAliases(const SndBank* sndBank) const
|
void DumpSndBankAliases(const SndBank* sndBank) const
|
||||||
{
|
{
|
||||||
std::unordered_set<unsigned> dumpedAssets;
|
std::unordered_map<unsigned int, std::optional<snd_asset_format>> dumpedAssets;
|
||||||
|
|
||||||
const auto outFile = OpenAssetOutputFile("soundbank/" + std::string(sndBank->name) + ".aliases", ".csv");
|
const auto outFile = OpenAssetOutputFile(std::format("soundbank/{}.aliases", sndBank->name), ".csv");
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open sound alias output file: \"" << sndBank->name << "\"\n";
|
std::cerr << std::format("Failed to open sound alias output file: \"\"\n", sndBank->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,15 +539,24 @@ class AssetDumperSndBank::Internal
|
|||||||
for (auto j = 0; j < aliasList.count; j++)
|
for (auto j = 0; j < aliasList.count; j++)
|
||||||
{
|
{
|
||||||
const auto& alias = aliasList.head[j];
|
const auto& alias = aliasList.head[j];
|
||||||
|
std::optional<snd_asset_format> maybeFormat;
|
||||||
|
|
||||||
WriteAliasToFile(csvStream, &alias, sndBank);
|
if (alias.assetId && alias.assetFileName)
|
||||||
csvStream.NextRow();
|
|
||||||
|
|
||||||
if (alias.assetId && alias.assetFileName && dumpedAssets.find(alias.assetId) == dumpedAssets.end())
|
|
||||||
{
|
{
|
||||||
DumpSndAlias(alias);
|
const auto previouslyDeterminedFormat = dumpedAssets.find(alias.assetId);
|
||||||
dumpedAssets.emplace(alias.assetId);
|
if (previouslyDeterminedFormat == dumpedAssets.end())
|
||||||
|
{
|
||||||
|
maybeFormat = DumpSndAlias(alias);
|
||||||
|
dumpedAssets[alias.assetId] = maybeFormat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maybeFormat = previouslyDeterminedFormat->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WriteAliasToFile(csvStream, &alias, maybeFormat, sndBank);
|
||||||
|
csvStream.NextRow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -536,14 +564,12 @@ class AssetDumperSndBank::Internal
|
|||||||
void DumpSoundRadverb(const SndBank* sndBank) const
|
void DumpSoundRadverb(const SndBank* sndBank) const
|
||||||
{
|
{
|
||||||
if (sndBank->radverbCount <= 0)
|
if (sndBank->radverbCount <= 0)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const auto outFile = OpenAssetOutputFile("soundbank/" + std::string(sndBank->name) + ".reverbs", ".csv");
|
const auto outFile = OpenAssetOutputFile(std::format("soundbank/{}.reverbs", sndBank->name), ".csv");
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open sound reverb output file: \"" << sndBank->name << "\"\n";
|
std::cerr << std::format("Failed to open sound reverb output file: \"{}\"\n", sndBank->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,14 +603,12 @@ class AssetDumperSndBank::Internal
|
|||||||
void DumpSoundDucks(const SndBank* sndBank) const
|
void DumpSoundDucks(const SndBank* sndBank) const
|
||||||
{
|
{
|
||||||
if (sndBank->duckCount <= 0)
|
if (sndBank->duckCount <= 0)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const auto outFile = OpenAssetOutputFile("soundbank/" + std::string(sndBank->name) + ".ducklist", ".csv");
|
const auto outFile = OpenAssetOutputFile(std::format("soundbank/{}.ducklist", sndBank->name), ".csv");
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open sound reverb output file: \"" << sndBank->name << "\"\n";
|
std::cerr << std::format("Failed to open sound reverb output file: \"{}\"\n", sndBank->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,10 +622,10 @@ class AssetDumperSndBank::Internal
|
|||||||
csvStream.WriteColumn(duck.name);
|
csvStream.WriteColumn(duck.name);
|
||||||
csvStream.NextRow();
|
csvStream.NextRow();
|
||||||
|
|
||||||
const auto duckFile = OpenAssetOutputFile("soundbank/ducks/" + std::string(duck.name), ".duk");
|
const auto duckFile = OpenAssetOutputFile(std::format("soundbank/ducks/{}", duck.name), ".duk");
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open sound duck output file: \"" << duck.name << "\"\n";
|
std::cerr << std::format("Failed to open sound duck output file: \"{}\"\n", duck.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,12 +652,12 @@ class AssetDumperSndBank::Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto values = std::vector<nlohmann::json>{};
|
auto values = std::vector<nlohmann::json>{};
|
||||||
for (auto i = 0u; i < 32u; i++)
|
for (auto j = 0u; j < 32u; j++)
|
||||||
{
|
{
|
||||||
values.push_back({
|
values.push_back({
|
||||||
{"duckGroup", SOUND_DUCK_GROUPS[i]},
|
{"duckGroup", SOUND_DUCK_GROUPS[j]},
|
||||||
{"attenuation", duck.attenuation[i] },
|
{"attenuation", duck.attenuation[j] },
|
||||||
{"filter", duck.filter[i] }
|
{"filter", duck.filter[j] }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user