1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_SoundArchiveLoader.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: 28259 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/snd/snd_SoundArchiveLoader.h>
19 #include <nw/snd/snd_SoundMemoryAllocatable.h>
20
21 // #define NW_SND_DEBUG_PRINT_ENABLE
22
23 #ifdef NW_SND_DEBUG_PRINT_ENABLE
24 #include <nw/snd/snd_GroupFileReader.h>
25 #endif
26
27 namespace nw {
28 namespace snd {
29 namespace internal {
30
31 namespace
32 {
33
34 const u32 REQUIRED_SIZE_FOR_LOAD_WARC_FILE_HEADER =
35 NW_SND_ROUND_UP_32B( sizeof( internal::WaveArchiveFile::FileHeader ) + 32 );
36 // 32 バイトごとに読むため
37
38 class FileStreamHandle
39 {
40 public:
FileStreamHandle(io::FileStream * stream)41 FileStreamHandle( io::FileStream* stream ) : m_pStream( stream ) { }
~FileStreamHandle()42 ~FileStreamHandle() { if ( m_pStream != NULL ) m_pStream->Close(); }
43
GetFileStream()44 io::FileStream* GetFileStream() { return m_pStream; }
operator ->()45 io::FileStream* operator->() { return m_pStream; }
operator bool() const46 operator bool() const { return m_pStream != NULL; }
47
48 private:
49 io::FileStream* m_pStream;
50 };
51
52 } // anonymous namespace
53
54 /*---------------------------------------------------------------------------*
55 Name: SoundArchiveLoader
56
57 Description: コンストラクタ
58
59 Arguments: arc - ローダで使用するサウンドアーカイブ
60
61 Returns: なし
62 *---------------------------------------------------------------------------*/
SoundArchiveLoader()63 SoundArchiveLoader::SoundArchiveLoader()
64 : m_pSoundArchive( NULL )
65 {
66 }
67
68 /*---------------------------------------------------------------------------*
69 Name: SoundArchiveLoader
70
71 Description: デストラクタ
72
73 Arguments: なし
74
75 Returns: なし
76 *---------------------------------------------------------------------------*/
~SoundArchiveLoader()77 SoundArchiveLoader::~SoundArchiveLoader()
78 {
79 m_pSoundArchive = NULL;
80 }
81
SetSoundArchive(const SoundArchive * arc)82 void SoundArchiveLoader::SetSoundArchive( const SoundArchive* arc )
83 {
84 m_pSoundArchive = arc;
85 }
86
87
88 /*---------------------------------------------------------------------------*
89 Name: IsAvailable
90
91 Description: サウンドアーカイブプレイヤーが利用可能かどうかを調べる
92
93 Arguments: 無し
94
95 Returns: 利用可能かどうかを返す
96 *---------------------------------------------------------------------------*/
IsAvailable() const97 bool SoundArchiveLoader::IsAvailable() const
98 {
99 if ( m_pSoundArchive == NULL )
100 {
101 return false;
102 }
103 if ( ! m_pSoundArchive->IsAvailable() )
104 {
105 return false;
106 }
107
108 return true;
109 }
110
LoadData(SoundArchive::ItemId itemId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)111 bool SoundArchiveLoader::LoadData(
112 SoundArchive::ItemId itemId,
113 SoundMemoryAllocatable* pAllocator,
114 u32 loadFlag,
115 size_t loadBlockSize )
116 {
117 NW_NULL_ASSERT( m_pSoundArchive );
118 NW_ALIGN32_ASSERT( loadBlockSize );
119
120 if ( ! IsAvailable() )
121 {
122 return false;
123 }
124 if ( itemId == SoundArchive::INVALID_ID )
125 {
126 return false;
127 }
128 if ( pAllocator == NULL )
129 {
130 return false;
131 }
132
133 switch ( internal::Util::GetItemType( itemId ) )
134 {
135 case internal::ItemType_Sound:
136 switch ( m_pSoundArchive->GetSoundType( itemId ) )
137 {
138 case SoundArchive::SOUND_TYPE_SEQ:
139 return LoadSequenceSound( itemId, pAllocator, loadFlag, loadBlockSize );
140 case SoundArchive::SOUND_TYPE_WAVE:
141 return LoadWaveSound( itemId, pAllocator, loadFlag, loadBlockSize );
142 case SoundArchive::SOUND_TYPE_STRM:
143 default:
144 return false;
145 }
146 case internal::ItemType_Bank:
147 return LoadBank( itemId, pAllocator, loadFlag, loadBlockSize );
148 case internal::ItemType_WaveArchive:
149 return LoadWaveArchive( itemId, pAllocator, loadFlag, loadBlockSize );
150 case internal::ItemType_Group:
151 return LoadGroup( itemId, pAllocator, loadBlockSize );
152 case internal::ItemType_SoundGroup:
153 return LoadSoundGroup( itemId, pAllocator, loadFlag, loadBlockSize );
154 case internal::ItemType_Player:
155 default:
156 return false;
157 }
158 }
159
LoadData(const char * pItemName,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)160 bool SoundArchiveLoader::LoadData(
161 const char* pItemName,
162 SoundMemoryAllocatable* pAllocator,
163 u32 loadFlag,
164 size_t loadBlockSize )
165 {
166 NW_NULL_ASSERT( m_pSoundArchive );
167
168 SoundArchive::ItemId id = m_pSoundArchive->GetItemId( pItemName );
169 return LoadData( id, pAllocator, loadFlag, loadBlockSize );
170 }
171
172
LoadImpl(SoundArchive::FileId fileId,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize,bool needDeviceMemory)173 const void* SoundArchiveLoader::LoadImpl(
174 SoundArchive::FileId fileId,
175 SoundMemoryAllocatable* pAllocator,
176 size_t loadBlockSize,
177 bool needDeviceMemory )
178 {
179 NW_NULL_ASSERT( m_pSoundArchive );
180 NW_UNUSED_VARIABLE( loadBlockSize );
181
182 const void* fileAddress = GetFileAddressImpl( fileId );
183 // 未ロードの場合
184 if ( fileAddress == NULL )
185 {
186 fileAddress = LoadFile( fileId, pAllocator, loadBlockSize, needDeviceMemory );
187 if ( fileAddress == NULL )
188 {
189 return NULL; // ロード失敗
190 }
191 else
192 {
193 SetFileAddressToTable( fileId, fileAddress );
194 return fileAddress;
195 }
196 }
197 // ロード済みだった場合
198 else
199 {
200 return fileAddress;
201 }
202 }
203
LoadSequenceSound(SoundArchive::ItemId soundId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)204 bool SoundArchiveLoader::LoadSequenceSound(
205 SoundArchive::ItemId soundId,
206 SoundMemoryAllocatable* pAllocator,
207 u32 loadFlag,
208 size_t loadBlockSize )
209 {
210 if ( loadFlag & LOAD_SEQ )
211 {
212 u32 fileId = m_pSoundArchive->GetItemFileId( soundId );
213 const void* pFile = LoadImpl( fileId, pAllocator, loadBlockSize );
214 if ( pFile == NULL )
215 {
216 return false; // ロード失敗
217 }
218 }
219
220 if ( loadFlag & LOAD_BANK || loadFlag & LOAD_WARC )
221 {
222 SoundArchive::SequenceSoundInfo info;
223 if ( ! m_pSoundArchive->ReadSequenceSoundInfo( soundId, &info ) )
224 {
225 return false; // INFO ブロックからシーケンスサウンド情報が得られなかった
226 }
227
228 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
229 {
230 u32 bankId = info.bankIds[ i ];
231 if ( bankId != SoundArchive::INVALID_ID )
232 {
233 if ( ! LoadBank( bankId, pAllocator, loadFlag, loadBlockSize ) )
234 {
235 return false;
236 }
237 }
238 }
239 }
240
241 return true;
242 }
243
LoadWaveSound(SoundArchive::ItemId soundId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize,SoundArchive::ItemId waveSoundSetId)244 bool SoundArchiveLoader::LoadWaveSound(
245 SoundArchive::ItemId soundId,
246 SoundMemoryAllocatable* pAllocator,
247 u32 loadFlag,
248 size_t loadBlockSize,
249 SoundArchive::ItemId waveSoundSetId )
250 {
251 u32 wsdFileId = m_pSoundArchive->GetItemFileId( soundId );
252 if ( loadFlag & LOAD_WSD )
253 {
254 const void* pFile = LoadImpl( wsdFileId, pAllocator, loadBlockSize );
255 if ( pFile == NULL )
256 {
257 return false; // ロード失敗
258 }
259 }
260
261 if ( loadFlag & LOAD_WARC )
262 {
263 const void* pWsdFile = GetFileAddressImpl( wsdFileId );
264
265 // ウェーブサウンドセットファイルがロード済みなら、
266 // 必要に応じて個別ロードを行う
267 if ( pWsdFile != NULL )
268 {
269 // bcwsd 内でのインデックス取得
270 u32 index;
271 {
272 SoundArchive::WaveSoundInfo info;
273 if ( ! m_pSoundArchive->detail_ReadWaveSoundInfo( soundId, &info ) )
274 {
275 return false; // WaveSoundInfo 取得失敗
276 }
277 index = info.index;
278 }
279 // 関連する波形アーカイブ ID を取得
280 u32 warcId = SoundArchive::INVALID_ID;
281 u32 waveIndex;
282 {
283 internal::WaveSoundFileReader reader( pWsdFile );
284 internal::WaveSoundNoteInfo info;
285 if ( ! reader.ReadNoteInfo( &info, index, 0 ) )
286 {
287 return false; // NoteInfo 取得失敗
288 }
289 warcId = info.waveArchiveId;
290 waveIndex = info.waveIndex;
291 }
292 // ロード
293 if ( ! LoadWaveArchiveImpl(
294 warcId,
295 waveIndex,
296 pAllocator,
297 loadFlag,
298 loadBlockSize ) )
299 {
300 return false;
301 }
302 }
303 // 未ロードの場合は、一括ロードのみ行う
304 else
305 {
306 SoundArchive::ItemId itemId;
307 if ( waveSoundSetId != SoundArchive::INVALID_ID )
308 {
309 itemId = waveSoundSetId;
310 /* ウェーブサウンド ID → ウェーブサウンドセット ID への変換は
311 時間がかかるので、あらかじめ waveSoundSetId を渡してもらえる場合は
312 これを利用する */
313 }
314 else
315 {
316 itemId = soundId;
317 }
318 const internal::Util::Table<u32>* pWarcIdTable =
319 m_pSoundArchive->detail_GetWaveArchiveIdTable( itemId );
320
321 NW_NULL_ASSERT( pWarcIdTable );
322
323 for ( u32 i = 0; i < pWarcIdTable->count; i++ )
324 {
325 if ( ! LoadWaveArchive(
326 pWarcIdTable->item[ i ],
327 pAllocator,
328 loadFlag,
329 loadBlockSize ) )
330 {
331 return false;
332 }
333 }
334 }
335 }
336 return true;
337 }
338
LoadBank(SoundArchive::ItemId bankId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)339 bool SoundArchiveLoader::LoadBank(
340 SoundArchive::ItemId bankId,
341 SoundMemoryAllocatable* pAllocator,
342 u32 loadFlag,
343 size_t loadBlockSize )
344 {
345 u32 bankFileId = m_pSoundArchive->GetItemFileId( bankId );
346 if ( loadFlag & LOAD_BANK )
347 {
348 const void* pFile = LoadImpl( bankFileId, pAllocator, loadBlockSize );
349 if ( pFile == NULL )
350 {
351 return false; // ロード失敗
352 }
353 }
354
355 if ( loadFlag & LOAD_WARC )
356 {
357 const void* pFile = GetFileAddressImpl( bankFileId );
358
359 // バンクがロード済みなら、必要に応じて個別ロードを行う
360 if ( pFile != NULL )
361 {
362 internal::BankFileReader reader( pFile );
363 const internal::Util::WaveIdTable& table = reader.GetWaveIdTable();
364
365 for ( u32 i = 0; i < table.GetCount(); i++ )
366 {
367 const internal::Util::WaveId& waveId = table.GetWaveId( i );
368 if ( ! LoadWaveArchiveImpl(
369 waveId.waveArchiveId,
370 waveId.waveIndex,
371 pAllocator,
372 loadFlag,
373 loadBlockSize ) )
374 {
375 return false;
376 }
377 }
378 }
379 // バンクが未ロードの場合は、一括ロードのみ行う
380 else
381 {
382 const internal::Util::Table<ut::ResU32>* pWarcIdTable =
383 m_pSoundArchive->detail_GetWaveArchiveIdTable( bankId );
384
385 NW_NULL_ASSERT( pWarcIdTable );
386
387 for ( u32 i = 0; i < pWarcIdTable->count; i++ )
388 {
389 if ( ! LoadWaveArchive(
390 pWarcIdTable->item[ i ],
391 pAllocator,
392 loadFlag,
393 loadBlockSize ) )
394 {
395 return false;
396 }
397 }
398 }
399 }
400 return true;
401 }
402
LoadWaveArchiveImpl(SoundArchive::ItemId warcId,u32 waveIndex,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)403 bool SoundArchiveLoader::LoadWaveArchiveImpl(
404 SoundArchive::ItemId warcId,
405 u32 waveIndex,
406 SoundMemoryAllocatable* pAllocator,
407 u32 loadFlag,
408 size_t loadBlockSize )
409 {
410 SoundArchive::WaveArchiveInfo info;
411 if ( ! m_pSoundArchive->ReadWaveArchiveInfo( warcId, &info ) )
412 {
413 return false;
414 }
415 if ( info.isLoadIndividual )
416 {
417 // 波形のロード
418 if ( ! LoadIndividualWave(
419 warcId,
420 waveIndex,
421 pAllocator,
422 loadBlockSize ) )
423 {
424 return false;
425 }
426 }
427 else
428 {
429 if ( ! LoadWaveArchive(
430 warcId,
431 pAllocator,
432 loadFlag,
433 loadBlockSize ) )
434 {
435 return false;
436 }
437 }
438 return true;
439 }
440
441 // 波形アーカイブの一括ロード
LoadWaveArchive(SoundArchive::ItemId warcId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)442 bool SoundArchiveLoader::LoadWaveArchive(
443 SoundArchive::ItemId warcId,
444 SoundMemoryAllocatable* pAllocator,
445 u32 loadFlag,
446 size_t loadBlockSize )
447 {
448 if ( loadFlag & LOAD_WARC )
449 {
450 u32 fileId = m_pSoundArchive->GetItemFileId( warcId );
451 // 要デバイスメモリ
452 const void* pFile = LoadImpl( fileId, pAllocator, loadBlockSize, true );
453 if ( pFile == NULL )
454 {
455 return false; // ロード失敗
456 }
457 }
458 return true;
459 }
460
LoadWaveArchiveTable(SoundArchive::ItemId warcId,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)461 const void* SoundArchiveLoader::LoadWaveArchiveTable(
462 SoundArchive::ItemId warcId,
463 SoundMemoryAllocatable* pAllocator,
464 size_t loadBlockSize )
465 {
466 u32 fileId = m_pSoundArchive->GetItemFileId( warcId );
467 const void* pWaveArchiveFile = GetFileAddressFromTable( fileId );
468 if ( pWaveArchiveFile != NULL )
469 {
470 return pWaveArchiveFile;
471 }
472
473 // 波形ファイル数
474 u32 waveCount;
475 {
476 SoundArchive::WaveArchiveInfo info;
477 if ( ! m_pSoundArchive->ReadWaveArchiveInfo( warcId, &info ) )
478 {
479 return NULL;
480 }
481 if ( info.waveCount <= 0 )
482 {
483 return NULL;
484 }
485 waveCount = info.waveCount;
486 }
487
488 // ファイルブロック手前までのオフセット
489 u32 fileBlockOffset;
490 {
491 u8 pBuffer[ REQUIRED_SIZE_FOR_LOAD_WARC_FILE_HEADER ];
492 u8* pAlignedBuffer = reinterpret_cast<u8*>( ut::RoundUp( pBuffer, 32 ) );
493 s32 readSize = ReadFile(
494 fileId,
495 pAlignedBuffer,
496 sizeof(internal::WaveArchiveFile::FileHeader),
497 0,
498 loadBlockSize );
499 if ( readSize != sizeof(internal::WaveArchiveFile::FileHeader) )
500 {
501 return NULL;
502 }
503 const internal::WaveArchiveFile::FileHeader* pHeader =
504 reinterpret_cast<const internal::WaveArchiveFile::FileHeader*>( pAlignedBuffer );
505 fileBlockOffset = pHeader->GetFileBlockOffset();
506 u32 infoBlockOffset = pHeader->GetInfoBlockOffset();
507 if ( infoBlockOffset > fileBlockOffset )
508 {
509 return NULL; // INFO ブロック → FILE ブロックの順に並んでいる必要がある
510 }
511 }
512
513 // ロード用テーブルを含めたヒープサイズ
514 const u32 REQUIRED_SIZE =
515 fileBlockOffset +
516 waveCount * sizeof( u32 ) +
517 sizeof( internal::WaveArchiveFileReader::SIGNATURE_WARC_TABLE );
518
519 void* buffer = pAllocator->Alloc( REQUIRED_SIZE );
520 if ( ! internal::Util::IsDeviceMemory( reinterpret_cast<uptr>(buffer), REQUIRED_SIZE ) )
521 {
522 NW_ASSERTMSG( false, "buffer, buffer + REQUIRED_SIZE is not Device Memory.");
523 return NULL;
524 }
525 {
526 s32 readSize = ReadFile( fileId, buffer, fileBlockOffset, 0, loadBlockSize );
527 if ( readSize != fileBlockOffset )
528 {
529 return NULL;
530 }
531 }
532 internal::WaveArchiveFileReader reader( buffer, true );
533
534 // テーブル頭につけるシグニチャ
535 std::memcpy(
536 ut::AddOffsetToPtr( buffer, fileBlockOffset ),
537 &internal::WaveArchiveFileReader::SIGNATURE_WARC_TABLE,
538 sizeof( internal::WaveArchiveFileReader::SIGNATURE_WARC_TABLE ) );
539 reader.InitializeFileTable();
540
541 SetFileAddressToTable( fileId, buffer );
542
543 return buffer;
544 }
545
LoadIndividualWave(SoundArchive::ItemId warcId,u32 waveIndex,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)546 bool SoundArchiveLoader::LoadIndividualWave(
547 SoundArchive::ItemId warcId,
548 u32 waveIndex,
549 SoundMemoryAllocatable* pAllocator,
550 size_t loadBlockSize )
551 {
552 NW_UNUSED_VARIABLE( loadBlockSize );
553
554 // (ロードされている) 波形アーカイブファイル取得
555 u32 fileId = m_pSoundArchive->GetItemFileId( warcId );
556 const void* pWaveArchiveFile = GetFileAddressFromTable( fileId );
557 if ( pWaveArchiveFile == NULL )
558 {
559 pWaveArchiveFile = LoadWaveArchiveTable( warcId, pAllocator, loadBlockSize );
560 if ( pWaveArchiveFile == NULL )
561 {
562 return false;
563 }
564 }
565
566 internal::WaveArchiveFileReader reader( pWaveArchiveFile, true );
567
568 // TODO: reader に対して IsLoaded のようなメソッドを呼ぶのは、少し気持ち悪い。
569 // 波形アーカイブファイルのロード周りの機能は、
570 // WaveArchiveFileReader から切り分けたほうがいいかもしれない。
571 if ( reader.IsLoaded( waveIndex ) )
572 {
573 return true;
574 }
575
576 const size_t WAVE_FILE_SIZE = reader.GetWaveFileSize( waveIndex );
577 const size_t REQUIRED_SIZE = WAVE_FILE_SIZE + sizeof(IndividualWaveInfo);
578 void* buffer = pAllocator->Alloc( REQUIRED_SIZE );
579 if ( ! internal::Util::IsDeviceMemory( reinterpret_cast<uptr>(buffer), REQUIRED_SIZE ) )
580 {
581 NW_ASSERTMSG( false, "buffer, buffer + REQUIRED_SIZE is not Device Memory.");
582 return false;
583 }
584
585 // 個別ロード用の情報書き込み
586 {
587 IndividualWaveInfo iWavInfo( fileId, waveIndex );
588 std::memcpy( buffer, &iWavInfo, sizeof(IndividualWaveInfo) );
589 }
590
591 // 個別ロード波形のロード
592 {
593 void* loadingAddress =
594 ut::AddOffsetToPtr( buffer, sizeof(IndividualWaveInfo) );
595 s32 readSize = ReadFile(
596 fileId,
597 loadingAddress,
598 WAVE_FILE_SIZE,
599 reader.GetWaveFileOffsetFromFileHead( waveIndex ),
600 loadBlockSize );
601 if ( readSize != WAVE_FILE_SIZE )
602 {
603 return false;
604 }
605 // NN_LOG("[%s] warc[%08X](%s) wIdx(%d)\n",
606 // __FUNCTION__,
607 // warcId,
608 // m_pSoundArchive->GetItemLabel(warcId),
609 // waveIndex );
610 reader.SetWaveFile( waveIndex, loadingAddress );
611
612 #ifdef NW_PLATFORM_CTR
613 nn::snd::FlushDataCache( reinterpret_cast<uptr>(loadingAddress), WAVE_FILE_SIZE );
614 #endif
615 }
616 return true;
617 }
618
619 // グループ内の埋め込みアイテムをロード済みファイルテーブルに登録し、
620 // リンクアイテムをロードする。
PostProcessForLoadedGroupFile(const void * pGroupFile,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)621 bool SoundArchiveLoader::PostProcessForLoadedGroupFile(
622 const void* pGroupFile,
623 SoundMemoryAllocatable* pAllocator,
624 size_t loadBlockSize )
625 {
626 internal::GroupFileReader reader( pGroupFile );
627 bool isLinkGroup = false;
628 u32 groupItemCount = reader.GetGroupItemCount();
629 for ( u32 i = 0; i < groupItemCount; i++ )
630 {
631 internal::GroupItemLocationInfo info;
632 if ( ! reader.ReadGroupItemLocationInfo( &info, i ) )
633 {
634 return false; // ファイル位置情報取得失敗
635 }
636
637 // 埋め込みアイテム
638 if ( info.address != NULL )
639 {
640 SetFileAddressToTable( info.fileId, info.address );
641 }
642 else
643 {
644 // 0 個目のアイテムが埋め込みかどうかで、グループ全体が埋め込みかどうかを判断
645 if ( i == 0 )
646 {
647 isLinkGroup = true;
648 break;
649 }
650 }
651 }
652 if ( isLinkGroup )
653 {
654 u32 groupItemInfoExCount = reader.GetGroupItemExCount();
655 for ( u32 i = 0; i < groupItemInfoExCount; i++ )
656 {
657 GroupFile::GroupItemInfoEx infoEx;
658 if ( reader.ReadGroupItemInfoEx( &infoEx, i ) )
659 {
660 if ( ! LoadData( infoEx.itemId, pAllocator, infoEx.loadFlag, loadBlockSize ) )
661 {
662 return false;
663 }
664 }
665 }
666 }
667 // 埋め込みかつ、個別ロードの波形アーカイブが入っている場合は、
668 // 波形アーカイブテーブルを生成しないと、当該波形アーカイブの波形を使ったサウンド再生ができない
669 else
670 {
671 u32 groupItemInfoExCount = reader.GetGroupItemExCount();
672 for ( u32 i = 0; i < groupItemInfoExCount; i++ )
673 {
674 GroupFile::GroupItemInfoEx infoEx;
675 if ( reader.ReadGroupItemInfoEx( &infoEx, i ) )
676 {
677 // infoEx.itemId - infoEx.loadFlag の組み合わせから波形アーカイブを見つける
678 if ( ! ( infoEx.loadFlag && LOAD_WARC ) )
679 {
680 continue;
681 }
682
683 switch ( Util::GetItemType( infoEx.itemId ) )
684 {
685 case ItemType_Sound:
686 switch ( m_pSoundArchive->GetSoundType( infoEx.itemId ) )
687 {
688 case SoundArchive::SOUND_TYPE_SEQ:
689 SetWaveArchiveTableWithSeqInEmbeddedGroup(
690 infoEx.itemId, pAllocator );
691 break;
692 #if 0 // 現状、グループのアイテムとして、直接ウェーブサウンドを指定できない
693 case SoundArchive::SOUND_TYPE_WAVE:
694 SetWaveArchiveTableWithWsdInEmbeddedGroup(
695 infoEx.itemId, pAllocator );
696 break;
697 #endif
698 }
699 break;
700 case ItemType_Bank:
701 SetWaveArchiveTableWithBankInEmbeddedGroup( infoEx.itemId, pAllocator );
702 break;
703 case ItemType_SoundGroup:
704 {
705 SoundArchive::SoundGroupInfo info;
706 if ( ! m_pSoundArchive->detail_ReadSoundGroupInfo(
707 infoEx.itemId, &info ) )
708 {
709 continue;
710 }
711 switch ( m_pSoundArchive->GetSoundType( info.startId ) )
712 {
713 case SoundArchive::SOUND_TYPE_SEQ:
714 for ( u32 id = info.startId; id <= info.endId; id++ )
715 {
716 SetWaveArchiveTableWithSeqInEmbeddedGroup(
717 id, pAllocator );
718 }
719 break;
720 case SoundArchive::SOUND_TYPE_WAVE:
721 // ウェーブサウンドはすべて同じ波形アーカイブを指すため、
722 // startId のもののみ評価する
723 SetWaveArchiveTableWithWsdInEmbeddedGroup(
724 info.startId, pAllocator );
725 break;
726 }
727 }
728 break;
729 }
730 }
731 }
732 }
733
734 return true;
735 }
736
737 // 埋め込みグループ内の個別ロード波形アーカイブに対して、テーブルを作成する
SetWaveArchiveTableWithSeqInEmbeddedGroup(SoundArchive::ItemId seqId,SoundMemoryAllocatable * pAllocator)738 void SoundArchiveLoader::SetWaveArchiveTableWithSeqInEmbeddedGroup(
739 SoundArchive::ItemId seqId, SoundMemoryAllocatable* pAllocator )
740 {
741 SoundArchive::SequenceSoundInfo info;
742 if ( ! m_pSoundArchive->ReadSequenceSoundInfo( seqId, &info ) )
743 {
744 return;
745 }
746 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
747 {
748 SetWaveArchiveTableWithBankInEmbeddedGroup(
749 info.bankIds[i], pAllocator );
750 }
751 }
752
SetWaveArchiveTableWithBankInEmbeddedGroup(SoundArchive::ItemId bankId,SoundMemoryAllocatable * pAllocator)753 void SoundArchiveLoader::SetWaveArchiveTableWithBankInEmbeddedGroup(
754 SoundArchive::ItemId bankId, SoundMemoryAllocatable* pAllocator )
755 {
756 if ( bankId == SoundArchive::INVALID_ID )
757 {
758 return;
759 }
760
761 // 波形アーカイブ ID を調べる
762 SoundArchive::BankInfo bankInfo;
763 if ( ! m_pSoundArchive->ReadBankInfo( bankId, &bankInfo ) )
764 {
765 return;
766 }
767 const void* bankFile = GetFileAddressFromTable( bankInfo.fileId );
768 if ( bankFile == NULL )
769 {
770 return;
771 }
772
773 BankFileReader bankReader( bankFile );
774 const Util::WaveIdTable& table = bankReader.GetWaveIdTable();
775 if ( table.GetCount() <= 0 )
776 {
777 return;
778 }
779
780 SoundArchive::ItemId warcId = table.GetWaveId( 0U ).waveArchiveId;
781 SetWaveArchiveTableInEmbeddedGroupImpl( warcId, pAllocator );
782 }
783
SetWaveArchiveTableWithWsdInEmbeddedGroup(SoundArchive::ItemId wsdId,SoundMemoryAllocatable * pAllocator)784 void SoundArchiveLoader::SetWaveArchiveTableWithWsdInEmbeddedGroup(
785 SoundArchive::ItemId wsdId, SoundMemoryAllocatable* pAllocator )
786 {
787 if ( wsdId == SoundArchive::INVALID_ID )
788 {
789 return;
790 }
791
792 // 波形アーカイブ ID を調べる
793 SoundArchive::SoundInfo soundInfo;
794 if ( ! m_pSoundArchive->ReadSoundInfo( wsdId, &soundInfo ) )
795 {
796 return;
797 }
798 SoundArchive::WaveSoundInfo wsdInfo;
799 if ( ! m_pSoundArchive->detail_ReadWaveSoundInfo( wsdId, &wsdInfo ) )
800 {
801 return;
802 }
803
804 const void* wsdFile = GetFileAddressFromTable( soundInfo.fileId );
805 if ( wsdFile == NULL )
806 {
807 return;
808 }
809
810 WaveSoundFileReader reader( wsdFile );
811 WaveSoundNoteInfo noteInfo;
812 if ( ! reader.ReadNoteInfo( ¬eInfo, wsdInfo.index, 0 ) )
813 {
814 return;
815 }
816
817 SetWaveArchiveTableInEmbeddedGroupImpl( noteInfo.waveArchiveId, pAllocator );
818 }
819
SetWaveArchiveTableInEmbeddedGroupImpl(SoundArchive::ItemId warcId,SoundMemoryAllocatable * pAllocator)820 void SoundArchiveLoader::SetWaveArchiveTableInEmbeddedGroupImpl(
821 SoundArchive::ItemId warcId, SoundMemoryAllocatable* pAllocator )
822 {
823 // 当該波形アーカイブが個別ロード OFF なら処理しない
824 SoundArchive::WaveArchiveInfo info;
825 if ( ! m_pSoundArchive->ReadWaveArchiveInfo( warcId, &info ) )
826 {
827 return;
828 }
829 if ( ! info.isLoadIndividual )
830 {
831 return;
832 }
833
834 const void* warcFile = GetFileAddressFromTable( info.fileId );
835 WaveArchiveFileReader loadedFileReader( warcFile, false );
836
837 // すでにテーブル作成済みの場合は、処理しない
838 if ( loadedFileReader.HasIndividualLoadTable() )
839 {
840 return;
841 }
842
843 // ファイルブロック手前までのオフセット取得
844 u32 fileBlockOffset = reinterpret_cast<const WaveArchiveFile::FileHeader*>(
845 warcFile )->GetFileBlockOffset();
846 const u32 REQUIRED_TABLE_SIZE =
847 fileBlockOffset + info.waveCount * sizeof(u32) +
848 sizeof( WaveArchiveFileReader::SIGNATURE_WARC_TABLE );
849
850
851 // ファイルテーブル用のバッファを確保
852 void* buffer = pAllocator->Alloc( REQUIRED_TABLE_SIZE );
853 if ( buffer == NULL )
854 {
855 return;
856 }
857
858 // ロード済みの波形アーカイブヘッダーをコピー
859 std::memcpy( buffer, warcFile, fileBlockOffset );
860
861 // テーブルのシグニチャ書き込み
862 std::memcpy( ut::AddOffsetToPtr( buffer, fileBlockOffset ),
863 &WaveArchiveFileReader::SIGNATURE_WARC_TABLE,
864 sizeof( WaveArchiveFileReader::SIGNATURE_WARC_TABLE ) );
865
866 WaveArchiveFileReader reader( buffer, true );
867 reader.InitializeFileTable();
868
869 // 波形アーカイブ中のすべての波形エントリを、テーブル上に書き出す
870 for ( u32 i = 0; i < info.waveCount; i++ )
871 {
872 reader.SetWaveFile( i, loadedFileReader.GetWaveFile( i ) );
873 }
874
875 // ロードテーブル上のエントリは今回作ったテーブルのものに差し替える
876 SetFileAddressToTable( info.fileId, buffer );
877 }
878
LoadGroup(SoundArchive::ItemId groupId,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)879 bool SoundArchiveLoader::LoadGroup(
880 SoundArchive::ItemId groupId,
881 SoundMemoryAllocatable* pAllocator,
882 size_t loadBlockSize )
883 {
884 // グループファイルのロード
885 const void* pGroupFile = NULL;
886 {
887 u32 fileId = m_pSoundArchive->GetItemFileId( groupId );
888
889 // NOTE: グループ内の埋め込みアイテムが、デバイスメモリにおくべきかどうかは判断できない。
890 // そのため、つねに LoadImpl の bool needDeviceMemory は true にしておく。
891 pGroupFile = LoadImpl( fileId, pAllocator, loadBlockSize, true );
892 if ( pGroupFile == NULL )
893 {
894 return false; // ロード失敗
895 }
896
897 #ifdef NW_SND_DEBUG_PRINT_ENABLE
898 {
899 GroupFileReader reader( pGroupFile );
900
901 NN_LOG("*** GroupItemLocatioInfo ***\n");
902 for ( u32 i = 0; i < reader.GetGroupItemCount(); i++ )
903 {
904 GroupItemLocationInfo info;
905 if ( reader.ReadGroupItemLocationInfo( &info, i ) )
906 {
907 NN_LOG(" [%3d] fileId(%08x) addr(%p)\n", i, info.fileId, info.address );
908 }
909 }
910
911 NN_LOG("*** GroupItemInfoEx ***\n");
912 for ( u32 i = 0; i < reader.GetGroupItemExCount(); i++ )
913 {
914 GroupFile::GroupItemInfoEx infoEx;
915 if ( reader.ReadGroupItemInfoEx( &infoEx, i ) )
916 {
917 NN_LOG(" [%3d] itemId(%08x) loadFlag(%08x)\n",
918 i, infoEx.itemId, infoEx.loadFlag );
919 }
920 }
921 }
922 #endif
923 }
924 return PostProcessForLoadedGroupFile( pGroupFile, pAllocator );
925 }
926
LoadSoundGroup(SoundArchive::ItemId soundGroupId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)927 bool SoundArchiveLoader::LoadSoundGroup(
928 SoundArchive::ItemId soundGroupId,
929 SoundMemoryAllocatable* pAllocator,
930 u32 loadFlag,
931 size_t loadBlockSize )
932 {
933 // SoundGroupInfo 取得
934 SoundArchive::SoundGroupInfo info;
935 if ( ! m_pSoundArchive->detail_ReadSoundGroupInfo( soundGroupId, &info ) )
936 {
937 return false;
938 }
939
940 // info.startId と info.endId の SoundType は同一であることが保障されている。
941 switch ( m_pSoundArchive->GetSoundType( info.startId ) )
942 {
943 case SoundArchive::SOUND_TYPE_SEQ:
944 for ( u32 id = info.startId; id <= info.endId; id++ )
945 {
946 if ( ! LoadSequenceSound( id, pAllocator, loadFlag, loadBlockSize ) )
947 {
948 return false;
949 }
950 }
951 break;
952 case SoundArchive::SOUND_TYPE_WAVE:
953 for ( u32 id = info.startId; id <= info.endId; id++ )
954 {
955 if ( ! LoadWaveSound( id, pAllocator, loadFlag, loadBlockSize, soundGroupId ) )
956 {
957 return false;
958 }
959 }
960 break;
961 }
962
963 #if 0
964 // TODO: パフォーマンスが気になる場合は、loadFlag と照らし合わせて、
965 // 下記のようにする。
966 //
967 if ( ( loadFlag == LOAD_SEQ ) || ( loadFlag == LOAD_WSD ) )
968 {
969 // SoundGroupInfo の fileIds を順番にロード
970 // ...
971 }
972 #endif
973
974 return true;
975 }
976
977 /*---------------------------------------------------------------------------*
978 Name: ReadFile
979
980 Description: サウンドアーカイブ内のファイルの一部をメモリ上に読み出します。
981 ID が fileId のファイルの offset バイト目から size だけ読み出します。
982
983 Arguments: fileId - サウンドアーカイブ内のファイル ID です。
984 buffer - ロードするバッファの先頭アドレスです。
985 size - 読み出すサイズです。
986 offset - ファイル「ファイル ID」の先頭からのオフセットです。
987
988 Returns: 読み込んだサイズを返します。
989 失敗したときは、-1 を返します。
990 *---------------------------------------------------------------------------*/
ReadFile(SoundArchive::FileId fileId,void * buffer,size_t size,s32 offset,size_t loadBlockSize)991 s32 SoundArchiveLoader::ReadFile(
992 SoundArchive::FileId fileId,
993 void* buffer,
994 size_t size,
995 s32 offset,
996 size_t loadBlockSize )
997 {
998 FileStreamHandle stream = const_cast<SoundArchive*>(m_pSoundArchive)->detail_OpenFileStream(
999 fileId, m_StreamArea, sizeof(m_StreamArea) );
1000 if ( ! stream )
1001 {
1002 return -1;
1003 }
1004 if ( ! stream->CanSeek() || ! stream->CanRead() )
1005 {
1006 return -1;
1007 }
1008
1009 stream->Seek( offset, io::FILE_STREAM_SEEK_BEGIN );
1010
1011 if ( loadBlockSize == 0 )
1012 {
1013 // 一括ロード
1014 s32 readByte = stream->Read( buffer, ut::RoundUp( static_cast<u32>( size ), 32 ) );
1015 if ( readByte < 0 )
1016 {
1017 return -1;
1018 }
1019 }
1020 else
1021 {
1022 // 分割ロード
1023 u8* ptr = reinterpret_cast<u8*>( buffer );
1024 u32 restSize = size;
1025 while ( restSize > 0 )
1026 {
1027 u32 curReadingSize = ut::RoundUp( ut::Min<u32>( loadBlockSize, restSize ), 32 );
1028 s32 readByte = stream->Read( ptr, curReadingSize );
1029 if ( readByte < 0 )
1030 {
1031 return -1;
1032 }
1033 if ( restSize > readByte )
1034 {
1035 restSize -= readByte;
1036 ptr += readByte;
1037 }
1038 else
1039 {
1040 restSize = 0;
1041 }
1042 }
1043 }
1044
1045 return size;
1046 }
1047
1048 /*---------------------------------------------------------------------------*
1049 Name: LoadFile
1050
1051 Description: サウンドアーカイブ内のファイルをロードします。
1052
1053 Arguments: fileId - サウンドアーカイブ内のファイル ID です。
1054 allocator - ファイルを格納するメモリを確保するアロケータです。
1055 loadBlockSize - 分割ロード時、1回の Read で読み取るサイズ。
1056 0 だと一括ロードする。
1057 needDeviceMemory - デバイスメモリへのロードが必要かどうかのフラグです。
1058
1059 Returns: ロードしたメモリアドレス
1060 ロード失敗時には NULL を返す
1061 *---------------------------------------------------------------------------*/
LoadFile(SoundArchive::FileId fileId,SoundMemoryAllocatable * allocator,size_t loadBlockSize,bool needDeviceMemory)1062 void* SoundArchiveLoader::LoadFile(
1063 SoundArchive::FileId fileId,
1064 SoundMemoryAllocatable* allocator,
1065 size_t loadBlockSize,
1066 bool needDeviceMemory )
1067 {
1068 NW_NULL_ASSERT( allocator );
1069 NW_NULL_ASSERT( m_pSoundArchive );
1070
1071 SoundArchive::FileInfo fileInfo;
1072 if ( ! m_pSoundArchive->detail_ReadFileInfo( fileId, &fileInfo ) )
1073 {
1074 return NULL;
1075 }
1076 u32 fileSize = fileInfo.fileSize;
1077 if ( fileSize == 0 )
1078 {
1079 return NULL;
1080 }
1081
1082 void* buffer = allocator->Alloc( fileSize );
1083 if ( buffer == NULL )
1084 {
1085 return NULL;
1086 }
1087 if ( needDeviceMemory )
1088 {
1089 if ( ! Util::IsDeviceMemory( reinterpret_cast<uptr>(buffer), fileSize ) )
1090 {
1091 NW_ASSERTMSG( false, "buffer, buffer + fileSize is not Device Memory.");
1092 return false;
1093 }
1094 }
1095
1096 if ( ReadFile( fileId, buffer, (s32)fileSize, 0, loadBlockSize ) != fileSize )
1097 {
1098 return NULL;
1099 }
1100 #ifdef NW_PLATFORM_CTR
1101 nn::snd::FlushDataCache( reinterpret_cast<uptr>(buffer), fileSize );
1102 #endif
1103
1104 return buffer;
1105 }
1106
IsDataLoaded(const char * pItemName,u32 loadFlag) const1107 bool SoundArchiveLoader::IsDataLoaded( const char* pItemName, u32 loadFlag ) const
1108 {
1109 NW_NULL_ASSERT( m_pSoundArchive );
1110
1111 SoundArchive::ItemId id = m_pSoundArchive->GetItemId( pItemName );
1112 return IsDataLoaded( id, loadFlag );
1113 }
1114
IsDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1115 bool SoundArchiveLoader::IsDataLoaded( SoundArchive::ItemId itemId, u32 loadFlag ) const
1116 {
1117 if ( ! IsAvailable() )
1118 {
1119 return false;
1120 }
1121 if ( itemId == SoundArchive::INVALID_ID )
1122 {
1123 return false;
1124 }
1125
1126 switch ( internal::Util::GetItemType( itemId ) )
1127 {
1128 case internal::ItemType_Sound:
1129 switch ( m_pSoundArchive->GetSoundType( itemId ) )
1130 {
1131 case SoundArchive::SOUND_TYPE_SEQ:
1132 return IsSequenceSoundDataLoaded( itemId, loadFlag );
1133 case SoundArchive::SOUND_TYPE_WAVE:
1134 return IsWaveSoundDataLoaded( itemId, loadFlag );
1135 case SoundArchive::SOUND_TYPE_STRM:
1136 default:
1137 return false;
1138 }
1139 case internal::ItemType_Bank:
1140 return IsBankDataLoaded( itemId, loadFlag );
1141 case internal::ItemType_WaveArchive:
1142 return IsWaveArchiveDataLoaded( itemId, SoundArchive::INVALID_ID );
1143 case internal::ItemType_Group:
1144 return IsGroupDataLoaded( itemId );
1145 case internal::ItemType_SoundGroup:
1146 return IsSoundGroupDataLoaded( itemId, loadFlag );
1147 case internal::ItemType_Player:
1148 default:
1149 return false;
1150 }
1151 }
1152
IsSequenceSoundDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1153 bool SoundArchiveLoader::IsSequenceSoundDataLoaded(
1154 SoundArchive::ItemId itemId, u32 loadFlag ) const
1155 {
1156 if ( loadFlag & LOAD_SEQ )
1157 {
1158 u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1159 if ( GetFileAddressImpl( fileId ) == NULL )
1160 {
1161 return false;
1162 }
1163 }
1164
1165 if ( loadFlag & LOAD_BANK || loadFlag & LOAD_WARC )
1166 {
1167 SoundArchive::SequenceSoundInfo info;
1168 if ( ! m_pSoundArchive->ReadSequenceSoundInfo( itemId, &info ) )
1169 {
1170 return false;
1171 }
1172
1173 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
1174 {
1175 u32 bankId = info.bankIds[i];
1176 if ( bankId != SoundArchive::INVALID_ID )
1177 {
1178 if ( ! IsBankDataLoaded( bankId, loadFlag ) )
1179 {
1180 return false;
1181 }
1182 }
1183 }
1184 }
1185 return true;
1186 }
1187
IsWaveSoundDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1188 bool SoundArchiveLoader::IsWaveSoundDataLoaded( SoundArchive::ItemId itemId, u32 loadFlag ) const
1189 {
1190 const void* pWsdFile = NULL;
1191 {
1192 u32 wsdFileId = m_pSoundArchive->GetItemFileId( itemId );
1193 pWsdFile = GetFileAddressImpl( wsdFileId );
1194 }
1195
1196 if ( (loadFlag & LOAD_WSD) || (loadFlag & LOAD_WARC) )
1197 {
1198 if ( pWsdFile == NULL )
1199 {
1200 return false;
1201 }
1202 }
1203
1204 if ( loadFlag & LOAD_WARC )
1205 {
1206 u32 index; // bcwsd 内のインデックス
1207 {
1208 SoundArchive::WaveSoundInfo info;
1209 if ( ! m_pSoundArchive->detail_ReadWaveSoundInfo( itemId, &info ) )
1210 {
1211 return false;
1212 }
1213 index = info.index;
1214 }
1215 u32 warcId;
1216 u32 waveIndex;
1217 {
1218 internal::WaveSoundFileReader reader( pWsdFile );
1219 internal::WaveSoundNoteInfo info;
1220 if ( ! reader.ReadNoteInfo( &info, index, 0 ) )
1221 {
1222 return false;
1223 }
1224 warcId = info.waveArchiveId;
1225 waveIndex = info.waveIndex;
1226 }
1227 if ( ! IsWaveArchiveDataLoaded( warcId, waveIndex ) )
1228 {
1229 return false;
1230 }
1231 }
1232 return true;
1233 }
1234
IsBankDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1235 bool SoundArchiveLoader::IsBankDataLoaded( SoundArchive::ItemId itemId, u32 loadFlag ) const
1236 {
1237 const void* pBankFile = NULL;
1238 {
1239 u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1240 pBankFile = GetFileAddressImpl( fileId );
1241 }
1242 if ( (loadFlag & LOAD_BANK) || (loadFlag & LOAD_WARC) )
1243 {
1244 if ( pBankFile == NULL )
1245 {
1246 return false;
1247 }
1248 }
1249
1250 if ( loadFlag & LOAD_WARC )
1251 {
1252 internal::BankFileReader reader( pBankFile );
1253 const internal::Util::WaveIdTable& table = reader.GetWaveIdTable();
1254
1255 for ( u32 i = 0; i < table.GetCount(); i++ )
1256 {
1257 const internal::Util::WaveId& waveId = table.GetWaveId( i );
1258 u32 warcId = waveId.waveArchiveId;
1259 u32 waveIndex = waveId.waveIndex;
1260 if ( ! IsWaveArchiveDataLoaded( warcId, waveIndex ) )
1261 {
1262 return false;
1263 }
1264 }
1265 }
1266 return true;
1267 }
1268
1269 // LOAD_WARC が有効なだけ呼ばれるので、u32 loadFlag は必要ない。
IsWaveArchiveDataLoaded(SoundArchive::ItemId itemId,u32 waveIndex) const1270 bool SoundArchiveLoader::IsWaveArchiveDataLoaded(
1271 SoundArchive::ItemId itemId, u32 waveIndex ) const
1272 {
1273 const void* pWarcFile = NULL;
1274 {
1275 u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1276 pWarcFile = GetFileAddressImpl( fileId );
1277 }
1278 if ( pWarcFile == NULL )
1279 {
1280 return false;
1281 }
1282
1283 SoundArchive::WaveArchiveInfo info;
1284 if ( ! m_pSoundArchive->ReadWaveArchiveInfo( itemId, &info ) )
1285 {
1286 return false;
1287 }
1288 if ( info.isLoadIndividual == true )
1289 {
1290 internal::WaveArchiveFileReader reader( pWarcFile, true );
1291 if ( waveIndex != SoundArchive::INVALID_ID )
1292 {
1293 if ( ! reader.IsLoaded( waveIndex ) )
1294 {
1295 return false;
1296 }
1297 }
1298 else
1299 {
1300 // 波形アーカイブのみのロード確認 and 個別ロード時は、全部確認
1301 u32 waveCount = reader.GetWaveFileCount();
1302 for ( u32 i = 0; i < waveCount; i++ )
1303 {
1304 if ( ! reader.IsLoaded( i ) )
1305 {
1306 return false;
1307 }
1308 }
1309 }
1310 }
1311 return true;
1312 }
1313
1314 // 中身がなにか分からないので u32 loadFlag は必要ない
IsGroupDataLoaded(SoundArchive::ItemId itemId) const1315 bool SoundArchiveLoader::IsGroupDataLoaded( SoundArchive::ItemId itemId ) const
1316 {
1317 u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1318 if ( GetFileAddressImpl( fileId ) == NULL )
1319 {
1320 return false;
1321 }
1322 return true;
1323 }
1324
IsSoundGroupDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1325 bool SoundArchiveLoader::IsSoundGroupDataLoaded(
1326 SoundArchive::ItemId itemId, u32 loadFlag ) const
1327 {
1328 SoundArchive::SoundGroupInfo info;
1329 if ( ! m_pSoundArchive->detail_ReadSoundGroupInfo( itemId, &info ) )
1330 {
1331 return false;
1332 }
1333
1334 switch ( m_pSoundArchive->GetSoundType( info.startId ) )
1335 {
1336 case SoundArchive::SOUND_TYPE_SEQ:
1337 for ( u32 id = info.startId; id <= info.endId; id++ )
1338 {
1339 if ( ! IsSequenceSoundDataLoaded( id, loadFlag ) )
1340 {
1341 return false;
1342 }
1343 }
1344 break;
1345 case SoundArchive::SOUND_TYPE_WAVE:
1346 for ( u32 id = info.startId; id <= info.endId; id++ )
1347 {
1348 if ( ! IsWaveSoundDataLoaded( id, loadFlag ) )
1349 {
1350 return false;
1351 }
1352 }
1353 break;
1354 }
1355 return true;
1356 }
1357
GetFileAddressFromSoundArchive(SoundArchive::FileId fileId) const1358 const void* SoundArchiveLoader::GetFileAddressFromSoundArchive(
1359 SoundArchive::FileId fileId ) const
1360 {
1361 if ( m_pSoundArchive == NULL )
1362 {
1363 return NULL;
1364 }
1365 return m_pSoundArchive->detail_GetFileAddress( fileId );
1366 }
1367
detail_GetFileAddressByItemId(SoundArchive::ItemId itemId) const1368 const void* SoundArchiveLoader::detail_GetFileAddressByItemId(
1369 SoundArchive::ItemId itemId ) const
1370 {
1371 if ( m_pSoundArchive == NULL )
1372 {
1373 return NULL;
1374 }
1375
1376 SoundArchive::FileId fileId = SoundArchive::INVALID_ID;
1377 const void* result = NULL;
1378
1379 switch ( Util::GetItemType( itemId ) )
1380 {
1381 case ItemType_Sound:
1382 {
1383 SoundArchive::SoundInfo info;
1384 m_pSoundArchive->ReadSoundInfo( itemId, &info );
1385 fileId = info.fileId;
1386 }
1387 break;
1388 case ItemType_Bank:
1389 {
1390 SoundArchive::BankInfo info;
1391 m_pSoundArchive->ReadBankInfo( itemId, &info );
1392 fileId = info.fileId;
1393 }
1394 break;
1395 case ItemType_WaveArchive:
1396 {
1397 SoundArchive::WaveArchiveInfo info;
1398 m_pSoundArchive->ReadWaveArchiveInfo( itemId, &info );
1399 fileId = info.fileId;
1400 }
1401 break;
1402 case ItemType_Group:
1403 {
1404 SoundArchive::GroupInfo info;
1405 m_pSoundArchive->detail_ReadGroupInfo( itemId, &info );
1406 fileId = info.fileId;
1407 }
1408 break;
1409 default:
1410 NW_ASSERTMSG( false, "invalid itemId(%08x)\n", itemId );
1411 break;
1412 }
1413
1414 if ( fileId != SoundArchive::INVALID_ID )
1415 {
1416 result = GetFileAddressImpl( fileId );
1417 }
1418 return result;
1419 }
1420
1421 // 当該バンクに必要な波形をロード
detail_LoadWaveArchiveByBankFile(const void * bankFile,SoundMemoryAllocatable * pAllocator)1422 bool SoundArchiveLoader::detail_LoadWaveArchiveByBankFile(
1423 const void* bankFile,
1424 SoundMemoryAllocatable* pAllocator )
1425 {
1426 if ( bankFile == NULL )
1427 {
1428 return false;
1429 }
1430
1431 // 当該バンクに必要な波形のみロード
1432 internal::BankFileReader reader( bankFile );
1433 const internal::Util::WaveIdTable& table = reader.GetWaveIdTable();
1434
1435 for ( u32 i = 0; i < table.GetCount(); i++ )
1436 {
1437 const internal::Util::WaveId& waveId = table.GetWaveId( i );
1438 if ( ! LoadWaveArchiveImpl(
1439 waveId.waveArchiveId,
1440 waveId.waveIndex,
1441 pAllocator,
1442 LOAD_WARC ) )
1443 {
1444 return false;
1445 }
1446 }
1447 return true;
1448 }
1449
1450 // 当該ウェーブサウンド1つに必要な波形をロード
detail_LoadWaveArchiveByWaveSoundFile(const void * wsdFile,s32 wsdIndex,SoundMemoryAllocatable * pAllocator)1451 bool SoundArchiveLoader::detail_LoadWaveArchiveByWaveSoundFile(
1452 const void* wsdFile,
1453 s32 wsdIndex,
1454 SoundMemoryAllocatable* pAllocator )
1455 {
1456 if ( wsdFile == NULL )
1457 {
1458 return false;
1459 }
1460
1461 // wsdFile, wsdIndex から必要な波形アーカイブ ID および、波形インデックスを取得
1462 u32 warcId = SoundArchive::INVALID_ID;
1463 u32 waveIndex;
1464 {
1465 internal::WaveSoundFileReader reader( wsdFile );
1466 internal::WaveSoundNoteInfo info;
1467 if ( ! reader.ReadNoteInfo( &info, wsdIndex, 0 ) )
1468 {
1469 return false;
1470 }
1471 warcId = info.waveArchiveId;
1472 waveIndex = info.waveIndex;
1473 }
1474 if ( ! LoadWaveArchiveImpl( // 波形アーカイブの個別ロードフラグが ON なら、個別ロードされる
1475 warcId,
1476 waveIndex,
1477 pAllocator,
1478 LOAD_WARC ) )
1479 {
1480 return false;
1481 }
1482 return true;
1483 }
1484
1485 } // namespace nw::snd::internal
1486 } // namespace nw::snd
1487 } // namespace nw
1488
1489