1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundArchiveFileReader.cpp
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 #include "precompiled.h"
19 #include <nw/snd/snd_SoundArchiveFileReader.h>
20 #include <nw/snd/snd_ItemType.h>
21 
22 namespace nw {
23 namespace snd {
24 namespace internal {
25 
26 namespace {
27 
28 const u32 SIGNATURE_STRING_BLOCK    = NW_UT_MAKE_SIGWORD( 'S', 'T', 'R', 'G' );
29 const u32 SIGNATURE_INFO_BLOCK      = NW_UT_MAKE_SIGWORD( 'I', 'N', 'F', 'O' );
30 const u32 SIGNATURE_DATA_BLOCK      = NW_UT_MAKE_SIGWORD( 'D', 'A', 'T', 'A' );
31 const u32 SUPPORTED_FILE_VERSION    = 0x02000000;
32 const u32 CURRENT_FILE_VERSION      = 0x02000000;
33 
IsValidFileHeader(const void * soundArchiveData)34 bool IsValidFileHeader( const void* soundArchiveData )
35 {
36     const ut::BinaryFileHeader& header =
37         *reinterpret_cast<const ut::BinaryFileHeader*>( soundArchiveData );
38 
39     // シグニチャ確認
40     NW_ASSERTMSG( header.signature == SoundArchiveFileReader::SIGNATURE_FILE,
41             "invalid file signature." );
42     if ( header.signature != SoundArchiveFileReader::SIGNATURE_FILE )
43     {
44         return false;
45     }
46 
47     // バージョン確認
48     NW_ASSERTMSG(
49             header.version >= SUPPORTED_FILE_VERSION,
50             "sound archive file is not supported version.\n"
51             "please reconvert file using new version tools.\n"
52             "(SUPPORTED_FILE_VERSION:0x%08x >= your version:0x%08x)\n",
53             SUPPORTED_FILE_VERSION, header.version
54     );
55     if ( header.version < SUPPORTED_FILE_VERSION )
56     {
57         return false;
58     }
59     NW_ASSERTMSG(
60             header.version <= CURRENT_FILE_VERSION,
61             "sound archive file is not supported version.\n"
62             "please reconvert file using new version tools.\n"
63             "(CURRENT_FILE_VERSION:0x%08x <= your version:0x%08x)\n",
64             CURRENT_FILE_VERSION, header.version
65     );
66     if ( header.version > CURRENT_FILE_VERSION )
67     {
68         return false;
69     }
70     return true;
71 }
72 
73 } // anonymous namespace
74 
SoundArchiveFileReader()75 SoundArchiveFileReader::SoundArchiveFileReader()
76 : m_pStringBlockBody( NULL ),
77   m_pInfoBlockBody( NULL ),
78   m_pFileBlockBody( NULL )
79 {
80 }
81 
Initialize(const void * soundArchiveData)82 void SoundArchiveFileReader::Initialize( const void* soundArchiveData )
83 {
84     NW_NULL_ASSERT( soundArchiveData );
85     if ( ! IsValidFileHeader( soundArchiveData ) ) return;
86 
87     const SoundArchiveFile::FileHeader& header =
88         *reinterpret_cast<const SoundArchiveFile::FileHeader*>( soundArchiveData );
89     m_Header = header;  // 構造体コピー
90 }
91 
Finalize()92 void SoundArchiveFileReader::Finalize()
93 {
94     m_pStringBlockBody = NULL;
95     m_pInfoBlockBody = NULL;
96     m_pFileBlockBody = NULL;
97 }
98 
SetStringBlock(const void * stringBlock)99 void SoundArchiveFileReader::SetStringBlock( const void* stringBlock )
100 {
101     m_pStringBlockBody =
102         &reinterpret_cast<const SoundArchiveFile::StringBlock*>( stringBlock )->body;
103 }
104 
SetInfoBlock(const void * infoBlock)105 void SoundArchiveFileReader::SetInfoBlock( const void* infoBlock )
106 {
107     m_pInfoBlockBody =
108         &reinterpret_cast<const SoundArchiveFile::InfoBlock*>( infoBlock )->body;
109 }
110 
GetStringCount() const111 u32 SoundArchiveFileReader::GetStringCount() const
112 {
113     NW_NULL_ASSERT( m_pStringBlockBody );
114     return m_pStringBlockBody->GetStringCount();
115 }
GetString(SoundArchive::ItemId stringId) const116 const char* SoundArchiveFileReader::GetString( SoundArchive::ItemId stringId ) const
117 {
118     NW_NULL_ASSERT( m_pStringBlockBody );
119     return m_pStringBlockBody->GetString( stringId );
120 }
121 
DumpTree() const122 void SoundArchiveFileReader::DumpTree() const
123 {
124     NW_NULL_ASSERT( m_pStringBlockBody );
125     m_pStringBlockBody->DumpTree();
126 }
127 
GetItemId(const char * pStr) const128 SoundArchive::ItemId SoundArchiveFileReader::GetItemId( const char* pStr ) const
129 {
130     if ( m_pStringBlockBody == NULL )
131     {
132         return SoundArchive::INVALID_ID;
133     }
134     return m_pStringBlockBody->GetItemId( pStr );
135 }
GetItemLabel(SoundArchive::ItemId id) const136 const char* SoundArchiveFileReader::GetItemLabel( SoundArchive::ItemId id ) const
137 {
138     NW_NULL_ASSERT( m_pInfoBlockBody );
139     if ( m_pStringBlockBody == NULL )
140     {
141         return NULL;
142     }
143     SoundArchive::StringId stringId = m_pInfoBlockBody->GetItemStringId( id );
144     if ( stringId == SoundArchive::INVALID_ID )
145     {
146         return NULL;
147     }
148     return m_pStringBlockBody->GetString( stringId );
149 }
GetItemFileId(SoundArchive::ItemId id) const150 SoundArchive::FileId SoundArchiveFileReader::GetItemFileId( SoundArchive::ItemId id ) const
151 {
152     NW_NULL_ASSERT( m_pInfoBlockBody );
153     return m_pInfoBlockBody->GetItemFileId( id );
154 }
155 
GetSoundCount() const156 u32 SoundArchiveFileReader::GetSoundCount() const
157 {
158     NW_NULL_ASSERT( m_pInfoBlockBody );
159     return m_pInfoBlockBody->GetSoundCount();
160 }
161 
GetBankCount() const162 u32 SoundArchiveFileReader::GetBankCount() const
163 {
164     NW_NULL_ASSERT( m_pInfoBlockBody );
165     return m_pInfoBlockBody->GetBankCount();
166 }
167 
GetPlayerCount() const168 u32 SoundArchiveFileReader::GetPlayerCount() const
169 {
170     NW_NULL_ASSERT( m_pInfoBlockBody );
171     return m_pInfoBlockBody->GetPlayerCount();
172 }
173 
GetSoundGroupCount() const174 u32 SoundArchiveFileReader::GetSoundGroupCount() const
175 {
176     NW_NULL_ASSERT( m_pInfoBlockBody );
177     return m_pInfoBlockBody->GetSoundGroupCount();
178 }
179 
GetGroupCount() const180 u32 SoundArchiveFileReader::GetGroupCount() const
181 {
182     NW_NULL_ASSERT( m_pInfoBlockBody );
183     return m_pInfoBlockBody->GetGroupCount();
184 }
185 
GetWaveArchiveCount() const186 u32 SoundArchiveFileReader::GetWaveArchiveCount() const
187 {
188     NW_NULL_ASSERT( m_pInfoBlockBody );
189     return m_pInfoBlockBody->GetWaveArchiveCount();
190 }
191 
GetFileCount() const192 u32 SoundArchiveFileReader::GetFileCount() const
193 {
194     NW_NULL_ASSERT( m_pInfoBlockBody );
195     return m_pInfoBlockBody->GetFileCount();
196 }
197 
ReadSoundInfo(SoundArchive::ItemId soundId,SoundArchive::SoundInfo * info) const198 bool SoundArchiveFileReader::ReadSoundInfo(
199         SoundArchive::ItemId soundId, SoundArchive::SoundInfo* info ) const
200 {
201     NW_NULL_ASSERT( m_pInfoBlockBody );
202     NW_NULL_ASSERT( info );
203 
204     const SoundArchiveFile::SoundInfo* data = m_pInfoBlockBody->GetSoundInfo( soundId );
205     if ( data == NULL ) return false;
206 
207     info->fileId = data->fileId;
208     info->playerId = data->playerId;
209     info->volume = data->volume;
210     info->panMode = data->GetPanMode();
211     info->panCurve = data->GetPanCurve();
212     info->playerPriority = data->GetPlayerPriority();
213     info->actorPlayerId = data->GetActorPlayerId();
214     info->isFrontBypass = data->IsFrontBypass();
215 
216     return true;
217 }
218 
ReadBankInfo(SoundArchive::ItemId bankId,SoundArchive::BankInfo * info) const219 bool SoundArchiveFileReader::ReadBankInfo(
220         SoundArchive::ItemId bankId, SoundArchive::BankInfo* info ) const
221 {
222     NW_NULL_ASSERT( m_pInfoBlockBody );
223     NW_NULL_ASSERT( info );
224 
225     const SoundArchiveFile::BankInfo* data = m_pInfoBlockBody->GetBankInfo( bankId );
226     if ( data == NULL ) return false;
227 
228     info->fileId = data->fileId;
229     return true;
230 }
231 
ReadPlayerInfo(SoundArchive::ItemId playerId,SoundArchive::PlayerInfo * info) const232 bool SoundArchiveFileReader::ReadPlayerInfo(
233         SoundArchive::ItemId playerId, SoundArchive::PlayerInfo* info ) const
234 {
235     NW_NULL_ASSERT( m_pInfoBlockBody );
236     NW_NULL_ASSERT( info );
237 
238     const SoundArchiveFile::PlayerInfo* data = m_pInfoBlockBody->GetPlayerInfo( playerId );
239     if ( data == NULL ) return false;
240 
241     info->playableSoundMax = data->playableSoundMax;
242     info->playerHeapSize = data->GetPlayerHeapSize();
243 
244     return true;
245 }
246 
ReadSoundGroupInfo(SoundArchive::ItemId soundGroupId,SoundArchive::SoundGroupInfo * info) const247 bool SoundArchiveFileReader::ReadSoundGroupInfo(
248         SoundArchive::ItemId soundGroupId, SoundArchive::SoundGroupInfo* info ) const
249 {
250     NW_NULL_ASSERT( m_pInfoBlockBody );
251     NW_NULL_ASSERT( info );
252 
253     const SoundArchiveFile::SoundGroupInfo* data = m_pInfoBlockBody->GetSoundGroupInfo( soundGroupId );
254     if ( data == NULL ) return false;
255 
256     info->startId = data->startId;
257     info->endId = data->endId;
258     info->fileIdTable = data->GetFileIdTable();
259     return true;
260 }
261 
ReadGroupInfo(SoundArchive::ItemId groupId,SoundArchive::GroupInfo * info) const262 bool SoundArchiveFileReader::ReadGroupInfo(
263         SoundArchive::ItemId groupId, SoundArchive::GroupInfo* info ) const
264 {
265     NW_NULL_ASSERT( m_pInfoBlockBody );
266     NW_NULL_ASSERT( info );
267 
268     const SoundArchiveFile::GroupInfo* data = m_pInfoBlockBody->GetGroupInfo( groupId );
269     if ( data == NULL ) return false;
270 
271     info->fileId = data->fileId;
272     return true;
273 }
274 
ReadWaveArchiveInfo(SoundArchive::ItemId warcId,SoundArchive::WaveArchiveInfo * info) const275 bool SoundArchiveFileReader::ReadWaveArchiveInfo(
276         SoundArchive::ItemId warcId, SoundArchive::WaveArchiveInfo* info ) const
277 {
278     NW_NULL_ASSERT( m_pInfoBlockBody );
279     NW_NULL_ASSERT( info );
280 
281     const SoundArchiveFile::WaveArchiveInfo* data = m_pInfoBlockBody->GetWaveArchiveInfo( warcId );
282     if ( data == NULL ) return false;
283 
284     info->fileId = data->fileId;
285     info->waveCount = data->GetWaveCount();
286     info->isLoadIndividual = data->isLoadIndividual;
287     return true;
288 }
289 
ReadFileInfo(SoundArchive::FileId id,SoundArchive::FileInfo * info,int index) const290 bool SoundArchiveFileReader::ReadFileInfo(
291         SoundArchive::FileId id, SoundArchive::FileInfo* info, int index ) const
292 {
293     NW_NULL_ASSERT( m_pInfoBlockBody );
294     NW_NULL_ASSERT( info );
295     NW_UNUSED_VARIABLE( index );
296 
297     const SoundArchiveFile::FileInfo* data = m_pInfoBlockBody->GetFileInfo( id );
298     if ( data == NULL ) return false;
299 
300     switch ( data->GetFileLocationType() )
301     {
302         case SoundArchiveFile::FILE_LOCATION_TYPE_INTERNAL:
303             {
304                 const SoundArchiveFile::InternalFileInfo* location = data->GetInternalFileInfo();
305                 info->fileSize = location->GetFileSize();
306                 info->offsetFromFileBlockHead = location->GetOffsetFromFileBlockHead();
307             }
308             break;
309         case SoundArchiveFile::FILE_LOCATION_TYPE_EXTERNAL:
310             {
311                 const SoundArchiveFile::ExternalFileInfo* location = data->GetExternalFileInfo();
312                 info->externalFilePath = location->filePath;
313             }
314             break;
315         case SoundArchiveFile::FILE_LOCATION_TYPE_NONE:
316             return false;
317     }
318     return true;
319 }
320 
ReadSoundArchivePlayerInfo(SoundArchive::SoundArchivePlayerInfo * info) const321 bool SoundArchiveFileReader::ReadSoundArchivePlayerInfo(
322         SoundArchive::SoundArchivePlayerInfo* info ) const
323 {
324     NW_NULL_ASSERT( m_pInfoBlockBody );
325     NW_NULL_ASSERT( info );
326 
327     const SoundArchiveFile::SoundArchivePlayerInfo* data = m_pInfoBlockBody->GetSoundArchivePlayerInfo();
328     if ( data == NULL ) return false;
329 
330     info->sequenceSoundMax = data->sequenceSoundMax;
331     info->sequenceTrackMax = data->sequenceTrackMax;
332     info->streamSoundMax   = data->streamSoundMax;
333     info->streamTrackMax   = data->streamTrackMax;
334     info->streamChannelMax = data->streamChannelMax;
335     info->waveSoundMax     = data->waveSoundMax;
336     info->waveTrackMax     = data->waveTrackmax;
337     return true;
338 }
339 
ReadSound3DInfo(SoundArchive::ItemId soundId,SoundArchive::Sound3DInfo * info) const340 bool SoundArchiveFileReader::ReadSound3DInfo(
341         SoundArchive::ItemId soundId, SoundArchive::Sound3DInfo* info ) const
342 {
343     NW_NULL_ASSERT( m_pInfoBlockBody );
344     NW_NULL_ASSERT( info );
345 
346     const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
347     if ( soundInfo == NULL )
348     {
349         return false;
350     }
351 
352     const SoundArchiveFile::Sound3DInfo* sound3dInfo = soundInfo->GetSound3DInfo();
353     if ( sound3dInfo == NULL )
354     {
355         return false;
356     }
357     info->flags = sound3dInfo->flags;
358     info->decayRatio = sound3dInfo->decayRatio;
359     info->decayCurve = sound3dInfo->decayCurve;
360     info->dopplerFactor = sound3dInfo->dopplerFactor;
361     return true;
362 }
363 
ReadSequenceSoundInfo(SoundArchive::ItemId soundId,SoundArchive::SequenceSoundInfo * info) const364 bool SoundArchiveFileReader::ReadSequenceSoundInfo(
365         SoundArchive::ItemId soundId, SoundArchive::SequenceSoundInfo* info ) const
366 {
367     NW_NULL_ASSERT( m_pInfoBlockBody );
368     NW_NULL_ASSERT( info );
369 
370     const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
371     if ( soundInfo == NULL )
372     {
373         return false;
374     }
375     if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_SEQ )
376     {
377         return false;
378     }
379 
380     const SoundArchiveFile::SequenceSoundInfo& seqSoundInfo = soundInfo->GetSequenceSoundInfo();
381     info->startOffset = seqSoundInfo.GetStartOffset();
382     info->allocateTrackFlags = seqSoundInfo.allocateTrackFlags;
383     info->channelPriority = seqSoundInfo.GetChannelPriority();
384     info->isReleasePriorityFix = seqSoundInfo.IsReleasePriorityFix();
385     seqSoundInfo.GetBankIds( info->bankIds );
386     return true;
387 }
388 
ReadStreamSoundInfo(SoundArchive::ItemId soundId,SoundArchive::StreamSoundInfo * info) const389 bool SoundArchiveFileReader::ReadStreamSoundInfo(
390         SoundArchive::ItemId soundId, SoundArchive::StreamSoundInfo* info ) const
391 {
392     NW_NULL_ASSERT( m_pInfoBlockBody );
393     NW_NULL_ASSERT( info );
394 
395     const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
396     if ( soundInfo == NULL )
397     {
398         return false;
399     }
400     if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_STRM )
401     {
402         return false;
403     }
404 
405     const SoundArchiveFile::StreamSoundInfo& strmSoundInfo = soundInfo->GetStreamSoundInfo();
406     info->allocTrackCount   = strmSoundInfo.allocTrackCount;
407     info->allocChannelCount = strmSoundInfo.allocChannelCount;
408     return true;
409 }
410 
ReadWaveSoundInfo(SoundArchive::ItemId soundId,SoundArchive::WaveSoundInfo * info) const411 bool SoundArchiveFileReader::ReadWaveSoundInfo(
412         SoundArchive::ItemId soundId, SoundArchive::WaveSoundInfo* info ) const
413 {
414     NW_NULL_ASSERT( m_pInfoBlockBody );
415     NW_NULL_ASSERT( info );
416 
417     const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
418     if ( soundInfo == NULL )
419     {
420         return false;
421     }
422     if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_WAVE )
423     {
424         return false;
425     }
426 
427     const SoundArchiveFile::WaveSoundInfo& waveSoundInfo = soundInfo->GetWaveSoundInfo();
428     info->index                 = waveSoundInfo.index;
429     info->allocTrackCount       = waveSoundInfo.allocTrackCount;
430     info->channelPriority       = waveSoundInfo.GetChannelPriority();
431     info->isReleasePriorityFix  = waveSoundInfo.GetIsReleasePriorityFix() > 0 ? true : false;
432 
433     return true;
434 }
435 
436 const internal::Util::Table<u32>*
GetWaveArchiveIdTable(SoundArchive::ItemId id) const437 SoundArchiveFileReader::GetWaveArchiveIdTable( SoundArchive::ItemId id ) const
438 {
439     NW_NULL_ASSERT( m_pInfoBlockBody );
440 
441     switch ( Util::GetItemType( id ) )
442     {
443         case ItemType_Sound:
444             {
445                 const SoundArchiveFile::SoundInfo* pInfo =
446                     m_pInfoBlockBody->GetSoundInfo( id );
447                 NW_NULL_ASSERT( pInfo );
448 
449                 if ( pInfo->GetSoundType() == SoundArchive::SOUND_TYPE_WAVE )
450                 {
451                     // ウェーブサウンド ID → ウェーブサウンドセット ID を引く
452                     for ( u32 i = 0; i < m_pInfoBlockBody->GetSoundGroupCount(); i++ )
453                     {
454                         const SoundArchiveFile::SoundGroupInfo* pGroupInfo =
455                             m_pInfoBlockBody->GetSoundGroupInfo(
456                                     Util::GetMaskedItemId( i, ItemType_SoundGroup ) );
457                         NW_NULL_ASSERT( pGroupInfo );
458 
459                         if ( id < pGroupInfo->startId || pGroupInfo->endId < id )
460                         {
461                             continue;
462                         }
463 
464                         // 該当するウェーブサウンドセットの波形アーカイブテーブルを返す
465                         const SoundArchiveFile::WaveSoundGroupInfo*
466                             pWaveSoundGroupInfo = pGroupInfo->GetWaveSoundGroupInfo();
467                         NW_NULL_ASSERT( pWaveSoundGroupInfo );
468 
469                         return pWaveSoundGroupInfo->GetWaveArchiveItemIdTable();
470                     }
471                 }
472                 return NULL;
473             }
474         case ItemType_SoundGroup:
475             {
476                 const SoundArchiveFile::SoundGroupInfo* pInfo =
477                     m_pInfoBlockBody->GetSoundGroupInfo( id );
478                 NW_NULL_ASSERT( pInfo );
479 
480                 const SoundArchiveFile::WaveSoundGroupInfo*
481                     pWaveSoundGroupInfo = pInfo->GetWaveSoundGroupInfo();
482                 NW_NULL_ASSERT( pWaveSoundGroupInfo );
483 
484                 return pWaveSoundGroupInfo->GetWaveArchiveItemIdTable();
485             }
486         case ItemType_Bank:
487             {
488                 const SoundArchiveFile::BankInfo* pInfo =
489                     m_pInfoBlockBody->GetBankInfo( id );
490                 NW_NULL_ASSERT( pInfo );
491 
492                 return pInfo->GetWaveArchiveItemIdTable();
493             }
494         default:
495             return NULL;
496     }
497 }
498 
499 SoundArchive::SoundType
GetSoundType(SoundArchive::ItemId soundId) const500 SoundArchiveFileReader::GetSoundType( SoundArchive::ItemId soundId ) const
501 {
502     NW_NULL_ASSERT( m_pInfoBlockBody );
503 
504     const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
505     NW_NULL_ASSERT( soundInfo );
506     return soundInfo->GetSoundType();
507 }
508 
509 u32
GetSoundUserParam(SoundArchive::ItemId soundId) const510 SoundArchiveFileReader::GetSoundUserParam( SoundArchive::ItemId soundId ) const
511 {
512     NW_NULL_ASSERT( m_pInfoBlockBody );
513 
514     const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
515     NW_NULL_ASSERT( soundInfo );
516     return soundInfo->GetUserParam();
517 }
518 
519 
520 } // namespace nw::snd::internal
521 } // namespace nw::snd
522 } // namespace nw
523