1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00
Beef/BeefySysLib/sound/Common/AkFilePackageLUT.h
2019-08-23 11:56:54 -07:00

207 lines
6.5 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// AkFilePackageLUT.h
//
// This class parses the header of file packages that were created with the
// AkFilePackager utility app (located in ($WWISESDK)/samples/FilePackager/),
// and looks-up files at run-time.
//
// The header of these file packages contains look-up tables that describe the
// internal offset of each file it references, their block size (required alignment),
// and their language. Each combination of AkFileID and Language ID is unique.
//
// The language was created dynamically when the package was created. The header
// also contains a map of language names (strings) to their ID, so that the proper
// language-specific version of files can be resolved. The language name that is stored
// matches the name of the directory that is created by the Wwise Bank Manager,
// except for the trailing slash.
//
// Copyright (c) 2007-2009 Audiokinetic Inc. / All Rights Reserved
//
//////////////////////////////////////////////////////////////////////
#ifndef _AK_FILE_PACKAGE_LUT_H_
#define _AK_FILE_PACKAGE_LUT_H_
#include <AK/SoundEngine/Common/IAkStreamMgr.h>
#include <AK/Tools/Common/AkAssert.h>
// AK file packager definitions.
#define AKPK_CURRENT_VERSION (1)
#define AKPK_HEADER_CHUNK_DEF_SIZE (8) // The header chunk definition is 8 bytes wide.
#define AKPK_FILE_FORMAT_TAG \
AkmmioFOURCC('A','K','P','K')
//-----------------------------------------------------------------------------
// Name: class CAkFilePackageLUT.
// Desc: Keeps pointers to various parts of the header. Offers look-up services
// for file look-up and soundbank ID retrieval.
//-----------------------------------------------------------------------------
class CAkFilePackageLUT
{
public:
static const AkUInt16 AK_INVALID_LANGUAGE_ID = 0;
// Ensure no padding is done because this structure is mapped to file content
#pragma pack(push, 4)
template <class T_FILEID>
struct AkFileEntry
{
T_FILEID fileID; // File identifier.
AkUInt32 uBlockSize; // Size of one block, required alignment (in bytes).
AkUInt32 uFileSize; // File size in bytes.
AkUInt32 uStartBlock;// Start block, expressed in terms of uBlockSize.
AkUInt32 uLanguageID;// Language ID. AK_INVALID_LANGUAGE_ID if not language-specific.
};
#pragma pack(pop)
CAkFilePackageLUT();
virtual ~CAkFilePackageLUT();
// Create a new LUT from a packaged file header.
// The LUT sets pointers to appropriate location inside header data (in_pData).
AKRESULT Setup(
AkUInt8 * in_pData, // Header data.
AkUInt32 in_uHeaderSize // Size of file package header.
);
// Find a file entry by ID.
const AkFileEntry<AkFileID> * LookupFile(
AkFileID in_uID, // File ID.
AkFileSystemFlags * in_pFlags // Special flags. Do not pass NULL.
);
// Find a file entry by ID with 64 bit ID.
const AkFileEntry<AkUInt64> * LookupFile(
AkUInt64 in_uID, // File ID.
AkFileSystemFlags * in_pFlags // Special flags. Do not pass NULL.
);
// Set current language.
// Returns AK_InvalidLanguage if a package is loaded but the language string cannot be found.
// Returns AK_Success otherwise.
AKRESULT SetCurLanguage(
const AkOSChar* in_pszLanguage // Language string.
);
// Find a soundbank ID by its name (by hashing its name)
AkFileID GetSoundBankID(
const AkOSChar* in_pszBankName // Soundbank name.
);
// Return the id of an external file (by hashing its name in 64 bits)
AkUInt64 GetExternalID(
const AkOSChar* in_pszExternalName // External Source name.
);
protected:
static void RemoveFileExtension( AkOSChar* in_pstring );
static void _MakeLower( AkOSChar* in_pString );
static void _MakeLowerA( char* in_pString, size_t in_strlen );
static AkUInt64 _MakeLowerAndHash64( char* in_pszString );
static AkUInt64 GetID64FromString( const char* in_pszString );
static AkUInt64 GetID64FromString( const wchar_t* in_pszString );
//
// File LUTs.
//
template <class T_FILEID>
class FileLUT
{
public:
const AkFileEntry<T_FILEID> * FileEntries() const { return (AkFileEntry<T_FILEID>*)((AkUInt32*)this + 1); }
bool HasFiles() const { return ( m_uNumFiles > 0 ); }
AkUInt32 NumFiles() const { return m_uNumFiles; }
private:
FileLUT(); // Do not create this object, just cast raw data.
AkUInt32 m_uNumFiles;
};
// Helper: Find a file entry by ID.
template <class T_FILEID>
const AkFileEntry<T_FILEID> * LookupFile(
T_FILEID in_uID, // File ID.
const FileLUT<T_FILEID> * in_pLut, // LUT to search.
bool in_bIsLanguageSpecific // True: match language ID.
);
private:
AkUInt16 m_curLangID; // Current language.
//
// Maps format.
//
class StringMap
{
public:
// Returns AK_INVALID_UNIQUE_ID if ID is not found.
AkUInt32 GetID( const AkOSChar* in_pszString );
inline AkUInt32 GetNumStrings() { return m_uNumStrings; }
private:
struct StringEntry
{
AkUInt32 uOffset; // Byte offset of the string in the packaged strings section,
// from beginning of the string map.
AkUInt32 uID; // ID.
};
StringMap(); // Do not create this object, just cast raw data to use GetID().
AkUInt32 m_uNumStrings;
};
// Languages map.
StringMap * m_pLangMap;
// SoundBanks LUT.
FileLUT<AkFileID> * m_pSoundBanks;
// StreamedFiles LUT.
FileLUT<AkFileID> * m_pStmFiles;
// External Sources LUT.
FileLUT<AkUInt64> * m_pExternals;
};
// Helper: Find a file entry by ID.
template <class T_FILEID>
const CAkFilePackageLUT::AkFileEntry<T_FILEID> * CAkFilePackageLUT::LookupFile(
T_FILEID in_uID, // File ID.
const FileLUT<T_FILEID> * in_pLut, // LUT to search.
bool in_bIsLanguageSpecific // True: match language ID.
)
{
const AkFileEntry<T_FILEID> * pTable = in_pLut->FileEntries();
AKASSERT( pTable && in_pLut->HasFiles() );
AkUInt16 uLangID = in_bIsLanguageSpecific ? m_curLangID : AK_INVALID_LANGUAGE_ID;
// Binary search. LUT items should be sorted by fileID, then by language ID.
AkInt32 uTop = 0, uBottom = in_pLut->NumFiles()-1;
do
{
AkInt32 uThis = ( uBottom - uTop ) / 2 + uTop;
if ( pTable[ uThis ].fileID > in_uID )
uBottom = uThis - 1;
else if ( pTable[ uThis ].fileID < in_uID )
uTop = uThis + 1;
else
{
// Correct ID. Check language.
if ( pTable[ uThis ].uLanguageID > uLangID )
uBottom = uThis - 1;
else if ( pTable[ uThis ].uLanguageID < uLangID )
uTop = uThis + 1;
else
return pTable + uThis;
}
}
while ( uTop <= uBottom );
return NULL;
}
#endif //_AK_FILE_PACKAGE_LUT_H_