1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundDataManager.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: 22506 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_SoundDataManager.h>
19 
20 #include <nw/snd/snd_DisposeCallbackManager.h>
21 #include <nw/snd/snd_DriverCommand.h>
22 #include <nw/snd/snd_SoundArchiveLoader.h>
23 #include <nw/snd/snd_GroupFileReader.h>
24 #include <nw/snd/snd_WaveArchiveFile.h>
25 #include <nw/snd/snd_Util.h>
26 #include <nn/os.h>
27 
28 namespace nw {
29 namespace snd {
30 
31 namespace {
32 
33 // 個別ロード波形のメモリブロック先頭に置かれる情報
34 //
35 struct IndividualWaveInfo
36 {
37     // データ
38     u32 signature;
39     u32 fileId;         //< 所属する波形アーカイブファイル ID
40     u32 waveIndex;      //< 波形アーカイブ内インデックス
41     u32 padding[5];
42 
43     // メソッド
IndividualWaveInfonw::snd::__anon95690e410111::IndividualWaveInfo44     IndividualWaveInfo( u32 id, u32 index )
45     : signature( SoundDataManager::SIGNATURE_INDIVIDUAL_WAVE ),
46       fileId( id ),
47       waveIndex( index )
48     {}
49 };
50 
51 const u32 REQUIRED_SIZE_FOR_LOAD_WARC_FILE_HEADER =
52         NW_SND_ROUND_UP_32B( sizeof( internal::WaveArchiveFile::FileHeader ) + 32 );
53         // 32 バイトごとに読むため
54 } // anonymous namespace
55 
56 
SoundDataManager()57 SoundDataManager::SoundDataManager()
58 : m_pFileTable ( NULL ),
59   m_pSoundArchive( NULL ),
60   m_pFileManager( NULL )
61 {
62 }
63 
~SoundDataManager()64 SoundDataManager::~SoundDataManager()
65 {
66 }
67 
GetRequiredMemSize(const SoundArchive * arc) const68 size_t SoundDataManager::GetRequiredMemSize( const SoundArchive* arc ) const
69 {
70     NW_NULL_ASSERT( arc );
71     size_t size = 0;
72 
73     size += ut::RoundUp(
74             sizeof( u32 ) +
75             sizeof( FileAddress ) * arc->detail_GetFileCount(), 4 );
76     return size;
77 }
78 
Initialize(const SoundArchive * arc,void * buffer,u32 size)79 bool SoundDataManager::Initialize( const SoundArchive* arc, void* buffer, u32 size )
80 {
81     NW_NULL_ASSERT( arc );
82     NW_NULL_ASSERT( buffer );
83     NW_ALIGN4_ASSERT( buffer );
84     NW_ASSERT( size >= GetRequiredMemSize( arc ) );
85 
86     void* endp = static_cast<char*>(buffer) + size;
87     void* buf = buffer;
88 
89     if ( ! CreateFileAddressTable( arc, &buf, endp ) )
90     {
91         return false;
92     }
93 
94     NW_ASSERT( static_cast<char*>(buf) - static_cast<char*>(buffer) == GetRequiredMemSize( arc ) );
95     m_pSoundArchive = arc;
96 
97     internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
98 
99     internal::DriverCommandDisposeCallback* command =
100         cmdmgr.AllocCommand<internal::DriverCommandDisposeCallback>();
101     command->id = internal::DRIVER_COMMAND_REGIST_DISPOSE_CALLBACK;
102     command->callback = this;
103     cmdmgr.PushCommand(command);
104 
105     return true;
106 }
107 
Finalize()108 void SoundDataManager::Finalize()
109 {
110     internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
111 
112     internal::DriverCommandDisposeCallback* command =
113         cmdmgr.AllocCommand<internal::DriverCommandDisposeCallback>();
114     command->id = internal::DRIVER_COMMAND_UNREGIST_DISPOSE_CALLBACK;
115     command->callback = this;
116     cmdmgr.PushCommand(command);
117     u32 tag = cmdmgr.FlushCommand( true );
118     cmdmgr.WaitCommandReply( tag );
119 
120     m_pSoundArchive = NULL;
121     m_pFileManager = NULL;
122     m_pFileTable = NULL;
123 }
124 
CreateFileAddressTable(const SoundArchive * arc,void ** buffer,void * endp)125 bool SoundDataManager::CreateFileAddressTable(
126     const SoundArchive* arc,
127     void** buffer,
128     void* endp
129 )
130 {
131     size_t requiredSize =
132         sizeof( u32 ) +
133         sizeof( FileAddress ) * arc->detail_GetFileCount();
134 
135     void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requiredSize ), 4 );
136     if ( ut::ComparePtr( ep, endp ) > 0 )
137     {
138         return false;
139     }
140     m_pFileTable = reinterpret_cast< FileTable* >(*buffer);
141     *buffer = ep;
142 
143 
144     m_pFileTable->count = arc->detail_GetFileCount();
145     for( u32 i = 0 ; i < m_pFileTable->count ; i++ )
146     {
147         m_pFileTable->item[ i ].address = NULL;
148     }
149 
150     return true;
151 }
152 
153 /*---------------------------------------------------------------------------*
154   Name:         IsAvailable
155 
156   Description:  サウンドアーカイブプレイヤーが利用可能かどうかを調べる
157 
158   Arguments:    無し
159 
160   Returns:      利用可能かどうかを返す
161  *---------------------------------------------------------------------------*/
IsAvailable() const162 bool SoundDataManager::IsAvailable() const
163 {
164     if ( m_pSoundArchive == NULL ) return false;
165     if ( ! m_pSoundArchive->IsAvailable() ) return false;
166 
167     return true;
168 }
169 
LoadData(SoundArchive::ItemId itemId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)170 bool SoundDataManager::LoadData(
171     SoundArchive::ItemId itemId,
172     SoundMemoryAllocatable* pAllocator,
173     u32 loadFlag,
174     size_t loadBlockSize )
175 {
176     NW_NULL_ASSERT( m_pSoundArchive );
177     NW_ALIGN32_ASSERT( loadBlockSize );
178 
179     if ( ! IsAvailable() ) return false;
180     if ( itemId == SoundArchive::INVALID_ID ) return false;
181     if ( pAllocator == NULL ) return false;
182 
183     switch ( internal::Util::GetItemType( itemId ) )
184     {
185     case internal::ItemType_Sound:
186         switch ( m_pSoundArchive->GetSoundType( itemId ) )
187         {
188         case SoundArchive::SOUND_TYPE_SEQ:
189             return LoadSequenceSound( itemId, pAllocator, loadFlag, loadBlockSize );
190         case SoundArchive::SOUND_TYPE_WAVE:
191             return LoadWaveSound( itemId, pAllocator, loadFlag, loadBlockSize );
192         case SoundArchive::SOUND_TYPE_STRM:
193         default:
194             return false;
195         }
196     case internal::ItemType_Bank:
197         return LoadBank( itemId, pAllocator, loadFlag, loadBlockSize );
198     case internal::ItemType_WaveArchive:
199         return LoadWaveArchive( itemId, pAllocator, loadFlag, loadBlockSize );
200     case internal::ItemType_Group:
201         return LoadGroup( itemId, pAllocator, loadBlockSize );
202     case internal::ItemType_SoundGroup:
203         return LoadSoundGroup( itemId, pAllocator, loadFlag, loadBlockSize );
204     case internal::ItemType_Player:
205     default:
206         return false;
207     }
208 }
209 
LoadData(const char * pItemName,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)210 bool SoundDataManager::LoadData(
211     const char* pItemName,
212     SoundMemoryAllocatable* pAllocator,
213     u32 loadFlag,
214     size_t loadBlockSize )
215 {
216     NW_NULL_ASSERT( m_pSoundArchive );
217 
218     SoundArchive::ItemId id = m_pSoundArchive->GetItemId( pItemName );
219     return LoadData( id, pAllocator, loadFlag, loadBlockSize );
220 }
221 
222 
LoadImpl(SoundArchive::FileId fileId,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize,bool needDeviceMemory)223 const void* SoundDataManager::LoadImpl(
224     SoundArchive::FileId fileId,
225     SoundMemoryAllocatable* pAllocator,
226     size_t loadBlockSize,
227     bool needDeviceMemory )
228 {
229     NW_NULL_ASSERT( m_pSoundArchive );
230     NW_UNUSED_VARIABLE( loadBlockSize );
231 
232     const void* fileAddress = detail_GetFileAddress( fileId );
233     // 未ロードの場合
234     if ( fileAddress == NULL )
235     {
236         internal::SoundArchiveLoader loader( *m_pSoundArchive );
237         fileAddress = loader.LoadFile( fileId, pAllocator, loadBlockSize, needDeviceMemory );
238         if ( fileAddress == NULL )
239         {
240             return NULL;    // ロード失敗
241         }
242         else
243         {
244             SetFileAddress( fileId, fileAddress );
245             return fileAddress;
246         }
247     }
248     // ロード済みだった場合
249     else
250     {
251         return fileAddress;
252     }
253 }
254 
LoadSequenceSound(SoundArchive::ItemId soundId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)255 bool SoundDataManager::LoadSequenceSound(
256     SoundArchive::ItemId soundId,
257     SoundMemoryAllocatable* pAllocator,
258     u32 loadFlag,
259     size_t loadBlockSize )
260 {
261     if ( loadFlag & LOAD_SEQ )
262     {
263         u32 fileId = m_pSoundArchive->GetItemFileId( soundId );
264         const void* pFile = LoadImpl( fileId, pAllocator, loadBlockSize );
265         if ( pFile == NULL )
266         {
267             return false;   // ロード失敗
268         }
269     }
270 
271     if ( loadFlag & LOAD_BANK || loadFlag & LOAD_WARC )
272     {
273         SoundArchive::SequenceSoundInfo info;
274         if ( ! m_pSoundArchive->ReadSequenceSoundInfo( soundId, &info ) )
275         {
276             return false;       // INFO ブロックからシーケンスサウンド情報が得られなかった
277         }
278 
279         for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
280         {
281             u32 bankId = info.bankIds[ i ];
282             if ( bankId != SoundArchive::INVALID_ID )
283             {
284                 if ( ! LoadBank( bankId, pAllocator, loadFlag, loadBlockSize ) )
285                 {
286                     return false;
287                 }
288             }
289         }
290     }
291 
292     return true;
293 }
294 
LoadWaveSound(SoundArchive::ItemId soundId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize,SoundArchive::ItemId waveSoundSetId)295 bool SoundDataManager::LoadWaveSound(
296     SoundArchive::ItemId soundId,
297     SoundMemoryAllocatable* pAllocator,
298     u32 loadFlag,
299     size_t loadBlockSize,
300     SoundArchive::ItemId waveSoundSetId )
301 {
302     u32 wsdFileId = m_pSoundArchive->GetItemFileId( soundId );
303     if ( loadFlag & LOAD_WSD )
304     {
305         const void* pFile = LoadImpl( wsdFileId, pAllocator, loadBlockSize );
306         if ( pFile == NULL )
307         {
308             return false;   // ロード失敗
309         }
310     }
311 
312     if ( loadFlag & LOAD_WARC )
313     {
314         const void* pWsdFile = detail_GetFileAddress( wsdFileId );
315 
316         // ウェーブサウンドセットファイルがロード済みなら、
317         // 必要に応じて個別ロードを行う
318         if ( pWsdFile != NULL )
319         {
320             // bcwsd 内でのインデックス取得
321             u32 index;
322             {
323                 SoundArchive::WaveSoundInfo info;
324                 if ( ! m_pSoundArchive->detail_ReadWaveSoundInfo( soundId, &info ) )
325                 {
326                     return false;   // WaveSoundInfo 取得失敗
327                 }
328                 index = info.index;
329             }
330             // 関連する波形アーカイブ ID を取得
331             u32 warcId = SoundArchive::INVALID_ID;
332             u32 waveIndex;
333             {
334                 internal::WaveSoundFileReader reader( pWsdFile );
335                 internal::WaveSoundNoteInfo info;
336                 if ( ! reader.ReadNoteInfo( &info, index, 0 ) )
337                 {
338                     return false;   // NoteInfo 取得失敗
339                 }
340                 warcId = info.waveArchiveId;
341                 waveIndex = info.waveIndex;
342             }
343             // ロード
344             if ( ! LoadWaveArchiveImpl(
345                         warcId,
346                         waveIndex,
347                         pAllocator,
348                         loadFlag,
349                         loadBlockSize ) )
350             {
351                 return false;
352             }
353         }
354         // 未ロードの場合は、一括ロードのみ行う
355         else
356         {
357             SoundArchive::ItemId itemId;
358             if ( waveSoundSetId != SoundArchive::INVALID_ID )
359             {
360                 itemId = waveSoundSetId;
361                 /* ウェーブサウンド ID → ウェーブサウンドセット ID への変換は
362                    時間がかかるので、あらかじめ waveSoundSetId を渡してもらえる場合は
363                    これを利用する */
364             }
365             else
366             {
367                 itemId = soundId;
368             }
369             const internal::Util::Table<u32>* pWarcIdTable =
370                 m_pSoundArchive->detail_GetWaveArchiveIdTable( itemId );
371 
372             NW_NULL_ASSERT( pWarcIdTable );
373 
374             for ( u32 i = 0; i < pWarcIdTable->count; i++ )
375             {
376                 if ( ! LoadWaveArchive(
377                             pWarcIdTable->item[ i ],
378                             pAllocator,
379                             loadFlag,
380                             loadBlockSize ) )
381                 {
382                     return false;
383                 }
384             }
385         }
386     }
387     return true;
388 }
389 
LoadBank(SoundArchive::ItemId bankId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)390 bool SoundDataManager::LoadBank(
391     SoundArchive::ItemId bankId,
392     SoundMemoryAllocatable* pAllocator,
393     u32 loadFlag,
394     size_t loadBlockSize )
395 {
396     u32 bankFileId = m_pSoundArchive->GetItemFileId( bankId );
397     if ( loadFlag & LOAD_BANK )
398     {
399         const void* pFile = LoadImpl( bankFileId, pAllocator, loadBlockSize );
400         if ( pFile == NULL )
401         {
402             return false;   // ロード失敗
403         }
404     }
405 
406     if ( loadFlag & LOAD_WARC )
407     {
408         const void* pFile = detail_GetFileAddress( bankFileId );
409 
410         // バンクがロード済みなら、必要に応じて個別ロードを行う
411         if ( pFile != NULL )
412         {
413             internal::BankFileReader reader( pFile );
414             const internal::Util::WaveIdTable& table = reader.GetWaveIdTable();
415 
416             for ( u32 i = 0; i < table.GetCount(); i++ )
417             {
418                 const internal::Util::WaveId& waveId = table.GetWaveId( i );
419                 u32 warcId = waveId.waveArchiveId;
420                 u32 waveIndex = waveId.waveIndex;
421                 if ( ! LoadWaveArchiveImpl(
422                             warcId,
423                             waveIndex,
424                             pAllocator,
425                             loadFlag,
426                             loadBlockSize ) )
427                 {
428                     return false;
429                 }
430             }
431         }
432         // バンクが未ロードの場合は、一括ロードのみ行う
433         else
434         {
435             const internal::Util::Table<ut::ResU32>* pWarcIdTable =
436                 m_pSoundArchive->detail_GetWaveArchiveIdTable( bankId );
437 
438             NW_NULL_ASSERT( pWarcIdTable );
439 
440             for ( u32 i = 0; i < pWarcIdTable->count; i++ )
441             {
442                 if ( ! LoadWaveArchive(
443                             pWarcIdTable->item[ i ],
444                             pAllocator,
445                             loadFlag,
446                             loadBlockSize ) )
447                 {
448                     return false;
449                 }
450             }
451         }
452     }
453     return true;
454 }
455 
LoadWaveArchiveImpl(SoundArchive::ItemId warcId,u32 waveIndex,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)456 bool SoundDataManager::LoadWaveArchiveImpl(
457     SoundArchive::ItemId warcId,
458     u32 waveIndex,
459     SoundMemoryAllocatable* pAllocator,
460     u32 loadFlag,
461     size_t loadBlockSize )
462 {
463     SoundArchive::WaveArchiveInfo info;
464     if ( ! m_pSoundArchive->ReadWaveArchiveInfo( warcId, &info ) )
465     {
466         return false;
467     }
468     if ( info.isLoadIndividual )
469     {
470         // 波形のロード
471         if ( ! LoadIndividualWave(
472                     warcId,
473                     waveIndex,
474                     pAllocator,
475                     loadBlockSize ) )
476         {
477             return false;
478         }
479     }
480     else
481     {
482         if ( ! LoadWaveArchive(
483                     warcId,
484                     pAllocator,
485                     loadFlag,
486                     loadBlockSize ) )
487         {
488             return false;
489         }
490     }
491     return true;
492 }
493 
494 // 波形アーカイブの一括ロード
LoadWaveArchive(SoundArchive::ItemId warcId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)495 bool SoundDataManager::LoadWaveArchive(
496     SoundArchive::ItemId warcId,
497     SoundMemoryAllocatable* pAllocator,
498     u32 loadFlag,
499     size_t loadBlockSize )
500 {
501     if ( loadFlag & LOAD_WARC )
502     {
503         u32 fileId = m_pSoundArchive->GetItemFileId( warcId );
504         // 要デバイスメモリ
505         const void* pFile = LoadImpl( fileId, pAllocator, loadBlockSize, true );
506         if ( pFile == NULL )
507         {
508             return false;   // ロード失敗
509         }
510     }
511     return true;
512 }
513 
LoadWaveArchiveTable(SoundArchive::ItemId warcId,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)514 const void* SoundDataManager::LoadWaveArchiveTable(
515     SoundArchive::ItemId warcId,
516     SoundMemoryAllocatable* pAllocator,
517     size_t loadBlockSize )
518 {
519     u32 fileId = m_pSoundArchive->GetItemFileId( warcId );
520     const void* pWaveArchiveFile = GetFileAddress( fileId );
521     if ( pWaveArchiveFile != NULL ) return pWaveArchiveFile;
522 
523     // 波形ファイル数
524     u32 waveCount;
525     {
526         SoundArchive::WaveArchiveInfo info;
527         if ( ! m_pSoundArchive->ReadWaveArchiveInfo( warcId, &info ) )
528         {
529             return NULL;
530         }
531         if ( info.waveCount <= 0 )
532         {
533             return NULL;
534         }
535         waveCount = info.waveCount;
536     }
537 
538     // ファイルブロック手前までのオフセット
539     internal::SoundArchiveLoader loader( *m_pSoundArchive );
540     u32 fileBlockOffset;
541     {
542         u8 pBuffer[ REQUIRED_SIZE_FOR_LOAD_WARC_FILE_HEADER ];
543         u8* pAlignedBuffer = reinterpret_cast<u8*>( ut::RoundUp( pBuffer, 32 ) );
544         s32 readSize = loader.ReadFile(
545                 fileId,
546                 pAlignedBuffer,
547                 sizeof(internal::WaveArchiveFile::FileHeader),
548                 0,
549                 loadBlockSize );
550         if ( readSize != sizeof(internal::WaveArchiveFile::FileHeader) )
551         {
552             return NULL;
553         }
554         const internal::WaveArchiveFile::FileHeader* pHeader =
555             reinterpret_cast<const internal::WaveArchiveFile::FileHeader*>( pAlignedBuffer );
556         fileBlockOffset = pHeader->GetFileBlockOffset();
557         u32 infoBlockOffset = pHeader->GetInfoBlockOffset();
558         if ( infoBlockOffset > fileBlockOffset )
559         {
560             return NULL;    // INFO ブロック → FILE ブロックの順に並んでいる必要がある
561         }
562     }
563 
564     // ロード用テーブルを含めたヒープサイズ
565     const u32 REQUIRED_SIZE =
566         fileBlockOffset +
567         waveCount * sizeof( u32 ) +
568         sizeof( internal::WaveArchiveFileReader::SIGNATURE_WARC_TABLE );
569 
570     void* buffer = pAllocator->Alloc( REQUIRED_SIZE );
571     if ( ! internal::Util::IsDeviceMemory( reinterpret_cast<uptr>(buffer), REQUIRED_SIZE )  )
572     {
573         NW_ASSERTMSG( false, "buffer, buffer + REQUIRED_SIZE is not Device Memory.");
574         return NULL;
575     }
576     {
577         s32 readSize = loader.ReadFile( fileId, buffer, fileBlockOffset, 0, loadBlockSize );
578         if ( readSize != fileBlockOffset )
579         {
580             return NULL;
581         }
582     }
583     internal::WaveArchiveFileReader reader( buffer, true );
584 
585     // テーブル頭につけるシグニチャ
586     std::memcpy(
587             ut::AddOffsetToPtr( buffer, fileBlockOffset ),
588             &internal::WaveArchiveFileReader::SIGNATURE_WARC_TABLE,
589             sizeof( internal::WaveArchiveFileReader::SIGNATURE_WARC_TABLE ) );
590     reader.InitializeFileTable();
591 
592     SetFileAddress( fileId, buffer );
593 
594     return buffer;
595 }
596 
LoadIndividualWave(SoundArchive::ItemId warcId,u32 waveIndex,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)597 bool SoundDataManager::LoadIndividualWave(
598     SoundArchive::ItemId warcId,
599     u32 waveIndex,
600     SoundMemoryAllocatable* pAllocator,
601     size_t loadBlockSize )
602 {
603     NW_UNUSED_VARIABLE( loadBlockSize );
604 
605     // (ロードされている) 波形アーカイブファイル取得
606     u32 fileId = m_pSoundArchive->GetItemFileId( warcId );
607     const void* pWaveArchiveFile = GetFileAddress( fileId );
608     if ( pWaveArchiveFile == NULL )
609     {
610         pWaveArchiveFile = LoadWaveArchiveTable( warcId, pAllocator, loadBlockSize );
611         if ( pWaveArchiveFile == NULL )
612         {
613             return false;
614         }
615     }
616 
617     internal::WaveArchiveFileReader reader( pWaveArchiveFile, true );
618 
619     // TODO: reader に対して IsLoaded のようなメソッドを呼ぶのは、少し気持ち悪い。
620     //       波形アーカイブファイルのロード周りの機能は、
621     //       WaveArchiveFileReader から切り分けたほうがいいかもしれない。
622     if ( reader.IsLoaded( waveIndex ) )
623     {
624         return true;
625     }
626 
627     const size_t WAVE_FILE_SIZE = reader.GetWaveFileSize( waveIndex );
628     const size_t REQUIRED_SIZE = WAVE_FILE_SIZE + sizeof(IndividualWaveInfo);
629     void* buffer = pAllocator->Alloc( REQUIRED_SIZE );
630     if ( ! internal::Util::IsDeviceMemory( reinterpret_cast<uptr>(buffer), REQUIRED_SIZE )  )
631     {
632         NW_ASSERTMSG( false, "buffer, buffer + REQUIRED_SIZE is not Device Memory.");
633         return false;
634     }
635 
636     // 個別ロード用の情報書き込み
637     {
638         IndividualWaveInfo iWavInfo( fileId, waveIndex );
639         std::memcpy( buffer, &iWavInfo, sizeof(IndividualWaveInfo) );
640     }
641 
642     // 個別ロード波形のロード
643     {
644         void* loadingAddress =
645             ut::AddOffsetToPtr( buffer, sizeof(IndividualWaveInfo) );
646         internal::SoundArchiveLoader loader( *m_pSoundArchive );
647         s32 readSize = loader.ReadFile(
648                 fileId,
649                 loadingAddress,
650                 WAVE_FILE_SIZE,
651                 reader.GetWaveFileOffsetFromFileHead( waveIndex ),
652                 loadBlockSize );
653         if ( readSize != WAVE_FILE_SIZE )
654         {
655             return false;
656         }
657         // NN_LOG("[%s] warc[%08X](%s) wIdx(%d)\n",
658         //         __FUNCTION__,
659         //         warcId,
660         //         m_pSoundArchive->GetItemLabel(warcId),
661         //         waveIndex );
662         reader.SetWaveFile( waveIndex, loadingAddress );
663 
664 #ifdef NW_PLATFORM_CTR
665         nn::snd::FlushDataCache( reinterpret_cast<uptr>(loadingAddress), WAVE_FILE_SIZE );
666 #endif
667     }
668     return true;
669 }
670 
671 // グループ内の埋め込みアイテムをロード済みファイルテーブルに登録し、
672 // リンクアイテムをロードする。
SetGroupItem(const void * pGroupFile,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)673 bool SoundDataManager::SetGroupItem(
674             const void* pGroupFile,
675             SoundMemoryAllocatable* pAllocator,
676             size_t loadBlockSize )
677 {
678     internal::GroupFileReader reader( pGroupFile );
679     for ( u32 i = 0; i < reader.GetGroupItemCount(); i++ )
680     {
681         internal::GroupItemLocationInfo info;
682         if ( ! reader.ReadGroupItemLocationInfo( &info, i ) )
683         {
684             return false;   // ファイル位置情報取得失敗
685         }
686 
687         // 埋め込みアイテム
688         if ( info.address != NULL )
689         {
690             // NN_LOG("  EMBEDDED fileId(%08X) addr(%p)\n",
691             //         info.fileId, info.address );
692             SetFileAddress( info.fileId, info.address );
693         }
694         // リンクアイテム
695         else
696         {
697             // NN_LOG("  LINK     fileId(%08X)  addr(%p)\n",
698             //         info.fileId, info.address );
699             if ( pAllocator != NULL )
700             {
701                 // NOTE: リンクアイテムがデバイスメモリにおくべきかどうかは判断できない
702                 if ( LoadImpl( info.fileId, pAllocator, loadBlockSize ) == NULL )
703                 {
704                     // NN_LOG("  ... load failed\n");
705                     return false;
706                 }
707             }
708         }
709     }
710     return true;
711 }
712 
LoadGroup(SoundArchive::ItemId groupId,SoundMemoryAllocatable * pAllocator,size_t loadBlockSize)713 bool SoundDataManager::LoadGroup(
714     SoundArchive::ItemId groupId,
715     SoundMemoryAllocatable* pAllocator,
716     size_t loadBlockSize )
717 {
718     // グループファイルのロード
719     const void* pGroupFile = NULL;
720     {
721         u32 fileId = m_pSoundArchive->GetItemFileId( groupId );
722 
723         // NOTE: グループ内の埋め込みアイテムが、デバイスメモリにおくべきかどうかは判断できない。
724         //       そのため、つねに LoadImpl の bool needDeviceMemory は true にしておく。
725         pGroupFile = LoadImpl( fileId, pAllocator, loadBlockSize, true );
726         if ( pGroupFile == NULL )
727         {
728             return false;   // ロード失敗
729         }
730     }
731     // NN_LOG("[%08X](%-15s)\n",
732     //         groupId, m_pSoundArchive->GetItemLabel( groupId ) );
733     return SetGroupItem( pGroupFile, pAllocator );
734 }
735 
LoadSoundGroup(SoundArchive::ItemId soundGroupId,SoundMemoryAllocatable * pAllocator,u32 loadFlag,size_t loadBlockSize)736 bool SoundDataManager::LoadSoundGroup(
737     SoundArchive::ItemId soundGroupId,
738     SoundMemoryAllocatable* pAllocator,
739     u32 loadFlag,
740     size_t loadBlockSize )
741 {
742     // SoundGroupInfo 取得
743     SoundArchive::SoundGroupInfo info;
744     if ( ! m_pSoundArchive->detail_ReadSoundGroupInfo( soundGroupId, &info ) )
745     {
746         return false;
747     }
748 
749     // info.startId と info.endId の SoundType は同一であることが保障されている。
750     switch ( m_pSoundArchive->GetSoundType( info.startId ) )
751     {
752     case SoundArchive::SOUND_TYPE_SEQ:
753         for ( u32 id = info.startId; id <= info.endId; id++ )
754         {
755             if ( ! LoadSequenceSound( id, pAllocator, loadFlag, loadBlockSize ) )
756             {
757                 return false;
758             }
759         }
760         break;
761     case SoundArchive::SOUND_TYPE_WAVE:
762         for ( u32 id = info.startId; id <= info.endId; id++ )
763         {
764             if ( ! LoadWaveSound( id, pAllocator, loadFlag, loadBlockSize, soundGroupId ) )
765             {
766                 return false;
767             }
768         }
769         break;
770     }
771 
772 #if 0
773     // TODO: パフォーマンスが気になる場合は、loadFlag と照らし合わせて、
774     //       下記のようにする。
775     //
776     if ( ( loadFlag == LOAD_SEQ ) || ( loadFlag == LOAD_WSD ) )
777     {
778         // SoundGroupInfo の fileIds を順番にロード
779         // ...
780     }
781 #endif
782 
783     return true;
784 }
785 
786 /*---------------------------------------------------------------------------*
787   Name:         InvalidateData
788 
789   Description:  ロードされたデータが破棄されたときにテーブルから削除する
790 
791   Arguments:    start - 開始アドレス
792                 end   - 終了アドレス
793 
794   Returns:      None.
795  *---------------------------------------------------------------------------*/
InvalidateData(const void * start,const void * end)796 void SoundDataManager::InvalidateData( const void* start, const void* end )
797 {
798     // ファイルアドレステーブルから破棄
799     if ( m_pFileTable != NULL )
800     {
801         for( u32 i = 0 ; i < m_pFileTable->count ; i++ )
802         {
803             const void* addr = m_pFileTable->item[ i ].address;
804             if ( start <= addr && addr <= end )
805             {
806                 m_pFileTable->item[ i ].address = NULL;
807             }
808         }
809     }
810 
811     if ( ut::GetOffsetFromPtr( start, end ) >= sizeof(IndividualWaveInfo) )
812     {
813         if ( start != NULL )
814         {
815             const IndividualWaveInfo* info =
816                 reinterpret_cast<const IndividualWaveInfo*>( start );
817             if ( info->signature == SoundDataManager::SIGNATURE_INDIVIDUAL_WAVE )
818             {
819                 const void* pWarcTable = GetFileAddress( info->fileId );
820                 if ( pWarcTable != NULL )
821                 {
822                     internal::WaveArchiveFileReader reader( pWarcTable, true );
823                     reader.SetWaveFile( info->waveIndex, NULL );
824                 }
825             }
826         }
827     }
828 }
829 
830 /*---------------------------------------------------------------------------*
831   Name:         detail_GetFileAddress
832 
833   Description:  記憶させたファイルアドレスを取得
834 
835   Arguments:    fileId - ファイルID
836 
837   Returns:      ファイルアドレス
838  *---------------------------------------------------------------------------*/
detail_GetFileAddress(SoundArchive::FileId fileId) const839 const void* SoundDataManager::detail_GetFileAddress( SoundArchive::FileId fileId ) const
840 {
841     // 外部のファイルマネージャに問い合わせ
842     if ( m_pFileManager != NULL )
843     {
844         const void* addr = m_pFileManager->GetFileAddress( fileId );
845         if ( addr != NULL ) return addr;
846     }
847 
848     // サウンドアーカイブに問い合わせ
849     {
850         const void* addr = m_pSoundArchive->detail_GetFileAddress( fileId );
851         if ( addr != NULL ) return addr;
852     }
853 
854     // ファイルアドレステーブルを参照
855     {
856         const void* fileData = GetFileAddress( fileId );
857         if ( fileData != NULL ) return fileData;
858     }
859     return NULL;
860 }
861 
862 /*---------------------------------------------------------------------------*
863   Name:         GetFileAddress
864 
865   Description:  記憶させたファイルアドレスを取得
866 
867   Arguments:    fileId - ファイルID
868 
869   Returns:      ファイルアドレス
870  *---------------------------------------------------------------------------*/
GetFileAddress(SoundArchive::FileId fileId) const871 const void* SoundDataManager::GetFileAddress( SoundArchive::FileId fileId ) const
872 {
873     if ( m_pFileTable == NULL )
874     {
875         NW_WARNING(
876             m_pFileTable != NULL,
877             "Failed to SoundDataManager::GetFileAddress because file table is not allocated.\n"
878         );
879         return NULL;
880     }
881 
882     if ( fileId >= m_pFileTable->count ) return NULL;
883 
884     return m_pFileTable->item[ fileId ].address;
885 }
886 
887 /*---------------------------------------------------------------------------*
888   Name:         SetFileAddress
889 
890   Description:  ファイルアドレスを記憶
891 
892   Arguments:    fileId - ファイル番号
893                 address - ファイルアドレス
894 
895   Returns:      セットする前に書かれていたファイルアドレス
896  *---------------------------------------------------------------------------*/
897 const void*
SetFileAddress(SoundArchive::FileId fileId,const void * address)898 SoundDataManager::SetFileAddress( SoundArchive::FileId fileId, const void* address )
899 {
900     if ( m_pFileTable == NULL )
901     {
902         NW_WARNING(
903             m_pFileTable != NULL,
904             "Failed to SoundDataManager::SetFileAddress because file table is not allocated.\n"
905         );
906         return NULL;
907     }
908 
909     NW_MINMAXLT_ASSERT( fileId, 0, m_pFileTable->count );
910 
911     const void* preAddress = m_pFileTable->item[ fileId ].address;
912     m_pFileTable->item[ fileId ].address = address;
913     return preAddress;
914 }
915 
916 // ロード済みファイルテーブルの中から、
917 // 引数と一致するアドレスを持つファイルのファイル ID を取得する
detail_GetFileId(const void * address) const918 u32 SoundDataManager::detail_GetFileId( const void* address ) const
919 {
920     for ( u32 i = 0; i < m_pSoundArchive->detail_GetFileCount(); i++ )
921     {
922         if ( address == m_pFileTable->item[i].address )
923         {
924             return i;
925         }
926     }
927     return SoundArchive::INVALID_ID;
928 }
929 
InvalidateSoundData(void * mem,size_t size)930 void SoundDataManager::InvalidateSoundData( void* mem, size_t size )
931 {
932     internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
933 
934     internal::DriverCommandInvalidateData* command =
935         cmdmgr.AllocCommand<internal::DriverCommandInvalidateData>();
936     command->id = internal::DRIVER_COMMAND_INVALIDATE_DATA;
937     command->mem = mem;
938     command->size = size;
939     cmdmgr.PushCommand(command);
940     u32 tag = cmdmgr.FlushCommand( true );
941     cmdmgr.WaitCommandReply( tag );
942 }
943 
IsDataLoaded(const char * pItemName,u32 loadFlag) const944 bool SoundDataManager::IsDataLoaded( const char* pItemName, u32 loadFlag ) const
945 {
946     NW_NULL_ASSERT( m_pSoundArchive );
947 
948     SoundArchive::ItemId id = m_pSoundArchive->GetItemId( pItemName );
949     return IsDataLoaded( id, loadFlag );
950 }
951 
IsDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const952 bool SoundDataManager::IsDataLoaded( SoundArchive::ItemId itemId, u32 loadFlag ) const
953 {
954     if ( ! IsAvailable() ) return false;
955     if ( itemId == SoundArchive::INVALID_ID ) return false;
956 
957     switch ( internal::Util::GetItemType( itemId ) )
958     {
959     case internal::ItemType_Sound:
960         switch ( m_pSoundArchive->GetSoundType( itemId ) )
961         {
962         case SoundArchive::SOUND_TYPE_SEQ:
963             return IsSequenceSoundDataLoaded( itemId, loadFlag );
964         case SoundArchive::SOUND_TYPE_WAVE:
965             return IsWaveSoundDataLoaded( itemId, loadFlag );
966         case SoundArchive::SOUND_TYPE_STRM:
967         default:
968             return false;
969         }
970     case internal::ItemType_Bank:
971         return IsBankDataLoaded( itemId, loadFlag );
972     case internal::ItemType_WaveArchive:
973         return IsWaveArchiveDataLoaded( itemId, SoundArchive::INVALID_ID );
974     case internal::ItemType_Group:
975         return IsGroupDataLoaded( itemId );
976     case internal::ItemType_SoundGroup:
977         return IsSoundGroupDataLoaded( itemId, loadFlag );
978     case internal::ItemType_Player:
979     default:
980         return false;
981     }
982 }
983 
IsSequenceSoundDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const984 bool SoundDataManager::IsSequenceSoundDataLoaded(
985         SoundArchive::ItemId itemId, u32 loadFlag ) const
986 {
987     if ( loadFlag & LOAD_SEQ )
988     {
989         u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
990         if ( detail_GetFileAddress( fileId ) == NULL )
991         {
992             return false;
993         }
994     }
995 
996     if ( loadFlag & LOAD_BANK || loadFlag & LOAD_WARC )
997     {
998         SoundArchive::SequenceSoundInfo info;
999         if ( ! m_pSoundArchive->ReadSequenceSoundInfo( itemId, &info ) )
1000         {
1001             return false;
1002         }
1003 
1004         for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
1005         {
1006             u32 bankId = info.bankIds[i];
1007             if ( bankId != SoundArchive::INVALID_ID )
1008             {
1009                 if ( ! IsBankDataLoaded( bankId, loadFlag ) )
1010                 {
1011                     return false;
1012                 }
1013             }
1014         }
1015     }
1016     return true;
1017 }
1018 
IsWaveSoundDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1019 bool SoundDataManager::IsWaveSoundDataLoaded( SoundArchive::ItemId itemId, u32 loadFlag ) const
1020 {
1021     const void* pWsdFile = NULL;
1022     {
1023         u32 wsdFileId = m_pSoundArchive->GetItemFileId( itemId );
1024         pWsdFile = detail_GetFileAddress( wsdFileId );
1025     }
1026 
1027     if ( (loadFlag & LOAD_WSD) || (loadFlag & LOAD_WARC) )
1028     {
1029         if ( pWsdFile == NULL )
1030         {
1031             return false;
1032         }
1033     }
1034 
1035     if ( loadFlag & LOAD_WARC )
1036     {
1037         u32 index;  // bcwsd 内のインデックス
1038         {
1039             SoundArchive::WaveSoundInfo info;
1040             if ( ! m_pSoundArchive->detail_ReadWaveSoundInfo( itemId, &info ) )
1041             {
1042                 return false;
1043             }
1044             index = info.index;
1045         }
1046         u32 warcId;
1047         u32 waveIndex;
1048         {
1049             internal::WaveSoundFileReader reader( pWsdFile );
1050             internal::WaveSoundNoteInfo info;
1051             if ( ! reader.ReadNoteInfo( &info, index, 0 ) )
1052             {
1053                 return false;
1054             }
1055             warcId = info.waveArchiveId;
1056             waveIndex = info.waveIndex;
1057         }
1058         if ( ! IsWaveArchiveDataLoaded( warcId, waveIndex ) )
1059         {
1060             return false;
1061         }
1062     }
1063     return true;
1064 }
1065 
IsBankDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1066 bool SoundDataManager::IsBankDataLoaded( SoundArchive::ItemId itemId, u32 loadFlag ) const
1067 {
1068     const void* pBankFile = NULL;
1069     {
1070         u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1071         pBankFile = detail_GetFileAddress( fileId );
1072     }
1073     if ( (loadFlag & LOAD_BANK) || (loadFlag & LOAD_WARC) )
1074     {
1075         if ( pBankFile == NULL )
1076         {
1077             return false;
1078         }
1079     }
1080 
1081     if ( loadFlag & LOAD_WARC )
1082     {
1083         internal::BankFileReader reader( pBankFile );
1084         const internal::Util::WaveIdTable& table = reader.GetWaveIdTable();
1085 
1086         for ( u32 i = 0; i < table.GetCount(); i++ )
1087         {
1088             const internal::Util::WaveId& waveId = table.GetWaveId( i );
1089             u32 warcId = waveId.waveArchiveId;
1090             u32 waveIndex = waveId.waveIndex;
1091             if ( ! IsWaveArchiveDataLoaded( warcId, waveIndex ) )
1092             {
1093                 return false;
1094             }
1095         }
1096     }
1097     return true;
1098 }
1099 
1100 // LOAD_WARC が有効なだけ呼ばれるので、u32 loadFlag は必要ない。
IsWaveArchiveDataLoaded(SoundArchive::ItemId itemId,u32 waveIndex) const1101 bool SoundDataManager::IsWaveArchiveDataLoaded(
1102         SoundArchive::ItemId itemId, u32 waveIndex ) const
1103 {
1104     const void* pWarcFile = NULL;
1105     {
1106         u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1107         pWarcFile = detail_GetFileAddress( fileId );
1108     }
1109     if ( pWarcFile == NULL )
1110     {
1111         return false;
1112     }
1113 
1114     SoundArchive::WaveArchiveInfo info;
1115     if ( ! m_pSoundArchive->ReadWaveArchiveInfo( itemId, &info ) )
1116     {
1117         return false;
1118     }
1119     if ( info.isLoadIndividual == true )
1120     {
1121         internal::WaveArchiveFileReader reader( pWarcFile, true );
1122         if ( waveIndex != SoundArchive::INVALID_ID )
1123         {
1124             if ( ! reader.IsLoaded( waveIndex ) )
1125             {
1126                 return false;
1127             }
1128         }
1129         else
1130         {
1131             // 波形アーカイブのみのロード確認 and 個別ロード時は、全部確認
1132             u32 waveCount = reader.GetWaveFileCount();
1133             for ( u32 i = 0; i < waveCount; i++ )
1134             {
1135                 if ( ! reader.IsLoaded( i ) )
1136                 {
1137                     return false;
1138                 }
1139             }
1140         }
1141     }
1142     return true;
1143 }
1144 
1145 // 中身がなにか分からないので u32 loadFlag は必要ない
IsGroupDataLoaded(SoundArchive::ItemId itemId) const1146 bool SoundDataManager::IsGroupDataLoaded( SoundArchive::ItemId itemId ) const
1147 {
1148     u32 fileId = m_pSoundArchive->GetItemFileId( itemId );
1149     if ( detail_GetFileAddress( fileId ) == NULL )
1150     {
1151         return false;
1152     }
1153     return true;
1154 }
1155 
IsSoundGroupDataLoaded(SoundArchive::ItemId itemId,u32 loadFlag) const1156 bool SoundDataManager::IsSoundGroupDataLoaded(
1157         SoundArchive::ItemId itemId, u32 loadFlag ) const
1158 {
1159     SoundArchive::SoundGroupInfo info;
1160     if ( ! m_pSoundArchive->detail_ReadSoundGroupInfo( itemId, &info ) )
1161     {
1162         return false;
1163     }
1164 
1165     switch ( m_pSoundArchive->GetSoundType( info.startId ) )
1166     {
1167     case SoundArchive::SOUND_TYPE_SEQ:
1168         for ( u32 id = info.startId; id <= info.endId; id++ )
1169         {
1170             if ( ! IsSequenceSoundDataLoaded( id, loadFlag ) )
1171             {
1172                 return false;
1173             }
1174         }
1175         break;
1176     case SoundArchive::SOUND_TYPE_WAVE:
1177         for ( u32 id = info.startId; id <= info.endId; id++ )
1178         {
1179             if ( ! IsWaveSoundDataLoaded( id, loadFlag ) )
1180             {
1181                 return false;
1182             }
1183         }
1184         break;
1185     }
1186     return true;
1187 }
1188 
1189 
1190 } // namespace nw::snd
1191 } // namespace nw
1192 
1193