mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
Dump T6 sound PCM data as wav
This commit is contained in:
parent
8c2bb09b28
commit
51899d4a69
@ -38,8 +38,8 @@ struct SoundAssetBankEntry
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
unsigned int frameCount;
|
||||
char frameRateIndex;
|
||||
char channelCount;
|
||||
char looping;
|
||||
char format;
|
||||
unsigned char frameRateIndex;
|
||||
unsigned char channelCount;
|
||||
unsigned char looping;
|
||||
unsigned char format;
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "AssetDumperLoadedSound.h"
|
||||
|
||||
#include "Sound/WavTypes.h"
|
||||
#include "Sound/WavWriter.h"
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
@ -11,43 +12,16 @@ bool AssetDumperLoadedSound::ShouldDump(XAssetInfo<LoadedSound>* asset)
|
||||
|
||||
void AssetDumperLoadedSound::DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream)
|
||||
{
|
||||
const auto riffMasterChunkSize = sizeof(WAV_CHUNK_ID_RIFF)
|
||||
+ sizeof(uint32_t)
|
||||
+ sizeof(WAV_WAVE_ID)
|
||||
+ sizeof(WavChunkHeader)
|
||||
+ sizeof(WavFormatChunkPcm)
|
||||
+ sizeof(WavChunkHeader)
|
||||
+ sizeof(asset->sound.info.data_len);
|
||||
const WavWriter writer(stream);
|
||||
|
||||
stream.write(reinterpret_cast<const char*>(&WAV_CHUNK_ID_RIFF), sizeof(WAV_CHUNK_ID_RIFF));
|
||||
stream.write(reinterpret_cast<const char*>(&riffMasterChunkSize), sizeof(riffMasterChunkSize));
|
||||
stream.write(reinterpret_cast<const char*>(&WAV_WAVE_ID), sizeof(WAV_WAVE_ID));
|
||||
|
||||
const WavChunkHeader formatChunkHeader
|
||||
{
|
||||
WAV_CHUNK_ID_FMT,
|
||||
sizeof(WavFormatChunkPcm)
|
||||
const WavMetaData metaData{
|
||||
static_cast<unsigned>(asset->sound.info.channels),
|
||||
static_cast<unsigned>(asset->sound.info.rate),
|
||||
static_cast<unsigned>(asset->sound.info.bits)
|
||||
};
|
||||
stream.write(reinterpret_cast<const char*>(&formatChunkHeader), sizeof(formatChunkHeader));
|
||||
|
||||
WavFormatChunkPcm formatChunk
|
||||
{
|
||||
WavFormat::PCM,
|
||||
static_cast<uint16_t>(asset->sound.info.channels),
|
||||
asset->sound.info.rate,
|
||||
asset->sound.info.rate * asset->sound.info.channels * asset->sound.info.bits / 8,
|
||||
static_cast<uint16_t>(asset->sound.info.block_size),
|
||||
static_cast<uint16_t>(asset->sound.info.bits)
|
||||
};
|
||||
stream.write(reinterpret_cast<const char*>(&formatChunk), sizeof(formatChunk));
|
||||
|
||||
const WavChunkHeader dataChunkHeader
|
||||
{
|
||||
WAV_CHUNK_ID_DATA,
|
||||
asset->sound.info.data_len
|
||||
};
|
||||
stream.write(reinterpret_cast<const char*>(&dataChunkHeader), sizeof(dataChunkHeader));
|
||||
stream.write(asset->sound.data, asset->sound.info.data_len);
|
||||
writer.WritePcmHeader(metaData, asset->sound.info.data_len);
|
||||
writer.WritePcmData(asset->sound.data, asset->sound.info.data_len);
|
||||
}
|
||||
|
||||
void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo<LoadedSound>* asset)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Csv/CsvStream.h"
|
||||
#include "ObjContainer/SoundBank/SoundBank.h"
|
||||
#include "Sound/WavWriter.h"
|
||||
|
||||
using namespace T6;
|
||||
namespace fs = std::filesystem;
|
||||
@ -85,6 +86,19 @@ namespace
|
||||
"raw/",
|
||||
"devraw/",
|
||||
};
|
||||
|
||||
constexpr size_t FRAME_RATE_FOR_INDEX[]
|
||||
{
|
||||
8000,
|
||||
12000,
|
||||
16000,
|
||||
24000,
|
||||
32000,
|
||||
44100,
|
||||
48000,
|
||||
96000,
|
||||
192000
|
||||
};
|
||||
}
|
||||
|
||||
class AssetDumperSndBank::Internal
|
||||
@ -258,6 +272,37 @@ class AssetDumperSndBank::Internal
|
||||
return {};
|
||||
}
|
||||
|
||||
void DumpSoundFilePcm(const char* assetFileName, const SoundBankEntryInputStream& soundFile, const unsigned bitsPerSample) const
|
||||
{
|
||||
const auto outFile = OpenAssetOutputFile(assetFileName, ".wav");
|
||||
if (!outFile)
|
||||
{
|
||||
std::cerr << "Failed to open sound output file: \"" << assetFileName << "\"\n";
|
||||
return;
|
||||
}
|
||||
|
||||
const WavWriter writer(*outFile);
|
||||
|
||||
if (soundFile.m_entry.frameRateIndex >= std::extent_v<decltype(FRAME_RATE_FOR_INDEX)>)
|
||||
return;
|
||||
|
||||
const WavMetaData metaData{
|
||||
soundFile.m_entry.channelCount,
|
||||
FRAME_RATE_FOR_INDEX[soundFile.m_entry.frameRateIndex],
|
||||
bitsPerSample
|
||||
};
|
||||
|
||||
writer.WritePcmHeader(metaData, soundFile.m_entry.size);
|
||||
|
||||
while (!soundFile.m_stream->eof())
|
||||
{
|
||||
char buffer[2048];
|
||||
soundFile.m_stream->read(buffer, sizeof(buffer));
|
||||
const auto readSize = soundFile.m_stream->gcount();
|
||||
outFile->write(buffer, readSize);
|
||||
}
|
||||
}
|
||||
|
||||
void DumpSoundFilePassthrough(const char* assetFileName, const SoundBankEntryInputStream& soundFile, const std::string& extension) const
|
||||
{
|
||||
const auto outFile = OpenAssetOutputFile(assetFileName, extension);
|
||||
@ -284,15 +329,14 @@ class AssetDumperSndBank::Internal
|
||||
const auto format = static_cast<snd_asset_format>(soundFile.m_entry.format);
|
||||
switch (format)
|
||||
{
|
||||
case SND_ASSET_FORMAT_MP3:
|
||||
DumpSoundFilePassthrough(alias.assetFileName, soundFile, ".mp3");
|
||||
case SND_ASSET_FORMAT_PCMS16:
|
||||
DumpSoundFilePcm(alias.assetFileName, soundFile, 16u);
|
||||
break;
|
||||
|
||||
case SND_ASSET_FORMAT_FLAC:
|
||||
DumpSoundFilePassthrough(alias.assetFileName, soundFile, ".flac");
|
||||
break;
|
||||
|
||||
case SND_ASSET_FORMAT_PCMS16:
|
||||
case SND_ASSET_FORMAT_PCMS24:
|
||||
case SND_ASSET_FORMAT_PCMS32:
|
||||
case SND_ASSET_FORMAT_IEEE:
|
||||
|
53
src/ObjWriting/Sound/WavWriter.cpp
Normal file
53
src/ObjWriting/Sound/WavWriter.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "WavWriter.h"
|
||||
|
||||
#include "Sound/WavTypes.h"
|
||||
|
||||
WavWriter::WavWriter(std::ostream& stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
void WavWriter::WritePcmHeader(const WavMetaData& metaData, const size_t dataLen) const
|
||||
{
|
||||
constexpr auto riffMasterChunkSize = sizeof(WAV_CHUNK_ID_RIFF)
|
||||
+ sizeof(uint32_t)
|
||||
+ sizeof(WAV_WAVE_ID)
|
||||
+ sizeof(WavChunkHeader)
|
||||
+ sizeof(WavFormatChunkPcm)
|
||||
+ sizeof(WavChunkHeader)
|
||||
+ sizeof(dataLen);
|
||||
|
||||
m_stream.write(reinterpret_cast<const char*>(&WAV_CHUNK_ID_RIFF), sizeof(WAV_CHUNK_ID_RIFF));
|
||||
m_stream.write(reinterpret_cast<const char*>(&riffMasterChunkSize), sizeof(riffMasterChunkSize));
|
||||
m_stream.write(reinterpret_cast<const char*>(&WAV_WAVE_ID), sizeof(WAV_WAVE_ID));
|
||||
|
||||
constexpr WavChunkHeader formatChunkHeader
|
||||
{
|
||||
WAV_CHUNK_ID_FMT,
|
||||
sizeof(WavFormatChunkPcm)
|
||||
};
|
||||
m_stream.write(reinterpret_cast<const char*>(&formatChunkHeader), sizeof(formatChunkHeader));
|
||||
|
||||
const WavFormatChunkPcm formatChunk
|
||||
{
|
||||
WavFormat::PCM,
|
||||
static_cast<uint16_t>(metaData.channelCount),
|
||||
metaData.samplesPerSec,
|
||||
metaData.samplesPerSec * metaData.channelCount * metaData.bitsPerSample / 8,
|
||||
static_cast<uint16_t>(metaData.channelCount * (metaData.bitsPerSample / 8)),
|
||||
static_cast<uint16_t>(metaData.bitsPerSample)
|
||||
};
|
||||
m_stream.write(reinterpret_cast<const char*>(&formatChunk), sizeof(formatChunk));
|
||||
|
||||
const WavChunkHeader dataChunkHeader
|
||||
{
|
||||
WAV_CHUNK_ID_DATA,
|
||||
dataLen
|
||||
};
|
||||
m_stream.write(reinterpret_cast<const char*>(&dataChunkHeader), sizeof(dataChunkHeader));
|
||||
}
|
||||
|
||||
void WavWriter::WritePcmData(const void* data, const size_t dataLen) const
|
||||
{
|
||||
m_stream.write(static_cast<const char*>(data), dataLen);
|
||||
}
|
21
src/ObjWriting/Sound/WavWriter.h
Normal file
21
src/ObjWriting/Sound/WavWriter.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <ostream>
|
||||
|
||||
struct WavMetaData
|
||||
{
|
||||
unsigned channelCount;
|
||||
unsigned samplesPerSec;
|
||||
unsigned bitsPerSample;
|
||||
};
|
||||
|
||||
class WavWriter
|
||||
{
|
||||
public:
|
||||
explicit WavWriter(std::ostream& stream);
|
||||
|
||||
void WritePcmHeader(const WavMetaData& metaData, size_t dataLen) const;
|
||||
void WritePcmData(const void* data, size_t dataLen) const;
|
||||
|
||||
private:
|
||||
std::ostream& m_stream;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user