1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundArchiveFile.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_SND_SOUND_ARCHIVE_FILE_H_
19 #define NW_SND_SOUND_ARCHIVE_FILE_H_
20 
21 #include <nw/ut/ut_BinaryFileFormat.h>      // ut::BinaryFileHeader など
22 #include <nw/snd/snd_Util.h>                // ReferenceWithSize など
23 #include <nw/snd/snd_Global.h>              // PanMode など
24 #include <nw/snd/snd_SoundArchive.h>
25 #include <nw/snd/snd_ElementType.h>
26 
27 namespace nw {
28 namespace snd {
29 namespace internal {
30 
31 struct SoundArchiveFile
32 {
33     // ------------------------------------------------------------------------
34     //  ファイルヘッダー
35 
36     // 前方宣言
37     struct StringBlock;
38     struct InfoBlock;
39     struct FileBlock;
40 
41     // 定数
42     static const int BLOCK_SIZE = 3;
43 
44     // メモ : SoundArchiveFile::FileHeader はヘッダだけ個別にロードするので、
45     //        Util::SoundFileHeader を継承できない。
46     struct FileHeader : public ut::BinaryFileHeader
47     {
48         Util::ReferenceWithSize toBlocks[ BLOCK_SIZE ];
49 
50 #if 0
51         // ファイルを全ロードした場合
52         const StringBlock*  GetStringBlock() const;
53         const InfoBlock*    GetInfoBlock() const;
54         const FileBlock*    GetFileBlock() const;
55 #endif
56 
57         // 各ブロックのサイズ
58         u32 GetStringBlockSize() const;
59         u32 GetInfoBlockSize() const;
60         u32 GetFileBlockSize() const;
61 
62         // 各ブロックのオフセット
63         s32 GetStringBlockOffset() const;
64         s32 GetInfoBlockOffset() const;
65         s32 GetFileBlockOffset() const;
66 
67     private:
68         const Util::ReferenceWithSize* GetReferenceBy( u16 typeId ) const;
69     };
70 
71 
72     // ------------------------------------------------------------------------
73     //  文字列ブロック
74 
75     struct StringTable;
76     struct PatriciaTree;
77     struct StringBlockBody
78     {
79     private:
80         enum Sections
81         {
82             Sections_StringTable,
83             Sections_PatriciaTree,
84             Sections_Max = Sections_PatriciaTree
85         };
86 
87     public:
88         // データ
89         Util::Reference toSection[ Sections_Max ];
90 
91         // アクセサ
92         const char* GetString( SoundArchive::ItemId stringId ) const;
GetStringCountSoundArchiveFile::StringBlockBody93         u32 GetStringCount() const { return GetStringTable()->GetCount(); }
94 
GetItemIdSoundArchiveFile::StringBlockBody95         NW_INLINE u32 GetItemId( const char* str ) const
96         {
97             return GetItemIdImpl( Sections_PatriciaTree, str );
98         }
99 
100         // デバッグ
101         void DumpTree() const;
102 
103     private:
104         const void* GetSection( Sections section ) const;
GetStringTableSoundArchiveFile::StringBlockBody105         NW_INLINE const StringTable* GetStringTable() const
106         {
107             return reinterpret_cast<const StringTable*>(
108                     GetSection( Sections_StringTable ) );
109         }
GetPatriciaTreeSoundArchiveFile::StringBlockBody110         NW_INLINE const PatriciaTree* GetPatriciaTree( Sections section ) const
111         {
112             return reinterpret_cast<const PatriciaTree*>(
113                     GetSection( section ) );
114         }
115         u32 GetItemIdImpl( Sections section, const char* str ) const;
116     };
117 
118     struct PatriciaTree
119     {
120         struct NodeData
121         {
122             ut::ResU32 stringId;        // 文字列 ID
123             ut::ResU32 itemId;          // アイテム ID (サウンドID、バンクIDなど)
124         };
125         struct Node
126         {
127             static const u16 FLAG_LEAF = ( 1 << 0 );
128             ut::ResU16  flags;
129             ut::ResU16  bit;
130             ut::ResU32  leftIdx;
131             ut::ResU32  rightIdx;
132             NodeData    nodeData;
133         };
134 
135         ut::ResU32 rootIdx;
136         Util::Table<Node> nodeTable;
137 
138         const NodeData* GetNodeDataBy( const char* str, std::size_t len = 0 ) const;
139 
140         // ut_ResDictionary.h の ResDicPatricia のインタフェイスを踏襲
141         // のちのち、役立つことがあるかもしれない。
142         void* operator[](int idx) const
143         {
144             NW_MINMAX_ASSERT( idx, 0L, static_cast<int>( nodeTable.count - 1 ));
145             // 辞書引き関連についてはconst correctnessを維持しなくても問題ないだろう
146             return const_cast<void*>(
147                     reinterpret_cast<const void*>( &nodeTable.item[ idx ] ) );
148         }
149         void* operator[](u32 idx) const
150         {
151             return operator[]( static_cast<int>(idx) );
152         }
153         void* operator[](const char* s) const
154         {
155             return operator()( s, 0 );
156         }
operatorSoundArchiveFile::PatriciaTree157         void* operator()(const char* s, size_t len) const
158         {
159             return const_cast<void*>(
160                     reinterpret_cast<const void*>( GetNodeDataBy( s, len ) ) );
161         }
GetNumDataSoundArchiveFile::PatriciaTree162         u32 GetNumData() const { return nodeTable.count; }
GetCountSoundArchiveFile::PatriciaTree163         u32 GetCount() const { return GetNumData(); }
164     };
165 
166     struct StringBlock
167     {
168         ut::BinaryBlockHeader   header;
169         StringBlockBody         body;
170     };
171 
172     struct StringTable
173     {
174         // データ
175         Util::ReferenceWithSizeTable table;
176 
177         // アクセサ
GetStringSoundArchiveFile::StringTable178         const char* GetString( int stringId ) const
179         {
180             return reinterpret_cast<const char*>(
181                     ut::AddOffsetToPtr( this, table.item[ stringId ].offset ) );
182         }
GetCountSoundArchiveFile::StringTable183         u32 GetCount() const
184         {
185             return table.count;
186         }
187     };
188 
189 
190     // ------------------------------------------------------------------------
191     //  情報ブロック
192 
193     // 前方宣言
194     struct SoundInfo;
195     struct BankInfo;
196     struct PlayerInfo;
197     struct SoundGroupInfo;
198     struct GroupInfo;
199     struct WaveArchiveInfo;
200     struct FileInfo;
201     struct SoundArchivePlayerInfo;
202 
203     struct InfoBlockBody
204     {
205         //
206         // データ
207         //
208         Util::Reference toSoundInfoReferenceTable;
209         Util::Reference toSoundGroupInfoReferenceTable;
210         Util::Reference toBankInfoReferenceTable;
211         Util::Reference toWaveArchiveInfoReferenceTable;
212         Util::Reference toGroupInfoReferenceTable;
213         Util::Reference toPlayerInfoReferenceTable;
214         Util::Reference toFileInfoReferenceTable;
215         Util::Reference toSoundArchivePlayerInfo;
216 
217         //
218         // アクセサ
219         //
GetSoundCountSoundArchiveFile::InfoBlockBody220         NW_INLINE u32 GetSoundCount() const       { return GetSoundInfoReferenceTable().count; }
GetBankCountSoundArchiveFile::InfoBlockBody221         NW_INLINE u32 GetBankCount() const        { return GetBankInfoReferenceTable().count; }
GetPlayerCountSoundArchiveFile::InfoBlockBody222         NW_INLINE u32 GetPlayerCount() const      { return GetPlayerInfoReferenceTable().count; }
GetSoundGroupCountSoundArchiveFile::InfoBlockBody223         NW_INLINE u32 GetSoundGroupCount() const  { return GetSoundGroupInfoReferenceTable().count; }
GetGroupCountSoundArchiveFile::InfoBlockBody224         NW_INLINE u32 GetGroupCount() const       { return GetGroupInfoReferenceTable().count; }
GetWaveArchiveCountSoundArchiveFile::InfoBlockBody225         NW_INLINE u32 GetWaveArchiveCount() const { return GetWaveArchiveInfoReferenceTable().count; }
GetFileCountSoundArchiveFile::InfoBlockBody226         NW_INLINE u32 GetFileCount() const        { return GetFileInfoReferenceTable().count; }
227 
228         const SoundInfo*        GetSoundInfo( SoundArchive::ItemId soundId ) const;
229         const BankInfo*         GetBankInfo( SoundArchive::ItemId bankId ) const;
230         const PlayerInfo*       GetPlayerInfo( SoundArchive::ItemId playerId ) const;
231         const SoundGroupInfo*   GetSoundGroupInfo( SoundArchive::ItemId soundGroupId ) const;
232         const GroupInfo*        GetGroupInfo( SoundArchive::ItemId groupId ) const;
233         const WaveArchiveInfo*  GetWaveArchiveInfo( SoundArchive::ItemId warcId ) const;
234         const FileInfo*         GetFileInfo( SoundArchive::FileId fileId ) const;
235 
236         const SoundArchivePlayerInfo* GetSoundArchivePlayerInfo() const;
237 
238         SoundArchive::FileId    GetItemFileId( SoundArchive::ItemId id ) const;
239         SoundArchive::StringId  GetItemStringId( SoundArchive::ItemId id ) const;
240 
241     private:
242         const Util::ReferenceTable& GetSoundInfoReferenceTable() const;
243         const Util::ReferenceTable& GetBankInfoReferenceTable() const;
244         const Util::ReferenceTable& GetPlayerInfoReferenceTable() const;
245         const Util::ReferenceTable& GetSoundGroupInfoReferenceTable() const;
246         const Util::ReferenceTable& GetGroupInfoReferenceTable() const;
247         const Util::ReferenceTable& GetWaveArchiveInfoReferenceTable() const;
248         const Util::ReferenceTable& GetFileInfoReferenceTable() const;
249     };
250 
251     struct InfoBlock
252     {
253         ut::BinaryBlockHeader   header;
254         InfoBlockBody           body;
255     };
256 
257 
258     struct StreamSoundInfo;
259     struct WaveSoundInfo;
260     struct SequenceSoundInfo;
261     struct Sound3DInfo;
262 
263     struct SoundInfo
264     {
265         // データ
266         ut::ResU32      fileId;
267         ut::ResU32      playerId;
268         ut::ResU8       volume;
269         u8              padding0;
270         u16             padding1;
271         Util::Reference toDetailSoundInfo;  // {Sequence,Stream,Wave}SoundInfo への参照
272         Util::BitFlag   optionParameter;
273 
274         // アクセサ
275         SoundArchive::SoundType     GetSoundType() const;
276         const StreamSoundInfo&      GetStreamSoundInfo() const;
277         const WaveSoundInfo&        GetWaveSoundInfo() const;
278         const SequenceSoundInfo&    GetSequenceSoundInfo() const;
279         const Sound3DInfo*          GetSound3DInfo() const;
280             // いつか、3D サウンド情報を削ることもありそうなので、ポインタを返すようにする
281 
282         u32         GetStringId() const;
283         PanMode     GetPanMode() const;
284         PanCurve    GetPanCurve() const;
285         u8          GetPlayerPriority() const;
286         u8          GetActorPlayerId() const;
287         u32         GetUserParam() const;       // 通常の u32 ユーザーパラメータ
288         bool        IsFrontBypass() const;
289 
290         // TODO: SEND/MOD パラメータの取得関数
291 
292         // TODO: 要対応
293         // u32         GetUserExtraParamCount();    // u32 テーブル形式の拡張ユーザーパラメータ
294         // u32         GetUserExtraParam( int index );
295     };
296 
297     struct StreamSoundInfo
298     {
299         // データ
300         ut::ResU16 allocTrackCount;     // トラック数 (マルチトラックの設定)
301         ut::ResU16 allocChannelCount;   // マルチトラックを加味した総チャンネル数
302         Util::BitFlag optionParameter;  // 使い方は未定
303     };
304 
305     struct WaveSoundInfo
306     {
307         // データ
308         ut::ResU32 index;           // ウェーブサウンドセットファイル (bxwsd) 内で何番目か
309         ut::ResU32 allocTrackCount; // 必要なトラック数
310         Util::BitFlag optionParameter;
311 
312         // アクセサ
313         u8 GetChannelPriority() const;
314         u8 GetIsReleasePriorityFix() const;
315 
316     };
317 
318     struct SequenceSoundInfo
319     {
320         // データ
321         Util::Reference toBankIdTable;
322         ut::ResU32      allocateTrackFlags;
323         Util::BitFlag   optionParameter;
324 
325         // アクセサ
326         void GetBankIds( u32* bankIds ) const;  // SoundArchive::SEQ_BANK_MAX だけコピー
327         u32 GetStartOffset() const;
328         u8  GetChannelPriority() const;
329         bool IsReleasePriorityFix() const;
330     private:
331         const Util::Table<ut::ResU32>& GetBankIdTable() const;
332     };
333 
334     struct Sound3DInfo
335     {
336         ut::ResU32 flags;       // [0]Vol [1]Priotity [2]Pan [3]SPan [4]Filter
337                                 // (SoundArchive::Sound3DInfo::FLAG_CTRL_*** に対応しています)
338         ut::ResF32 decayRatio;  // 減衰率
339         u8 decayCurve;          // 減衰カーブタイプ (nw::snd::DecayCurve が入る)
340         u8 dopplerFactor;       // ドップラーファクター
341         u8 padding[2];          // padding
342         Util::BitFlag optionParameter;      // 予備
343     };
344 
345     struct BankInfo
346     {
347         // データ
348         ut::ResU32      fileId;
349         Util::Reference toWaveArchiveItemIdTable;
350         Util::BitFlag   optionParameter;
351 
352         // アクセサ
353         u32 GetStringId() const;
354 
355         NW_INLINE const Util::Table<ut::ResU32>*
GetWaveArchiveItemIdTableSoundArchiveFile::BankInfo356         GetWaveArchiveItemIdTable() const
357         {
358             return reinterpret_cast<const Util::Table<ut::ResU32>*>(
359                     ut::AddOffsetToPtr( this, toWaveArchiveItemIdTable.offset ) );
360         }
361     };
362 
363     struct PlayerInfo
364     {
365         // データ
366         ut::ResU32      playableSoundMax;   // プレイヤー最大再生数
367         Util::BitFlag   optionParameter;
368 
369         // アクセサ
370         u32 GetStringId() const;
371         u32 GetPlayerHeapSize() const;
372     };
373 
374     struct WaveSoundGroupInfo;
375     struct SoundGroupInfo
376     {
377         // データ
378         ut::ResU32      startId;    // アイテム ID (startId と endId の ItemType は同一)
379         ut::ResU32      endId;
380         Util::Reference toFileIdTable;
381         Util::Reference toDetailSoundGroupInfo;
382         Util::BitFlag   optionParameter;
383 
384         // アクセサ
385         u32 GetStringId() const;
386 
GetFileIdTableSoundArchiveFile::SoundGroupInfo387         NW_INLINE const Util::Table<ut::ResU32>* GetFileIdTable() const
388         {
389             return reinterpret_cast<const Util::Table<ut::ResU32>*>(
390                     ut::AddOffsetToPtr( this, toFileIdTable.offset ) );
391         }
GetWaveSoundGroupInfoSoundArchiveFile::SoundGroupInfo392         NW_INLINE const WaveSoundGroupInfo* GetWaveSoundGroupInfo() const
393         {
394             if ( toDetailSoundGroupInfo.typeId !=
395                     ElementType_SoundArchiveFile_WaveSoundGroupInfo )
396             {
397                 return NULL;
398             }
399 
400             return reinterpret_cast<const WaveSoundGroupInfo*>(
401                     ut::AddOffsetToPtr( this, toDetailSoundGroupInfo.offset ) );
402         }
403 
404 #if 0   // 必要になるかもしれない
405         u32 GetFileIdCount() const { return GetFileIdTable().count; }
406         u32 GetFileId( u32 index ) const
407         {
408             if ( index >= GetFileIdCount() ) return SoundArchive::INVALID_ID;
409             return GetFileIdTable().item[ index ];
410         }
411 #endif
412     };
413 
414     struct WaveSoundGroupInfo
415     {
416         // データ
417         Util::Reference toWaveArchiveItemIdTable;
418         Util::BitFlag   optionParameter;    // 仮。なにが割り当てられるかは未定。
419 
420         // アクセサ
421         NW_INLINE const Util::Table<ut::ResU32>*
GetWaveArchiveItemIdTableSoundArchiveFile::WaveSoundGroupInfo422         GetWaveArchiveItemIdTable() const
423         {
424             return reinterpret_cast<const Util::Table<ut::ResU32>*>(
425                     ut::AddOffsetToPtr( this, toWaveArchiveItemIdTable.offset ) );
426         }
427     };
428 
429     struct GroupInfo
430     {
431         // データ
432         ut::ResU32      fileId;
433         Util::BitFlag   optionParameter;
434 
435         // アクセサ
436         u32 GetStringId() const;
437     };
438 
439     struct WaveArchiveInfo
440     {
441         // データ
442         ut::ResU32      fileId;
443         bool            isLoadIndividual;
444         u8              padding1;
445         u16             padding2;
446         Util::BitFlag   optionParameter;
447 
448         // アクセサ
449         u32 GetStringId() const;
450         u32 GetWaveCount() const;
451     };
452 
453     enum FileLocationType
454     {
455         FILE_LOCATION_TYPE_INTERNAL,    // サウンドアーカイブ内に配置
456         FILE_LOCATION_TYPE_EXTERNAL,    // サウンドアーカイブ外に配置
457         FILE_LOCATION_TYPE_NONE
458             // ファイル単体にアクセスできない (=ロードできない)
459             //  * バンクファイルかウェーブサウンドセットファイルのうち、
460             //    次の条件を満たすものが該当
461             //      * 波形アーカイブ設定が【自動(共有)】で、
462             //      * 出力設定が【埋め込み】のグループに属している
463     };
464 
465     struct InternalFileInfo;    // サウンドアーカイブ FILE ブロック内に格納
466     struct ExternalFileInfo;    // サウンドアーカイブ外に格納
467 
468     struct FileInfo
469     {
470         // データ
471         Util::Reference toFileLocation;
472         Util::BitFlag   optionParameter;    // 仮。なにが割り当てられるかは未定。
473 
474         // アクセサ
475         FileLocationType GetFileLocationType() const;
476         const InternalFileInfo* GetInternalFileInfo() const;
477         const ExternalFileInfo* GetExternalFileInfo() const;
478 
479 #if 0
480         // サウンドアーカイブファイル上のアドレスを取得
481         // ROM 上のバイナリサウンドアーカイブファイルの先頭をアドレス 0 とする。
482         const void* GetFileAddress( const void* dataBlockBodyAddress ) const;
483             // TODO: ↑ これは必要ない?
484 #endif
485     };
486 
487     struct InternalFileInfo
488     {
489         // データ
490         Util::ReferenceWithSize toFileImageFromFileBlockBody;
491 
492         // アクセサ
GetFileSizeSoundArchiveFile::InternalFileInfo493         inline u32 GetFileSize() const
494         {
495             return toFileImageFromFileBlockBody.size;
496         }
GetOffsetFromFileBlockHeadSoundArchiveFile::InternalFileInfo497         inline u32 GetOffsetFromFileBlockHead() const
498         {
499             return toFileImageFromFileBlockBody.offset + sizeof(ut::BinaryBlockHeader);
500         }
501     };
502 
503     struct ExternalFileInfo
504     {
505         // データ
506         // TODO: u32 fileSize や u16? filePathLength が入るかも
507         char filePath[1];
508     };
509 
510     struct SoundArchivePlayerInfo
511     {
512         nw::ut::ResU16  sequenceSoundMax;
513         nw::ut::ResU16  sequenceTrackMax;
514         nw::ut::ResU16  streamSoundMax;
515         nw::ut::ResU16  streamTrackMax;
516         nw::ut::ResU16  streamChannelMax;
517         nw::ut::ResU16  waveSoundMax;
518         nw::ut::ResU16  waveTrackmax;
519         u16             padding;
520         nw::ut::ResU32  options;        // TODO: 仮
521     };
522 
523 
524     // ------------------------------------------------------------------------
525     //  ファイルブロック
526 
527     struct FileBlockBody
528     {
529         // ボディのアドレスを取るためだけ
530     };
531 
532     struct FileBlock
533     {
534         ut::BinaryBlockHeader   header;
535         FileBlockBody           body;
536     };
537 
538 };
539 
540 } // namespace nw::snd::internal
541 } // namespace nw::snd
542 } // namespace nw
543 
544 #endif /* NW_SND_SOUND_ARCHIVE_FILE_H_ */
545 
546