Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[T6] - SndBank Linking and Sound Bank (.sabs/.sabl) Writing #99

Merged
merged 27 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b5dd6df
begin working on SndBank loading from raw
Jan 12, 2024
b10c752
populate sound alias sub lists correctly. allocate memory for loadedA…
Jan 15, 2024
2323b32
finish SndAliasList loading
Jan 24, 2024
a93cb6f
dont comment that
Jan 24, 2024
acd9fa2
reverb and duck loading. cleaned up asset loading with custom csv parser
Jan 25, 2024
a020de6
SoundBankWriter code
Jan 26, 2024
80da882
Merge branch 'Laupetin:main' into main
skiff Jan 26, 2024
f53c895
fix MD5 crypto
Jan 26, 2024
4e8d335
add climits for linux builds
Jan 26, 2024
365502d
more linux build errors
Jan 26, 2024
e2f8892
clang formatting
Jan 26, 2024
7af802f
more linux build errors
Jan 26, 2024
bc1ebfc
.flac extension
Jan 26, 2024
c3590a9
dont build sabl if unable to find sound files
Feb 2, 2024
386f941
add comment
Feb 2, 2024
9254e25
fix loaded sound banks and generating streamed sound banks
Feb 2, 2024
aa2bebe
Merge branch 'Laupetin:main' into main
skiff Feb 7, 2024
42c4068
add flac decoding to correctly add flac sounds to sound banks
Feb 9, 2024
2478a13
code review changes
Feb 9, 2024
bfed3d5
clang format
Feb 9, 2024
54278a5
include memory for linux build
Feb 9, 2024
f7ece10
more linux build fails
Feb 9, 2024
45689a2
chore: make SoundBankEntryInfo a class without constructors
Laupetin Feb 10, 2024
05ce730
chore: small code cleanups
Laupetin Feb 10, 2024
4591787
chore: drop third party lib for reading flac header
Laupetin Feb 10, 2024
4914eb5
chore: fix linux build
Laupetin Feb 10, 2024
f6ee479
fix: not dumping all sound aliases in aliases csv
Laupetin Feb 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Crypto/Crypto.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#include "Crypto.h"

#include "Impl/AlgorithmMD5.h"
#include "Impl/AlgorithmRSA.h"
#include "Impl/AlgorithmSHA1.h"
#include "Impl/AlgorithmSHA256.h"
#include "Impl/AlgorithmSalsa20.h"

std::unique_ptr<IHashFunction> Crypto::CreateMD5()
{
return std::make_unique<AlgorithmMD5>();
}

std::unique_ptr<IHashFunction> Crypto::CreateSHA1()
{
return std::make_unique<AlgorithmSHA1>();
Expand Down
2 changes: 2 additions & 0 deletions src/Crypto/Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class Crypto
RSA_PADDING_PSS,
};

static std::unique_ptr<IHashFunction> CreateMD5();

static std::unique_ptr<IHashFunction> CreateSHA1();
static std::unique_ptr<IHashFunction> CreateSHA256();

Expand Down
64 changes: 64 additions & 0 deletions src/Crypto/Impl/AlgorithmMD5.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "AlgorithmMD5.h"

#include "CryptoLibrary.h"

#include <cstdint>

