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( &noteInfo, 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