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