mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
Introduce LoaderSDT for SDT/RAW audio files
This commit is contained in:
parent
4df20821e7
commit
727de03eb5
@ -29,6 +29,8 @@ SET(RWLIB_SOURCES
|
|||||||
"source/loaders/RWBinaryStream.hpp"
|
"source/loaders/RWBinaryStream.hpp"
|
||||||
"source/loaders/LoaderDFF.hpp"
|
"source/loaders/LoaderDFF.hpp"
|
||||||
"source/loaders/LoaderDFF.cpp"
|
"source/loaders/LoaderDFF.cpp"
|
||||||
|
"source/loaders/LoaderSDT.hpp"
|
||||||
|
"source/loaders/LoaderSDT.cpp"
|
||||||
"source/loaders/LoaderTXD.hpp"
|
"source/loaders/LoaderTXD.hpp"
|
||||||
"source/loaders/LoaderTXD.cpp"
|
"source/loaders/LoaderTXD.cpp"
|
||||||
|
|
||||||
|
156
rwlib/source/loaders/LoaderSDT.cpp
Normal file
156
rwlib/source/loaders/LoaderSDT.cpp
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include <loaders/LoaderSDT.hpp>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
LoaderSDT::LoaderSDT()
|
||||||
|
: m_version(GTAIIIVC)
|
||||||
|
, m_assetCount(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char chunkId[4];
|
||||||
|
uint32_t chunkSize;
|
||||||
|
char format[4];
|
||||||
|
struct {
|
||||||
|
char id[4];
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t audioFormat;
|
||||||
|
uint16_t numChannels;
|
||||||
|
uint32_t sampleRate;
|
||||||
|
uint32_t byteRate;
|
||||||
|
uint16_t blockAlign;
|
||||||
|
uint16_t bitsPerSample;
|
||||||
|
} fmt;
|
||||||
|
struct {
|
||||||
|
char id[4];
|
||||||
|
uint32_t size;
|
||||||
|
} data;
|
||||||
|
} WaveHeader;
|
||||||
|
|
||||||
|
bool LoaderSDT::load(const std::string& filename)
|
||||||
|
{
|
||||||
|
auto baseName = filename;
|
||||||
|
auto sdtName = baseName + ".SDT";
|
||||||
|
auto rawName = baseName + ".RAW";
|
||||||
|
|
||||||
|
FILE* fp = fopen(sdtName.c_str(), "rb");
|
||||||
|
if (fp) {
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
unsigned long fileSize = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
m_assetCount = fileSize / 20;
|
||||||
|
m_assets.resize(m_assetCount);
|
||||||
|
|
||||||
|
if ((m_assetCount = fread(&m_assets[0], sizeof(LoaderSDTFile), m_assetCount, fp)) != fileSize / 20) {
|
||||||
|
m_assets.resize(m_assetCount);
|
||||||
|
std::cout << "Error reading records in SDT archive" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
m_archive = rawName;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the information of a asset in the examining archive
|
||||||
|
bool LoaderSDT::findAssetInfo(size_t index, LoaderSDTFile& out)
|
||||||
|
{
|
||||||
|
if (index < m_assets.size()) {
|
||||||
|
out = m_assets[index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* LoaderSDT::loadToMemory(size_t index, bool asWave)
|
||||||
|
{
|
||||||
|
LoaderSDTFile assetInfo;
|
||||||
|
bool found = findAssetInfo(index, assetInfo);
|
||||||
|
|
||||||
|
if(!found) {
|
||||||
|
std::cerr << "Asset " << std::to_string(index) << " not found!" << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rawName = m_archive;
|
||||||
|
|
||||||
|
FILE* fp = fopen(rawName.c_str(), "rb");
|
||||||
|
if (fp) {
|
||||||
|
char* raw_data;
|
||||||
|
char* sample_data;
|
||||||
|
if (asWave) {
|
||||||
|
raw_data = new char[sizeof(WaveHeader) + assetInfo.size];
|
||||||
|
|
||||||
|
WaveHeader* header = reinterpret_cast<WaveHeader*>(raw_data);
|
||||||
|
memcpy(header->chunkId, "RIFF", 4);
|
||||||
|
header->chunkSize = sizeof(WaveHeader) - 8 + assetInfo.size;
|
||||||
|
memcpy(header->format, "WAVE", 4);
|
||||||
|
memcpy(header->fmt.id, "fmt ", 4);
|
||||||
|
header->fmt.size = sizeof(WaveHeader::fmt) - 8;
|
||||||
|
header->fmt.audioFormat = 1; // PCM
|
||||||
|
header->fmt.numChannels = 1; // Mono
|
||||||
|
header->fmt.sampleRate = assetInfo.sampleRate;
|
||||||
|
header->fmt.byteRate = assetInfo.sampleRate * 2;
|
||||||
|
header->fmt.blockAlign = 2;
|
||||||
|
header->fmt.bitsPerSample = 16;
|
||||||
|
memcpy(header->data.id, "data", 4);
|
||||||
|
header->data.size = assetInfo.size;
|
||||||
|
|
||||||
|
sample_data = raw_data + sizeof(WaveHeader);
|
||||||
|
} else {
|
||||||
|
raw_data = new char[assetInfo.size];
|
||||||
|
sample_data = raw_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, assetInfo.offset, SEEK_SET);
|
||||||
|
if (fread(sample_data, 1, assetInfo.size, fp) != assetInfo.size) {
|
||||||
|
std::cerr << "Error reading asset " << std::to_string(index) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return raw_data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes the contents of assetname to filename
|
||||||
|
bool LoaderSDT::saveAsset(size_t index, const std::string& filename, bool asWave)
|
||||||
|
{
|
||||||
|
char* raw_data = loadToMemory(index, asWave);
|
||||||
|
if(!raw_data)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FILE* dumpFile = fopen(filename.c_str(), "wb");
|
||||||
|
if(dumpFile) {
|
||||||
|
LoaderSDTFile asset;
|
||||||
|
if(findAssetInfo(index, asset)) {
|
||||||
|
fwrite(raw_data, 1, asset.size + (asWave ? sizeof(WaveHeader) : 0), dumpFile);
|
||||||
|
printf("=> SDT: Saved %zu to disk with filename %s\n", index, filename.c_str());
|
||||||
|
}
|
||||||
|
fclose(dumpFile);
|
||||||
|
|
||||||
|
delete[] raw_data;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
delete[] raw_data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the information of an asset by its index
|
||||||
|
const LoaderSDTFile &LoaderSDT::getAssetInfoByIndex(size_t index) const
|
||||||
|
{
|
||||||
|
return m_assets[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t LoaderSDT::getAssetCount() const
|
||||||
|
{
|
||||||
|
return m_assetCount;
|
||||||
|
}
|
67
rwlib/source/loaders/LoaderSDT.hpp
Normal file
67
rwlib/source/loaders/LoaderSDT.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _LOADERSDT_HPP_
|
||||||
|
#define _LOADERSDT_HPP_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/// \brief Points to one file within the archive
|
||||||
|
class LoaderSDTFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint32_t offset; // offset of audio file in sfx.raw
|
||||||
|
uint32_t size; // size of audio file in bytes
|
||||||
|
uint32_t sampleRate; // the speed of audio
|
||||||
|
uint32_t loopStart; /// loop start, where looping would begin relative to audio file's position, 0 for beginning of audio file
|
||||||
|
uint32_t loopEnd; /// where looping would end relative to audio file's position, -1 for end of audio file
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\class LoaderSDT
|
||||||
|
\brief Parses the structure of GTA .SDT archives and loads the files in it
|
||||||
|
*/
|
||||||
|
class LoaderSDT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Multiple versions of .SDT files
|
||||||
|
enum Versions
|
||||||
|
{
|
||||||
|
GTA2,
|
||||||
|
GTAIIIVC ///< GTA III and GTA VC archives -- only this one is implemented
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Construct
|
||||||
|
LoaderSDT();
|
||||||
|
|
||||||
|
/// Load the structure of the archive
|
||||||
|
/// Omit the extension in filename
|
||||||
|
bool load(const std::string& filename);
|
||||||
|
|
||||||
|
/// Load a file from the archive to memory and pass a pointer to it
|
||||||
|
/// Warning: Please delete[] the memory in the end.
|
||||||
|
/// Warning: Returns NULL (0) if by any reason it can't load the file
|
||||||
|
char* loadToMemory(size_t index, bool asWave = true);
|
||||||
|
|
||||||
|
/// Writes the contents of index to filename
|
||||||
|
bool saveAsset(size_t index, const std::string& filename, bool asWave = true);
|
||||||
|
|
||||||
|
/// Get the information of an asset in the examining archive
|
||||||
|
bool findAssetInfo(size_t index, LoaderSDTFile& out);
|
||||||
|
|
||||||
|
/// Get the information of an asset by its index
|
||||||
|
const LoaderSDTFile &getAssetInfoByIndex(size_t index) const;
|
||||||
|
|
||||||
|
/// Returns the number of asset files in the archive
|
||||||
|
uint32_t getAssetCount() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Versions m_version; ///< Version of this SDT archive
|
||||||
|
uint32_t m_assetCount; ///< Number of assets in the current archive
|
||||||
|
std::string m_archive; ///< Path to the archive being used (no extension)
|
||||||
|
|
||||||
|
std::vector<LoaderSDTFile> m_assets; ///< Asset info of the archive
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LoaderSDT_h__
|
Loading…
Reference in New Issue
Block a user