/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_SoundArchiveFile.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 19580 $ *---------------------------------------------------------------------------*/ #ifndef NW_SND_SOUND_ARCHIVE_FILE_H_ #define NW_SND_SOUND_ARCHIVE_FILE_H_ #include // ut::BinaryFileHeader など #include // ReferenceWithSize など #include // PanMode など #include #include namespace nw { namespace snd { namespace internal { struct SoundArchiveFile { // ------------------------------------------------------------------------ // ファイルヘッダー // 前方宣言 struct StringBlock; struct InfoBlock; struct FileBlock; // 定数 static const int BLOCK_SIZE = 3; // メモ : SoundArchiveFile::FileHeader はヘッダだけ個別にロードするので、 // Util::SoundFileHeader を継承できない。 struct FileHeader : public ut::BinaryFileHeader { Util::ReferenceWithSize toBlocks[ BLOCK_SIZE ]; #if 0 // ファイルを全ロードした場合 const StringBlock* GetStringBlock() const; const InfoBlock* GetInfoBlock() const; const FileBlock* GetFileBlock() const; #endif // 各ブロックのサイズ u32 GetStringBlockSize() const; u32 GetInfoBlockSize() const; u32 GetFileBlockSize() const; // 各ブロックのオフセット s32 GetStringBlockOffset() const; s32 GetInfoBlockOffset() const; s32 GetFileBlockOffset() const; private: const Util::ReferenceWithSize* GetReferenceBy( u16 typeId ) const; }; // ------------------------------------------------------------------------ // 文字列ブロック struct StringTable; struct PatriciaTree; struct StringBlockBody { private: enum Sections { Sections_StringTable, Sections_PatriciaTree, Sections_Max = Sections_PatriciaTree }; public: // データ Util::Reference toSection[ Sections_Max ]; // アクセサ const char* GetString( SoundArchive::ItemId stringId ) const; u32 GetStringCount() const { return GetStringTable()->GetCount(); } NW_INLINE u32 GetItemId( const char* str ) const { return GetItemIdImpl( Sections_PatriciaTree, str ); } // デバッグ void DumpTree() const; private: const void* GetSection( Sections section ) const; NW_INLINE const StringTable* GetStringTable() const { return reinterpret_cast( GetSection( Sections_StringTable ) ); } NW_INLINE const PatriciaTree* GetPatriciaTree( Sections section ) const { return reinterpret_cast( GetSection( section ) ); } u32 GetItemIdImpl( Sections section, const char* str ) const; }; struct PatriciaTree { struct NodeData { ut::ResU32 stringId; // 文字列 ID ut::ResU32 itemId; // アイテム ID (サウンドID、バンクIDなど) }; struct Node { static const u16 FLAG_LEAF = ( 1 << 0 ); ut::ResU16 flags; ut::ResU16 bit; ut::ResU32 leftIdx; ut::ResU32 rightIdx; NodeData nodeData; }; ut::ResU32 rootIdx; Util::Table nodeTable; const NodeData* GetNodeDataBy( const char* str, std::size_t len = 0 ) const; // ut_ResDictionary.h の ResDicPatricia のインタフェイスを踏襲 // のちのち、役立つことがあるかもしれない。 void* operator[](int idx) const { NW_MINMAX_ASSERT( idx, 0L, static_cast( nodeTable.count - 1 )); // 辞書引き関連についてはconst correctnessを維持しなくても問題ないだろう return const_cast( reinterpret_cast( &nodeTable.item[ idx ] ) ); } void* operator[](u32 idx) const { return operator[]( static_cast(idx) ); } void* operator[](const char* s) const { return operator()( s, 0 ); } void* operator()(const char* s, size_t len) const { return const_cast( reinterpret_cast( GetNodeDataBy( s, len ) ) ); } u32 GetNumData() const { return nodeTable.count; } u32 GetCount() const { return GetNumData(); } }; struct StringBlock { ut::BinaryBlockHeader header; StringBlockBody body; }; struct StringTable { // データ Util::ReferenceWithSizeTable table; // アクセサ const char* GetString( int stringId ) const { return reinterpret_cast( ut::AddOffsetToPtr( this, table.item[ stringId ].offset ) ); } u32 GetCount() const { return table.count; } }; // ------------------------------------------------------------------------ // 情報ブロック // 前方宣言 struct SoundInfo; struct BankInfo; struct PlayerInfo; struct SoundGroupInfo; struct GroupInfo; struct WaveArchiveInfo; struct FileInfo; struct SoundArchivePlayerInfo; struct InfoBlockBody { // // データ // Util::Reference toSoundInfoReferenceTable; Util::Reference toSoundGroupInfoReferenceTable; Util::Reference toBankInfoReferenceTable; Util::Reference toWaveArchiveInfoReferenceTable; Util::Reference toGroupInfoReferenceTable; Util::Reference toPlayerInfoReferenceTable; Util::Reference toFileInfoReferenceTable; Util::Reference toSoundArchivePlayerInfo; // // アクセサ // NW_INLINE u32 GetSoundCount() const { return GetSoundInfoReferenceTable().count; } NW_INLINE u32 GetBankCount() const { return GetBankInfoReferenceTable().count; } NW_INLINE u32 GetPlayerCount() const { return GetPlayerInfoReferenceTable().count; } NW_INLINE u32 GetSoundGroupCount() const { return GetSoundGroupInfoReferenceTable().count; } NW_INLINE u32 GetGroupCount() const { return GetGroupInfoReferenceTable().count; } NW_INLINE u32 GetWaveArchiveCount() const { return GetWaveArchiveInfoReferenceTable().count; } NW_INLINE u32 GetFileCount() const { return GetFileInfoReferenceTable().count; } const SoundInfo* GetSoundInfo( SoundArchive::ItemId soundId ) const; const BankInfo* GetBankInfo( SoundArchive::ItemId bankId ) const; const PlayerInfo* GetPlayerInfo( SoundArchive::ItemId playerId ) const; const SoundGroupInfo* GetSoundGroupInfo( SoundArchive::ItemId soundGroupId ) const; const GroupInfo* GetGroupInfo( SoundArchive::ItemId groupId ) const; const WaveArchiveInfo* GetWaveArchiveInfo( SoundArchive::ItemId warcId ) const; const FileInfo* GetFileInfo( SoundArchive::FileId fileId ) const; const SoundArchivePlayerInfo* GetSoundArchivePlayerInfo() const; SoundArchive::FileId GetItemFileId( SoundArchive::ItemId id ) const; SoundArchive::StringId GetItemStringId( SoundArchive::ItemId id ) const; private: const Util::ReferenceTable& GetSoundInfoReferenceTable() const; const Util::ReferenceTable& GetBankInfoReferenceTable() const; const Util::ReferenceTable& GetPlayerInfoReferenceTable() const; const Util::ReferenceTable& GetSoundGroupInfoReferenceTable() const; const Util::ReferenceTable& GetGroupInfoReferenceTable() const; const Util::ReferenceTable& GetWaveArchiveInfoReferenceTable() const; const Util::ReferenceTable& GetFileInfoReferenceTable() const; }; struct InfoBlock { ut::BinaryBlockHeader header; InfoBlockBody body; }; struct StreamSoundInfo; struct WaveSoundInfo; struct SequenceSoundInfo; struct Sound3DInfo; struct SoundInfo { // データ ut::ResU32 fileId; ut::ResU32 playerId; ut::ResU8 volume; u8 padding0; u16 padding1; Util::Reference toDetailSoundInfo; // {Sequence,Stream,Wave}SoundInfo への参照 Util::BitFlag optionParameter; // アクセサ SoundArchive::SoundType GetSoundType() const; const StreamSoundInfo& GetStreamSoundInfo() const; const WaveSoundInfo& GetWaveSoundInfo() const; const SequenceSoundInfo& GetSequenceSoundInfo() const; const Sound3DInfo* GetSound3DInfo() const; // いつか、3D サウンド情報を削ることもありそうなので、ポインタを返すようにする u32 GetStringId() const; PanMode GetPanMode() const; PanCurve GetPanCurve() const; u8 GetPlayerPriority() const; u8 GetActorPlayerId() const; u32 GetUserParam() const; // 通常の u32 ユーザーパラメータ bool IsFrontBypass() const; // TODO: SEND/MOD パラメータの取得関数 // TODO: 要対応 // u32 GetUserExtraParamCount(); // u32 テーブル形式の拡張ユーザーパラメータ // u32 GetUserExtraParam( int index ); }; struct StreamSoundInfo { // データ ut::ResU16 allocTrackCount; // トラック数 (マルチトラックの設定) ut::ResU16 allocChannelCount; // マルチトラックを加味した総チャンネル数 Util::BitFlag optionParameter; // 使い方は未定 }; struct WaveSoundInfo { // データ ut::ResU32 index; // ウェーブサウンドセットファイル (bxwsd) 内で何番目か ut::ResU32 allocTrackCount; // 必要なトラック数 Util::BitFlag optionParameter; // アクセサ u8 GetChannelPriority() const; u8 GetIsReleasePriorityFix() const; }; struct SequenceSoundInfo { // データ Util::Reference toBankIdTable; ut::ResU32 allocateTrackFlags; Util::BitFlag optionParameter; // アクセサ void GetBankIds( u32* bankIds ) const; // SoundArchive::SEQ_BANK_MAX だけコピー u32 GetStartOffset() const; u8 GetChannelPriority() const; bool IsReleasePriorityFix() const; private: const Util::Table& GetBankIdTable() const; }; struct Sound3DInfo { ut::ResU32 flags; // [0]Vol [1]Priotity [2]Pan [3]SPan [4]Filter ut::ResF32 decayRatio; // 減衰率 u8 decayCurve; // 減衰カーブタイプ (nw::snd::DecayCurve が入る) u8 dopplerFactor; // ドップラーファクター u8 padding[2]; // padding Util::BitFlag optionParameter; // 予備 }; struct BankInfo { // データ ut::ResU32 fileId; Util::Reference toWaveArchiveItemIdTable; Util::BitFlag optionParameter; // アクセサ u32 GetStringId() const; NW_INLINE const Util::Table* GetWaveArchiveItemIdTable() const { return reinterpret_cast*>( ut::AddOffsetToPtr( this, toWaveArchiveItemIdTable.offset ) ); } }; struct PlayerInfo { // データ ut::ResU32 playableSoundMax; // プレイヤー最大再生数 Util::BitFlag optionParameter; // アクセサ u32 GetStringId() const; u32 GetPlayerHeapSize() const; }; struct WaveSoundGroupInfo; struct SoundGroupInfo { // データ ut::ResU32 startId; // アイテム ID (startId と endId の ItemType は同一) ut::ResU32 endId; Util::Reference toFileIdTable; Util::Reference toDetailSoundGroupInfo; Util::BitFlag optionParameter; // アクセサ u32 GetStringId() const; NW_INLINE const Util::Table* GetFileIdTable() const { return reinterpret_cast*>( ut::AddOffsetToPtr( this, toFileIdTable.offset ) ); } NW_INLINE const WaveSoundGroupInfo* GetWaveSoundGroupInfo() const { if ( toDetailSoundGroupInfo.typeId != ElementType_SoundArchiveFile_WaveSoundGroupInfo ) { return NULL; } return reinterpret_cast( ut::AddOffsetToPtr( this, toDetailSoundGroupInfo.offset ) ); } #if 0 // 必要になるかもしれない u32 GetFileIdCount() const { return GetFileIdTable().count; } u32 GetFileId( u32 index ) const { if ( index >= GetFileIdCount() ) return SoundArchive::INVALID_ID; return GetFileIdTable().item[ index ]; } #endif }; struct WaveSoundGroupInfo { // データ Util::Reference toWaveArchiveItemIdTable; Util::BitFlag optionParameter; // 仮。なにが割り当てられるかは未定。 // アクセサ NW_INLINE const Util::Table* GetWaveArchiveItemIdTable() const { return reinterpret_cast*>( ut::AddOffsetToPtr( this, toWaveArchiveItemIdTable.offset ) ); } }; struct GroupInfo { // データ ut::ResU32 fileId; Util::BitFlag optionParameter; // アクセサ u32 GetStringId() const; }; struct WaveArchiveInfo { // データ ut::ResU32 fileId; bool isLoadIndividual; u8 padding1; u16 padding2; Util::BitFlag optionParameter; // アクセサ u32 GetStringId() const; u32 GetWaveCount() const; }; enum FileLocationType { FILE_LOCATION_TYPE_INTERNAL, // サウンドアーカイブ内に配置 FILE_LOCATION_TYPE_EXTERNAL, // サウンドアーカイブ外に配置 FILE_LOCATION_TYPE_NONE // ファイル単体にアクセスできない (=ロードできない) // * バンクファイルかウェーブサウンドセットファイルのうち、 // 次の条件を満たすものが該当 // * 波形アーカイブ設定が【自動(共有)】で、 // * 出力設定が【埋め込み】のグループに属している }; struct InternalFileInfo; // サウンドアーカイブ FILE ブロック内に格納 struct ExternalFileInfo; // サウンドアーカイブ外に格納 struct FileInfo { // データ Util::Reference toFileLocation; Util::BitFlag optionParameter; // 仮。なにが割り当てられるかは未定。 // アクセサ FileLocationType GetFileLocationType() const; const InternalFileInfo* GetInternalFileInfo() const; const ExternalFileInfo* GetExternalFileInfo() const; #if 0 // サウンドアーカイブファイル上のアドレスを取得 // ROM 上のバイナリサウンドアーカイブファイルの先頭をアドレス 0 とする。 const void* GetFileAddress( const void* dataBlockBodyAddress ) const; // TODO: ↑ これは必要ない? #endif }; struct InternalFileInfo { // データ Util::ReferenceWithSize toFileImageFromFileBlockBody; // アクセサ inline u32 GetFileSize() const { return toFileImageFromFileBlockBody.size; } inline u32 GetOffsetFromFileBlockHead() const { return toFileImageFromFileBlockBody.offset + sizeof(ut::BinaryBlockHeader); } }; struct ExternalFileInfo { // データ // TODO: u32 fileSize や u16? filePathLength が入るかも char filePath[1]; }; struct SoundArchivePlayerInfo { nw::ut::ResU16 sequenceSoundMax; nw::ut::ResU16 sequenceTrackMax; nw::ut::ResU16 streamSoundMax; nw::ut::ResU16 streamTrackMax; nw::ut::ResU16 streamChannelMax; nw::ut::ResU16 waveSoundMax; nw::ut::ResU16 waveTrackmax; u16 padding; nw::ut::ResU32 options; // TODO: 仮 }; // ------------------------------------------------------------------------ // ファイルブロック struct FileBlockBody { // ボディのアドレスを取るためだけ }; struct FileBlock { ut::BinaryBlockHeader header; FileBlockBody body; }; }; } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw #endif /* NW_SND_SOUND_ARCHIVE_FILE_H_ */