mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
Merge pull request #274 from Jbleezy/main
Dump and load correct volume and pitch values for T6 sound aliases
This commit is contained in:
commit
ff98b53625
@ -8,7 +8,9 @@
|
|||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
#include "Utils/StringUtils.h"
|
#include "Utils/StringUtils.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <format>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
@ -113,7 +115,43 @@ unsigned int GetAliasSubListCount(const unsigned int startRow, const ParsedCsv&
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadSoundAlias(MemoryManager* memory, SndAlias* alias, const ParsedCsvRow& row)
|
float DbsplToLinear(const float dbsplValue)
|
||||||
|
{
|
||||||
|
return std::pow(10.0f, (dbsplValue - 100.0f) / 20.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CentToHertz(const float cents)
|
||||||
|
{
|
||||||
|
return std::pow(2.0f, cents / 1200.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadColumnVolumeDbspl(const float dbsplValue, const char* colName, const unsigned rowIndex, uint16_t& value)
|
||||||
|
{
|
||||||
|
if (dbsplValue < 0.0f || dbsplValue > 100.0f)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Invalid value for row {} col '{}' - {} [0.0, 100.0]\n", rowIndex + 1, colName, dbsplValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = static_cast<uint16_t>(DbsplToLinear(dbsplValue) * static_cast<float>(std::numeric_limits<uint16_t>::max()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadColumnPitchCents(const float centValue, const char* colName, const unsigned rowIndex, uint16_t& value)
|
||||||
|
{
|
||||||
|
if (centValue < -2400.0f || centValue > 1200.0f)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Invalid value for row {} col '{}' - {} [-2400.0, 1200.0]\n", rowIndex + 1, colName, centValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = static_cast<uint16_t>(CentToHertz(centValue) * static_cast<float>(std::numeric_limits<uint16_t>::max()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadSoundAlias(MemoryManager* memory, SndAlias* alias, const ParsedCsvRow& row, const unsigned int rowNum)
|
||||||
{
|
{
|
||||||
memset(alias, 0, sizeof(SndAlias));
|
memset(alias, 0, sizeof(SndAlias));
|
||||||
|
|
||||||
@ -141,26 +179,42 @@ 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<decltype(alias->volMin)>("vol_min");
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("vol_min"), "vol_min", rowNum, alias->volMin))
|
||||||
alias->volMax = row.GetValueInt<decltype(alias->volMax)>("vol_max");
|
return false;
|
||||||
|
|
||||||
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("vol_max"), "vol_max", rowNum, alias->volMax))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("pitch_min"), "pitch_min", rowNum, alias->pitchMin))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("pitch_max"), "pitch_max", rowNum, alias->pitchMax))
|
||||||
|
return false;
|
||||||
|
|
||||||
alias->distMin = row.GetValueInt<decltype(alias->distMin)>("dist_min");
|
alias->distMin = row.GetValueInt<decltype(alias->distMin)>("dist_min");
|
||||||
alias->distMax = row.GetValueInt<decltype(alias->distMax)>("dist_max");
|
alias->distMax = row.GetValueInt<decltype(alias->distMax)>("dist_max");
|
||||||
alias->distReverbMax = row.GetValueInt<decltype(alias->distReverbMax)>("dist_reverb_max");
|
alias->distReverbMax = row.GetValueInt<decltype(alias->distReverbMax)>("dist_reverb_max");
|
||||||
alias->limitCount = row.GetValueInt<decltype(alias->limitCount)>("limit_count");
|
alias->limitCount = row.GetValueInt<decltype(alias->limitCount)>("limit_count");
|
||||||
alias->entityLimitCount = row.GetValueInt<decltype(alias->entityLimitCount)>("entity_limit_count");
|
alias->entityLimitCount = row.GetValueInt<decltype(alias->entityLimitCount)>("entity_limit_count");
|
||||||
alias->pitchMin = row.GetValueInt<decltype(alias->pitchMin)>("pitch_min");
|
|
||||||
alias->pitchMax = row.GetValueInt<decltype(alias->pitchMax)>("pitch_max");
|
|
||||||
alias->minPriority = row.GetValueInt<decltype(alias->minPriority)>("min_priority");
|
alias->minPriority = row.GetValueInt<decltype(alias->minPriority)>("min_priority");
|
||||||
alias->maxPriority = row.GetValueInt<decltype(alias->maxPriority)>("max_priority");
|
alias->maxPriority = row.GetValueInt<decltype(alias->maxPriority)>("max_priority");
|
||||||
alias->minPriorityThreshold = row.GetValueInt<decltype(alias->minPriorityThreshold)>("min_priority_threshold");
|
alias->minPriorityThreshold = row.GetValueInt<decltype(alias->minPriorityThreshold)>("min_priority_threshold");
|
||||||
alias->maxPriorityThreshold = row.GetValueInt<decltype(alias->maxPriorityThreshold)>("max_priority_threshold");
|
alias->maxPriorityThreshold = row.GetValueInt<decltype(alias->maxPriorityThreshold)>("max_priority_threshold");
|
||||||
alias->probability = row.GetValueInt<decltype(alias->probability)>("probability");
|
alias->probability = row.GetValueInt<decltype(alias->probability)>("probability");
|
||||||
alias->startDelay = row.GetValueInt<decltype(alias->startDelay)>("start_delay");
|
alias->startDelay = row.GetValueInt<decltype(alias->startDelay)>("start_delay");
|
||||||
alias->reverbSend = row.GetValueInt<decltype(alias->reverbSend)>("reverb_send");
|
|
||||||
alias->centerSend = row.GetValueInt<decltype(alias->centerSend)>("center_send");
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("reverb_send"), "reverb_send", rowNum, alias->reverbSend))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("center_send"), "center_send", rowNum, alias->centerSend))
|
||||||
|
return false;
|
||||||
|
|
||||||
alias->envelopMin = row.GetValueInt<decltype(alias->envelopMin)>("envelop_min");
|
alias->envelopMin = row.GetValueInt<decltype(alias->envelopMin)>("envelop_min");
|
||||||
alias->envelopMax = row.GetValueInt<decltype(alias->envelopMax)>("envelop_max");
|
alias->envelopMax = row.GetValueInt<decltype(alias->envelopMax)>("envelop_max");
|
||||||
alias->envelopPercentage = row.GetValueInt<decltype(alias->envelopPercentage)>("envelop_percentage");
|
|
||||||
|
if (!ReadColumnVolumeDbspl(row.GetValueFloat("envelop_percentage"), "envelop_percentage", rowNum, alias->envelopPercentage))
|
||||||
|
return false;
|
||||||
|
|
||||||
alias->occlusionLevel = row.GetValueInt<decltype(alias->occlusionLevel)>("occlusion_level");
|
alias->occlusionLevel = row.GetValueInt<decltype(alias->occlusionLevel)>("occlusion_level");
|
||||||
alias->fluxTime = row.GetValueInt<decltype(alias->fluxTime)>("move_time");
|
alias->fluxTime = row.GetValueInt<decltype(alias->fluxTime)>("move_time");
|
||||||
alias->futzPatch = row.GetValueInt<decltype(alias->futzPatch)>("futz");
|
alias->futzPatch = row.GetValueInt<decltype(alias->futzPatch)>("futz");
|
||||||
@ -292,7 +346,7 @@ bool LoadSoundAliasList(
|
|||||||
// list are next to each other in the file
|
// list are next to each other in the file
|
||||||
for (auto i = 0u; i < subListCount; i++)
|
for (auto i = 0u; i < subListCount; i++)
|
||||||
{
|
{
|
||||||
if (!LoadSoundAlias(memory, &sndBank->alias[listIndex].head[i], aliasCsv[row]))
|
if (!LoadSoundAlias(memory, &sndBank->alias[listIndex].head[i], aliasCsv[row], row))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if this asset is loaded instead of stream, increment the loaded count for later
|
// if this asset is loaded instead of stream, increment the loaded count for later
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "Sound/WavWriter.h"
|
#include "Sound/WavWriter.h"
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -225,6 +226,36 @@ class AssetDumperSndBank::Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float LinearToDbspl(float linear)
|
||||||
|
{
|
||||||
|
linear = std::max(linear, 0.0000152879f);
|
||||||
|
|
||||||
|
const auto db = 20.0f * std::log10(linear);
|
||||||
|
if (db > -95.0f)
|
||||||
|
return db + 100.0f;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float HertzToCents(const float hertz)
|
||||||
|
{
|
||||||
|
return 1200.0f * std::log2(hertz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteColumnVolumeLinear(CsvOutputStream& stream, const uint16_t value)
|
||||||
|
{
|
||||||
|
const auto linear = static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||||
|
const auto dbSpl = std::clamp(LinearToDbspl(linear), 0.0f, 100.0f);
|
||||||
|
stream.WriteColumn(std::format("{:.3g}", dbSpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteColumnPitchHertz(CsvOutputStream& stream, const uint16_t value)
|
||||||
|
{
|
||||||
|
const auto hertz = static_cast<float>(value) / static_cast<float>(std::numeric_limits<uint16_t>::max());
|
||||||
|
const auto cents = std::clamp(HertzToCents(hertz), -2400.0f, 1200.0f);
|
||||||
|
stream.WriteColumn(std::format("{:.4g}", cents));
|
||||||
|
}
|
||||||
|
|
||||||
static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias, const std::optional<snd_asset_format> maybeFormat, const SndBank* bank)
|
static void WriteAliasToFile(CsvOutputStream& stream, const SndAlias* alias, const std::optional<snd_asset_format> maybeFormat, const SndBank* bank)
|
||||||
{
|
{
|
||||||
// name
|
// name
|
||||||
@ -247,10 +278,10 @@ class AssetDumperSndBank::Internal
|
|||||||
stream.WriteColumn(SOUND_GROUPS[alias->flags.volumeGroup]);
|
stream.WriteColumn(SOUND_GROUPS[alias->flags.volumeGroup]);
|
||||||
|
|
||||||
// vol_min
|
// vol_min
|
||||||
stream.WriteColumn(std::to_string(alias->volMin));
|
WriteColumnVolumeLinear(stream, alias->volMin);
|
||||||
|
|
||||||
// vol_max
|
// vol_max
|
||||||
stream.WriteColumn(std::to_string(alias->volMax));
|
WriteColumnVolumeLinear(stream, alias->volMax);
|
||||||
|
|
||||||
// team_vol_mod
|
// team_vol_mod
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
@ -289,10 +320,10 @@ class AssetDumperSndBank::Internal
|
|||||||
stream.WriteColumn(SOUND_LIMIT_TYPES[alias->flags.entityLimitType]);
|
stream.WriteColumn(SOUND_LIMIT_TYPES[alias->flags.entityLimitType]);
|
||||||
|
|
||||||
// pitch_min
|
// pitch_min
|
||||||
stream.WriteColumn(std::to_string(alias->pitchMin));
|
WriteColumnPitchHertz(stream, alias->pitchMin);
|
||||||
|
|
||||||
// pitch_max
|
// pitch_max
|
||||||
stream.WriteColumn(std::to_string(alias->pitchMax));
|
WriteColumnPitchHertz(stream, alias->pitchMax);
|
||||||
|
|
||||||
// team_pitch_mod
|
// team_pitch_mod
|
||||||
stream.WriteColumn("");
|
stream.WriteColumn("");
|
||||||
@ -328,7 +359,7 @@ class AssetDumperSndBank::Internal
|
|||||||
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));
|
WriteColumnVolumeLinear(stream, alias->reverbSend);
|
||||||
|
|
||||||
// duck
|
// duck
|
||||||
stream.WriteColumn(FindNameForDuck(alias->duck, bank));
|
stream.WriteColumn(FindNameForDuck(alias->duck, bank));
|
||||||
@ -340,7 +371,7 @@ class AssetDumperSndBank::Internal
|
|||||||
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));
|
WriteColumnVolumeLinear(stream, alias->centerSend);
|
||||||
|
|
||||||
// envelop_min
|
// envelop_min
|
||||||
stream.WriteColumn(std::to_string(alias->envelopMin));
|
stream.WriteColumn(std::to_string(alias->envelopMin));
|
||||||
@ -349,7 +380,7 @@ class AssetDumperSndBank::Internal
|
|||||||
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));
|
WriteColumnVolumeLinear(stream, alias->envelopPercentage);
|
||||||
|
|
||||||
// occlusion_level
|
// occlusion_level
|
||||||
stream.WriteColumn(std::to_string(alias->occlusionLevel));
|
stream.WriteColumn(std::to_string(alias->occlusionLevel));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user