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