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