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