Sound Archives (.snd)
Sound archives store DOOM: Eternal and DOOM: The Dark Ages audio files (samples).
File Format
// Eternal version of sndEntry
struct sndEntry_Eternal
{
uint64_t farmhash; // Farmhash64 of the entry's DECODED data
uint32_t sampleID; // ID used to to reference this sample in the sound banks
uint32_t encodedSize; // Size of the entry's data as it's stored in the archive.
uint64_t offset; // Location of entry's data in the file. Relative to beginning of file
uint32_t decodedSize; // Size of the entry's data after being decoded
uint16_t encoding; // Either 2 or 3
uint16_t metaSize; // Size of this entry's meta section inside the meta blob
uint32_t metaOffset; // Location of this entry's meta section. Relative to global offset 0xC
}
// Dark Ages version of sndEntry
struct sndEntry_DarkAges
{
uint64_t farmhash; // Farmhash64 of the entry's data
uint32_t sampleID; // ID used to to reference this sample in the sound banks
uint32_t encodedSize; // Size of the entry's data as it's stored in the archive.
uint64_t offset; // Location of entry's data in the file. Relative to beginning of file
uint32_t decodedSize; // Always equal to encodedSize
uint32_t metaSize; // Size of this entry's meta section inside the meta blob
uint32_t metaOffset; // Location of this entry's meta section. Relative to global offset 0xC
}
struct sndHeaderChunk
{
uint32_t metaSize; // Size of the header chunk's meta blob + 4
char* metaBlob; // Header chunk's meta blob. Length == metaSize - 4
uint32_t numEntries; // Number of entries
sndEntry* entries; // Array of entry information. Length == numEntries. Exact format depends on the game
}
struct snd
{
uint32_t version; // Always 6
uint32_t headerSize; // Size of the header chunk
sndHeaderChunk; // Header chunk. Exact size given by headerSize
char* dataChunk; // Data chunk. Stores the complete audio samples. Length == remainder of file
}
About: Meta Blob
Audio samples in both games use RIFF as their basic format. A sample's "meta" section consists of the start of the file, up to and including the length field of it's data chunk.
Code that demonstrates how to calculate the length of a sample's meta chunk can be found here