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