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