class AlgorithmMD5::AlgorithmMD5Impl
{
hash_state m_state{};

public:
AlgorithmMD5Impl()
{
CryptoLibrary::Init();

Init();
}

void Init()
{
md5_init(&m_state);
}

void Process(const void* input, const size_t inputSize)
{
md5_process(&m_state, static_cast<const uint8_t*>(input), inputSize);
}

void Finish(void* hashBuffer)
{
md5_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
};

AlgorithmMD5::AlgorithmMD5()
{
m_impl = new AlgorithmMD5Impl();
}

AlgorithmMD5::~AlgorithmMD5()
{
delete m_impl;
m_impl = nullptr;
}

size_t AlgorithmMD5::GetHashSize()
{
return HASH_SIZE;
}

void AlgorithmMD5::Init()
{
m_impl->Init();
}

void AlgorithmMD5::Process(const void* input, const size_t inputSize)
{
m_impl->Process(input, inputSize);
}

void AlgorithmMD5::Finish(void* hashBuffer)
{
m_impl->Finish(hashBuffer);
}
20 changes: 20 additions & 0 deletions src/Crypto/Impl/AlgorithmMD5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once
#include "IHashFunction.h"

class AlgorithmMD5 : public IHashFunction
{
class AlgorithmMD5Impl;
AlgorithmMD5Impl* m_impl;

public:
static const int HASH_SIZE = 16;

AlgorithmMD5();
~AlgorithmMD5() override;

size_t GetHashSize() override;

void Init() override;
void Process(const void* input, size_t inputSize) override;
void Finish(void* hashBuffer) override;
};
3 changes: 3 additions & 0 deletions src/Linker/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "LinkerSearchPaths.h"
#include "ObjContainer/IPak/IPakWriter.h"
#include "ObjContainer/IWD/IWD.h"
#include "ObjContainer/SoundBank/SoundBankWriter.h"
#include "ObjLoading.h"
#include "ObjWriting.h"
#include "SearchPath/SearchPaths.h"
Expand Down Expand Up @@ -419,6 +420,8 @@ class LinkerImpl final : public Linker
SearchPaths& gdtSearchPaths,
SearchPaths& sourceSearchPaths) const
{
SoundBankWriter::OutputPath = fs::path(m_args.GetOutputFolderPathForProject(projectName));

const auto zone = CreateZoneForDefinition(targetName, zoneDefinition, &assetSearchPaths, &gdtSearchPaths, &sourceSearchPaths);
auto result = zone != nullptr;
if (zone)
Expand Down
80 changes: 80 additions & 0 deletions src/ObjCommon/Csv/ParsedCsv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "Csv/ParsedCsv.h"

ParsedCsvRow::ParsedCsvRow(std::unordered_map<std::string, size_t>& headers, std::vector<std::string> row)
: headers(headers),
values(std::move(row))
{
}

std::string ParsedCsvRow::GetValue(const std::string& header, const bool required) const
{
if (this->headers.find(header) == this->headers.end())
{
if (required)
std::cerr << "ERROR: Required column \"" << header << "\" was not found" << std::endl;
else
std::cerr << "WARNING: Expected column \"" << header << "\" was not found" << std::endl;

return {};
}

auto& value = this->values.at(this->headers[header]);
if (required && value.empty())
{
std::cerr << "ERROR: Required column \"" << header << "\" does not have a value" << std::endl;
return {};
}

return value;
}

float ParsedCsvRow::GetValueFloat(const std::string& header, const bool required) const
{
const auto& value = this->GetValue(header, required);
if (!value.empty())
{
std::istringstream ss(value);
float out;
ss >> out;
return out;
}

return {};
}

ParsedCsv::ParsedCsv(const CsvInputStream& inputStream, const bool hasHeaders)
{
std::vector<std::vector<std::string>> csvLines;
std::vector<std::string> currentLine;

while (inputStream.NextRow(currentLine))
{
csvLines.emplace_back(std::move(currentLine));
currentLine = std::vector<std::string>();
}

if (hasHeaders)
{
const auto& headersRow = csvLines[0];
for (auto i = 0u; i < headersRow.size(); i++)
{
this->headers[headersRow[i]] = i;
}
}

for (auto i = hasHeaders ? 1u : 0u; i < csvLines.size(); i++)
{
auto& rowValues = csvLines[i];
this->rows.emplace_back(this->headers, std::move(rowValues));
}
}

size_t ParsedCsv::Size() const
{
return this->rows.size();
}

ParsedCsvRow ParsedCsv::operator[](const size_t index) const
{
return this->rows.at(index);
}
45 changes: 45 additions & 0 deletions src/ObjCommon/Csv/ParsedCsv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "Csv/CsvStream.h"
#include "Utils/ClassUtils.h"

#include <sstream>
#include <unordered_map>

class ParsedCsvRow
{
std::unordered_map<std::string, size_t>& headers;
std::vector<std::string> values;

public:
explicit ParsedCsvRow(std::unordered_map<std::string, size_t>& headers, std::vector<std::string> row);
_NODISCARD std::string GetValue(const std::string& header, bool required = false) const;
_NODISCARD float GetValueFloat(const std::string& header, bool required = false) const;

template<typename T> T GetValueInt(const std::string& header, const bool required = false) const
{
const auto& value = this->GetValue(header, required);
if (!value.empty())
{
std::istringstream ss(value);
long long out;
ss >> out;
return static_cast<T>(out);
}

return {};
}
};

class ParsedCsv
{
std::unordered_map<std::string, size_t> headers;
std::vector<ParsedCsvRow> rows;

public:
explicit ParsedCsv(const CsvInputStream& inputStream, bool hasHeaders = true);

_NODISCARD size_t Size() const;

ParsedCsvRow operator[](size_t index) const;
};
137 changes: 137 additions & 0 deletions src/ObjCommon/Game/T6/SoundConstantsT6.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#pragma once
#include <string>

namespace T6
{
inline const std::string SOUND_GROUPS[]{
"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",
"",
};

inline const std::string SOUND_CURVES[]{
"default",
"defaultmin",
"allon",
"alloff",
"rcurve0",
"rcurve1",
"rcurve2",
"rcurve3",
"rcurve4",
"rcurve5",
"steep",
"sindelay",
"cosdelay",
"sin",
"cos",
"rev60",
"rev65",
"",
};

inline const std::string SOUND_DUCK_GROUPS[]{
"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",
};

inline const std::string SOUND_LIMIT_TYPES[]{
"none",
"oldest",
"reject",
"priority",
};

inline const std::string SOUND_MOVE_TYPES[]{
"none",
"left_player",
"center_player",
"right_player",
"random",
"left_shot",
"center_shot",
"right_shot",
};

inline const std::string SOUND_LOAD_TYPES[]{
"unknown",
"loaded",
"streamed",
"primed",
};

inline const std::string SOUND_BUS_IDS[]{
"bus_reverb",
"bus_fx",
"bus_voice",
"bus_pfutz",
"bus_hdrfx",
"bus_ui",
"bus_reference",
"bus_music",
"bus_movie",
"bus_reference",
"",
};

inline const std::string SOUND_RANDOMIZE_TYPES[]{
"volume",
"pitch",
"variant",
"",
};
} // namespace T6
Loading
Loading