1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_SoundArchivePlayer.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: 30089 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/snd/snd_SoundArchivePlayer.h>
19
20 #include <nw/snd/snd_SoundSystem.h>
21 #include <nw/snd/snd_SoundDataManager.h>
22 #include <nw/snd/snd_SoundPlayer.h>
23 #include <nw/snd/snd_SoundHandle.h>
24 #include <nw/snd/snd_SoundActor.h>
25 #include <nw/snd/snd_Bank.h>
26 #include <nw/snd/snd_SequenceSoundFileReader.h>
27 #include <nw/snd/snd_WaveSoundFileReader.h>
28 #include <nw/snd/snd_WaveArchiveFileReader.h>
29 #include <nw/snd/snd_WaveFileReader.h>
30 #include <nw/snd/snd_Debug.h>
31 #include <nw/snd/snd_Util.h>
32 #include <nw/snd/snd_PlayerHeap.h>
33 #include <nw/snd/snd_DriverCommandManager.h>
34
35 namespace
36 {
37 }
38
39 namespace nw {
40 namespace snd {
41
42 /*---------------------------------------------------------------------------*
43 Name: SoundArchivePlayer
44
45 Description: コンストラクタ
46
47 Arguments: 無し
48
49 Returns: 無し
50 *---------------------------------------------------------------------------*/
SoundArchivePlayer()51 SoundArchivePlayer::SoundArchivePlayer()
52 : m_pSoundArchive( NULL ),
53 m_SequenceCallback( *this ),
54 m_WaveSoundCallback( *this ),
55 m_SequenceUserprocCallback( NULL ),
56 m_pSequenceUserprocCallbackArg( NULL ),
57 m_SoundPlayerCount( 0 ),
58 m_pSoundPlayers( NULL ),
59 m_MmlSequenceTrackAllocator( &m_MmlParser ),
60 m_pSetupBufferAddress( NULL ),
61 m_SetupBufferSize( 0 )
62 {
63 }
64
65 /*---------------------------------------------------------------------------*
66 Name: SoundArchivePlayer
67
68 Description: デストラクタ
69
70 Arguments: 無し
71
72 Returns: 無し
73 *---------------------------------------------------------------------------*/
~SoundArchivePlayer()74 SoundArchivePlayer::~SoundArchivePlayer()
75 {
76 }
77
78 /*---------------------------------------------------------------------------*
79 Name: IsAvailable
80
81 Description: サウンドアーカイブプレイヤーが利用可能かどうかを調べる
82
83 Arguments: 無し
84
85 Returns: 利用可能かどうかを返す
86 *---------------------------------------------------------------------------*/
IsAvailable() const87 bool SoundArchivePlayer::IsAvailable() const
88 {
89 if ( m_pSoundArchive == NULL )
90 {
91 return false;
92 }
93 if ( ! m_pSoundArchive->IsAvailable() )
94 {
95 return false;
96 }
97
98 return true;
99 }
100
101 /*---------------------------------------------------------------------------*
102 Name: Initialize
103
104 Description: サウンドアーカイブ中のプレイヤー情報にしたがって
105 プレイヤーをセットアップする
106
107 Arguments: arc - サウンドアーカイブ
108 buffer - セットアップに使用するメモリ
109 size - メモリサイズ
110 aramBuffer - セットアップに使用するAメモリ
111 aramSize - メモリサイズ
112
113 Returns: セットアップに成功したらtrue
114 *---------------------------------------------------------------------------*/
Initialize(const SoundArchive * arc,const SoundDataManager * manager,void * buffer,u32 size,void * strmBuffer,u32 strmBufferSize)115 bool SoundArchivePlayer::Initialize(
116 const SoundArchive* arc,
117 const SoundDataManager* manager,
118 void* buffer,
119 u32 size,
120 void* strmBuffer,
121 u32 strmBufferSize
122 )
123 {
124 // サウンドシステムの初期化が必要
125 NW_ASSERT( SoundSystem::IsInitialized() );
126 if ( ! SoundSystem::IsInitialized() )
127 {
128 return false;
129 }
130
131 NW_NULL_ASSERT( arc );
132 NW_NULL_ASSERT( manager );
133 NW_NULL_ASSERT( buffer );
134 NW_ALIGN32_ASSERT( buffer );
135
136 if ( strmBufferSize > 0 ) {
137 NW_NULL_ASSERT( strmBuffer );
138 NW_ALIGN32_ASSERT( strmBuffer );
139
140 if ( ! internal::Util::IsDeviceMemory(
141 reinterpret_cast<uptr>(strmBuffer), strmBufferSize ) )
142 {
143 NW_ASSERTMSG( false,
144 "strmBuffer, strmBuffer + strmBufferSize is not Device Memory.");
145 return false;
146 }
147 }
148 NW_ASSERT( strmBufferSize >= GetRequiredStreamBufferSize( arc ) );
149
150 // ストリームバッファは 4 倍まで
151 NW_ASSERT( strmBufferSize <= GetRequiredStreamBufferSize( arc ) * internal::driver::StreamChannel::WAVE_BUFFER_MULTIPLYING_FACTOR );
152
153 if ( ! SetupMram( arc, buffer, size ) ) {
154 return false;
155 }
156
157 if ( ! SetupStreamBuffer( arc, strmBuffer, strmBufferSize ) ) {
158 return false;
159 }
160
161 m_pSequenceTrackAllocator = &m_MmlSequenceTrackAllocator;
162 m_pSoundDataManager = manager;
163 return true;
164 }
165
166 /*---------------------------------------------------------------------------*
167 Name: Finalize
168
169 Description: サウンドアーカイブプレイヤーの機能を停止させる
170
171 Arguments: 無し
172
173 Returns: 無し
174 *---------------------------------------------------------------------------*/
Finalize()175 void SoundArchivePlayer::Finalize()
176 {
177 // 参照の破棄
178 m_pSoundArchive = NULL;
179 m_pSequenceTrackAllocator = NULL;
180
181 // 全サウンドの停止
182 for ( SoundArchive::ItemId playerId = 0; playerId < m_SoundPlayerCount ; ++playerId )
183 {
184 m_pSoundPlayers[ playerId ].StopAllSound(0);
185 }
186
187 // 停止完了待ち
188 internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
189 u32 tag = cmdmgr.FlushCommand( true );
190 cmdmgr.WaitCommandReply( tag );
191
192 // インスタンスの破棄
193 m_SoundPlayerCount = 0;
194 m_pSoundPlayers = NULL;
195
196 m_StreamBufferPool.Finalize();
197
198 if ( m_pSetupBufferAddress != NULL )
199 {
200 m_SequenceSoundInstanceManager.Destroy( m_pSetupBufferAddress, m_SetupBufferSize );
201 m_MmlSequenceTrackAllocator.Destroy( m_pSetupBufferAddress, m_SetupBufferSize );
202 m_WaveSoundInstanceManager.Destroy( m_pSetupBufferAddress, m_SetupBufferSize );
203 m_StreamSoundInstanceManager.Destroy( m_pSetupBufferAddress, m_SetupBufferSize );
204
205 m_pSetupBufferAddress = NULL;
206 m_SetupBufferSize = 0;
207 }
208 }
209
210
211 /*---------------------------------------------------------------------------*
212 Name: GetRequiredMemSize
213
214 Description: サウンドアーカイブプレイヤーで使用するメモリサイズを取得する
215
216 Arguments: arc - サウンドアーカイブ
217
218 Returns: 無し
219 *---------------------------------------------------------------------------*/
GetRequiredMemSize(const SoundArchive * arc)220 size_t SoundArchivePlayer::GetRequiredMemSize( const SoundArchive* arc )
221 {
222 NW_NULL_ASSERT( arc );
223
224 size_t size = 0;
225
226 // SoundPlayer
227 {
228 u32 playerCount = arc->GetPlayerCount();
229 size += ut::RoundUp( playerCount * sizeof( SoundPlayer ), 4 );
230
231 for ( u32 playerIndex = 0; playerIndex < playerCount; ++playerIndex )
232 {
233 SoundArchive::PlayerInfo playerInfo;
234 if ( ! arc->ReadPlayerInfo( internal::Util::GetMaskedItemId(
235 playerIndex, internal::ItemType_Player ), &playerInfo ) )
236 {
237 continue;
238 }
239
240 if ( playerInfo.playerHeapSize > 0 )
241 {
242 for ( int i = 0; i < playerInfo.playableSoundMax ; i++ )
243 {
244 size += ut::RoundUp( sizeof(internal::PlayerHeap), 4 );
245 size = ut::RoundUp( size, 32 );
246 size += ut::RoundUp( playerInfo.playerHeapSize, 4 );
247 }
248 }
249 }
250 }
251
252 SoundArchive::SoundArchivePlayerInfo soundArchivePlayerInfo;
253 if ( arc->ReadSoundArchivePlayerInfo( &soundArchivePlayerInfo ) )
254 {
255 // SequenceSound
256 size += ut::RoundUp(
257 m_SequenceSoundInstanceManager.GetRequiredMemSize(soundArchivePlayerInfo.sequenceSoundMax), 4 );
258
259 // WaveSound
260 size += ut::RoundUp(
261 m_WaveSoundInstanceManager.GetRequiredMemSize(soundArchivePlayerInfo.waveSoundMax), 4 );
262
263 // StreamSound
264 size += ut::RoundUp(
265 m_StreamSoundInstanceManager.GetRequiredMemSize(soundArchivePlayerInfo.streamSoundMax), 4 );
266
267 // SequenceTrack
268 size += ut::RoundUp(
269 soundArchivePlayerInfo.sequenceTrackMax *
270 sizeof( internal::driver::MmlSequenceTrack ), 4 );
271
272 }
273
274 return size;
275 }
276
277 /*---------------------------------------------------------------------------*
278 Name: GetRequiredStreamBufferSize
279
280 Description: サウンドアーカイブプレイヤーで使用するAメモリサイズを取得する
281
282 Arguments: arc - サウンドアーカイブ
283
284 Returns: 無し
285 *---------------------------------------------------------------------------*/
GetRequiredStreamBufferSize(const nw::snd::SoundArchive * arc)286 size_t SoundArchivePlayer::GetRequiredStreamBufferSize(
287 const nw::snd::SoundArchive* arc )
288 {
289 NW_NULL_ASSERT( arc );
290
291 int strmChannelCount = 0;
292
293 SoundArchive::SoundArchivePlayerInfo soundArchivePlayerInfo;
294 if ( arc->ReadSoundArchivePlayerInfo( &soundArchivePlayerInfo ) )
295 {
296 strmChannelCount = soundArchivePlayerInfo.streamChannelMax;
297 }
298
299 size_t memSize = static_cast<size_t>(
300 internal::driver::StreamSoundPlayer::DATA_BLOCK_SIZE_MAX
301 * DEFAULT_STREAM_BLOCK_COUNT
302 * strmChannelCount
303 );
304 return memSize;
305 }
306
307 /*---------------------------------------------------------------------------*
308 Name: SetupMram
309
310 Description: サウンドアーカイブ中のプレイヤー情報にしたがって
311 プレイヤーをセットアップする
312
313 Arguments: arc - サウンドアーカイブ
314 buffer - セットアップに使用するメモリ
315 size - メモリサイズ
316
317 Returns: セットアップに成功したらtrue
318 *---------------------------------------------------------------------------*/
SetupMram(const SoundArchive * arc,void * buffer,unsigned long size)319 bool SoundArchivePlayer::SetupMram( const SoundArchive* arc, void* buffer, unsigned long size )
320 {
321 NW_ASSERT( size >= GetRequiredMemSize( arc ) );
322
323 void* endp = static_cast<char*>(buffer) + size;
324
325 void* buf = buffer;
326 if ( ! SetupSoundPlayer( arc, &buf, endp ) )
327 {
328 return false;
329 }
330
331 SoundArchive::SoundArchivePlayerInfo soundArchivePlayerInfo;
332 if ( arc->ReadSoundArchivePlayerInfo( &soundArchivePlayerInfo ) )
333 {
334 if ( ! SetupSequenceSound( arc, soundArchivePlayerInfo.sequenceSoundMax, &buf, endp ) )
335 {
336 return false;
337 }
338
339 if ( ! SetupWaveSound( arc, soundArchivePlayerInfo.waveSoundMax, &buf, endp ) )
340 {
341 return false;
342 }
343
344 if ( ! SetupStreamSound( arc, soundArchivePlayerInfo.streamSoundMax, &buf, endp ) )
345 {
346 return false;
347 }
348
349 if ( ! SetupSequenceTrack( arc, soundArchivePlayerInfo.sequenceTrackMax, &buf, endp ) )
350 {
351 return false;
352 }
353 }
354
355 NW_ASSERT(
356 static_cast<char*>(buf) - static_cast<char*>(buffer) ==
357 static_cast<s32>( GetRequiredMemSize( arc ) ) );
358
359 m_pSoundArchive = arc;
360 m_pSetupBufferAddress = buffer;
361 m_SetupBufferSize = size;
362
363 return true;
364 }
365
366 /*---------------------------------------------------------------------------*
367 Name: CreatePlayerHeap
368
369 Description: プレイヤーヒープの作成
370
371 Arguments: heap - サウンドヒープ
372 size - プレイヤーヒープサイズ
373
374 Returns: 作成したプレイヤーヒープへのポインタ
375 *---------------------------------------------------------------------------*/
CreatePlayerHeap(void ** buffer,void * endp,size_t heapSize)376 internal::PlayerHeap* SoundArchivePlayer::CreatePlayerHeap(
377 void** buffer,
378 void* endp,
379 size_t heapSize
380 )
381 {
382 // プレイヤーヒープ構造体初期化
383 void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, sizeof(internal::PlayerHeap) ), 4 );
384 if ( ut::ComparePtr( ep, endp ) > 0 )
385 {
386 return NULL;
387 }
388 void* buf = *buffer;
389 *buffer = ep;
390
391 internal::PlayerHeap* playerHeap = new ( buf ) internal::PlayerHeap();
392
393 // プレイヤーヒープ構築
394 *buffer = ut::RoundUp( *buffer, 32 );
395 ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, heapSize ), 4 );
396 if ( ut::ComparePtr( ep, endp ) > 0 )
397 {
398 return NULL;
399 }
400 buf = *buffer;
401 *buffer = ep;
402
403 bool result = playerHeap->Create( buf, heapSize );
404
405 if ( ! result )
406 {
407 return NULL;
408 }
409
410 return playerHeap;
411 }
412
SetupSoundPlayer(const SoundArchive * arc,void ** buffer,void * endp)413 bool SoundArchivePlayer::SetupSoundPlayer(
414 const SoundArchive* arc,
415 void** buffer,
416 void* endp
417 )
418 {
419 u32 playerCount = arc->GetPlayerCount();
420 size_t requireSize = playerCount * sizeof( SoundPlayer );
421
422 void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requireSize ), 4 );
423 if ( ut::ComparePtr( ep, endp ) > 0 )
424 {
425 return false;
426 }
427 void* buf = *buffer;
428 *buffer = ep;
429
430 // buf 上に SoundPlayer インスタンスを playerCount 個並べる
431 m_pSoundPlayers = reinterpret_cast<SoundPlayer*>( buf );
432 m_SoundPlayerCount = playerCount;
433
434 u8* ptr = static_cast<u8*>( buf );
435 for ( u32 playerIndex = 0; playerIndex < playerCount;
436 ++playerIndex, ptr += sizeof( SoundPlayer ) )
437 {
438 SoundPlayer* player = new ( ptr ) SoundPlayer();
439
440 SoundArchive::PlayerInfo playerInfo;
441 if ( ! arc->ReadPlayerInfo( internal::Util::GetMaskedItemId(
442 playerIndex, internal::ItemType_Player ), &playerInfo ) )
443 {
444 continue;
445 }
446
447 player->SetPlayableSoundCount( playerInfo.playableSoundMax );
448
449 // プレイヤーヒープのセットアップ
450 if ( playerInfo.playerHeapSize > 0 )
451 {
452 for ( int i = 0; i < playerInfo.playableSoundMax ; i++ )
453 {
454 internal::PlayerHeap* playerHeap = CreatePlayerHeap(
455 buffer, endp, playerInfo.playerHeapSize );
456
457 NW_WARNING( playerHeap != NULL,
458 "failed to create player heap. ( player id = %d )", playerIndex );
459 if ( playerHeap == NULL )
460 {
461 return false;
462 }
463 player->detail_AppendPlayerHeap( playerHeap );
464 }
465
466 // プレイヤーヒープを使用する場合、
467 // 用意されたプレイヤーヒープ数を超える同時再生数は指定できない
468 player->detail_SetPlayableSoundLimit( playerInfo.playableSoundMax );
469 }
470 }
471
472 return true;
473 }
474
475 /*---------------------------------------------------------------------------*
476 Name: SetupSequenceSound
477
478 Description: シーケンスサウンドのセットアップ
479
480 Arguments: numSounds - 確保するシーケンスサウンドの数
481 heap - サウンドヒープ
482
483 Returns: 成功したかどうか
484 *---------------------------------------------------------------------------*/
SetupSequenceSound(const SoundArchive *,int numSounds,void ** buffer,void * endp)485 bool SoundArchivePlayer::SetupSequenceSound(
486 const SoundArchive* /*arc*/,
487 int numSounds,
488 void** buffer,
489 void* endp
490 )
491 {
492 size_t requireSize = m_SequenceSoundInstanceManager.GetRequiredMemSize(numSounds);
493
494 void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requireSize ), 4 );
495 if ( ut::ComparePtr( ep, endp ) > 0 )
496 {
497 return false;
498 }
499
500 unsigned long createNum = m_SequenceSoundInstanceManager.Create( *buffer, requireSize );
501 NW_ASSERT( createNum == numSounds );
502 *buffer = ep;
503
504 return true;
505 }
506
507 /*---------------------------------------------------------------------------*
508 Name: SetupWaveSound
509
510 Description: ウェーブサウンドのセットアップ
511
512 Arguments: numSounds - 確保するウェーブサウンドの数
513 heap - サウンドヒープ
514
515 Returns: 成功したかどうか
516 *---------------------------------------------------------------------------*/
SetupWaveSound(const SoundArchive *,int numSounds,void ** buffer,void * endp)517 bool SoundArchivePlayer::SetupWaveSound(
518 const SoundArchive* /*arc*/,
519 int numSounds,
520 void** buffer,
521 void* endp
522 )
523 {
524 size_t requireSize = m_WaveSoundInstanceManager.GetRequiredMemSize(numSounds);
525
526 void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requireSize ), 4 );
527 if ( ut::ComparePtr( ep, endp ) > 0 )
528 {
529 return false;
530 }
531
532 unsigned long createNum = m_WaveSoundInstanceManager.Create( *buffer, requireSize );
533 NW_ASSERT( createNum == numSounds );
534 *buffer = ep;
535
536 return true;
537 }
538
539 /*---------------------------------------------------------------------------*
540 Name: SetupStreamSound
541
542 Description: ストリームサウンドのセットアップ
543
544 Arguments: numSounds - 確保するストリームサウンドの数
545 heap - サウンドヒープ
546
547 Returns: 成功したかどうか
548 *---------------------------------------------------------------------------*/
SetupStreamSound(const SoundArchive *,int numSounds,void ** buffer,void * endp)549 bool SoundArchivePlayer::SetupStreamSound(
550 const SoundArchive* /*arc*/,
551 int numSounds,
552 void** buffer,
553 void* endp
554 )
555 {
556 size_t requireSize = m_StreamSoundInstanceManager.GetRequiredMemSize(numSounds);
557
558 void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requireSize ), 4 );
559 if ( ut::ComparePtr( ep, endp ) > 0 )
560 {
561 return false;
562 }
563
564 unsigned long createNum = m_StreamSoundInstanceManager.Create( *buffer, requireSize );
565 NW_ASSERT( createNum == numSounds );
566 *buffer = ep;
567
568 return true;
569 }
570
571 /*---------------------------------------------------------------------------*
572 Name: SetupSequenceTrack
573
574 Description: シーケンスサウンドのセットアップ
575
576 Arguments: numSounds - 確保するシーケンスサウンドの数
577 heap - サウンドヒープ
578
579 Returns: 成功したかどうか
580 *---------------------------------------------------------------------------*/
SetupSequenceTrack(const SoundArchive *,int numTracks,void ** buffer,void * endp)581 bool SoundArchivePlayer::SetupSequenceTrack(
582 const SoundArchive* /*arc*/,
583 int numTracks,
584 void** buffer,
585 void* endp
586 )
587 {
588 unsigned long requireSize = numTracks * sizeof( internal::driver::MmlSequenceTrack );
589
590 void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requireSize ), 4 );
591 if ( ut::ComparePtr( ep, endp ) > 0 )
592 {
593 return false;
594 }
595
596 unsigned long createNum = m_MmlSequenceTrackAllocator.Create( *buffer, requireSize );
597 NW_ASSERT( createNum == numTracks );
598 *buffer = ep;
599
600 return true;
601 }
602
603 /*---------------------------------------------------------------------------*
604 Name: SetupStreamBuffer
605
606 Description: ストリームチャンネルのセットアップ
607
608 Arguments: heap - サウンドヒープ
609
610 Returns: 成功したかどうか
611 *---------------------------------------------------------------------------*/
SetupStreamBuffer(const SoundArchive * arc,void * buffer,unsigned long size)612 bool SoundArchivePlayer::SetupStreamBuffer(
613 const SoundArchive* arc,
614 void* buffer,
615 unsigned long size
616 )
617 {
618 if ( size < GetRequiredStreamBufferSize( arc ) ) return false;
619
620 int strmChannelCount = 0;
621
622 SoundArchive::SoundArchivePlayerInfo soundArchivePlayerInfo;
623 if ( arc->ReadSoundArchivePlayerInfo( &soundArchivePlayerInfo ) )
624 {
625 strmChannelCount = soundArchivePlayerInfo.streamChannelMax;
626 }
627
628 m_StreamBufferPool.Initialize( buffer, size, strmChannelCount );
629
630 return true;
631 }
632
633 /*---------------------------------------------------------------------------*
634 Name: Update
635
636 Description: プレイヤーのフレーム処理を更新する
637
638 Arguments: None.
639
640 Returns: None.
641 *---------------------------------------------------------------------------*/
Update()642 void SoundArchivePlayer::Update()
643 {
644 for ( u32 playerIndex = 0;
645 playerIndex < m_SoundPlayerCount; ++playerIndex )
646 {
647 GetSoundPlayer( internal::Util::GetMaskedItemId(
648 playerIndex, internal::ItemType_Player ) ).Update();
649 }
650
651 m_SequenceSoundInstanceManager.SortPriorityList();
652 m_WaveSoundInstanceManager.SortPriorityList();
653 m_StreamSoundInstanceManager.SortPriorityList();
654
655 internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
656 cmdmgr.RecvCommandReply();
657 cmdmgr.FlushCommand( false );
658 }
659
GetSoundArchive() const660 const SoundArchive& SoundArchivePlayer::GetSoundArchive() const
661 {
662 NW_ASSERTMSG( m_pSoundArchive != NULL, "Setup is not completed." );
663 return *m_pSoundArchive;
664 }
665
GetSoundPlayer(SoundArchive::ItemId playerId)666 SoundPlayer& SoundArchivePlayer::GetSoundPlayer( SoundArchive::ItemId playerId )
667 {
668 u32 itemIndex = internal::Util::GetItemIndex( playerId );
669 NW_MINMAXLT_ASSERT( itemIndex, 0, m_SoundPlayerCount );
670 return m_pSoundPlayers[ itemIndex ];
671 }
672
GetSoundPlayer(const char * pStr)673 SoundPlayer& SoundArchivePlayer::GetSoundPlayer( const char* pStr )
674 {
675 NW_NULL_ASSERT( m_pSoundArchive );
676
677 SoundArchive::ItemId playerId = m_pSoundArchive->GetItemId( pStr );
678 NW_ASSERT( playerId != SoundArchive::INVALID_ID );
679 return GetSoundPlayer( playerId );
680 }
681
682
683 /*---------------------------------------------------------------------------*
684 Name: AllocSound
685
686 Description: サウンドを取得する
687
688 Arguments: manager - サウンドインスタンスマネージャ
689 soundId - サウンドID
690 priority - プレイヤープライオリティ
691 ambientPriority - アンビエントプライオリティ
692 ambientArgInfo - アンビエント情報
693
694 Returns: サウンドへのポインタ。取得できなかったらNULL
695 *---------------------------------------------------------------------------*/
696 template< typename Sound, typename Player >
AllocSound(internal::SoundInstanceManager<Sound,Player> * manager,SoundArchive::ItemId soundId,int priority,int ambientPriority,internal::BasicSound::AmbientInfo * ambientArgInfo)697 Sound* SoundArchivePlayer::AllocSound(
698 internal::SoundInstanceManager< Sound,Player >* manager,
699 SoundArchive::ItemId soundId,
700 int priority,
701 int ambientPriority,
702 internal::BasicSound::AmbientInfo* ambientArgInfo
703 )
704 {
705 NW_NULL_ASSERT( manager );
706
707 // サウンドの確保
708 Sound* sound = manager->Alloc( priority, ambientPriority );
709 if ( sound == NULL ) return NULL;
710
711 // ID設定
712 sound->SetId( soundId );
713
714 // アンビエント設定
715 if ( ambientArgInfo != NULL )
716 {
717 sound->SetAmbientInfo( *ambientArgInfo );
718 }
719
720 return sound;
721 }
722
723 const void*
detail_GetFileAddress(SoundArchive::FileId fileId) const724 SoundArchivePlayer::detail_GetFileAddress( SoundArchive::FileId fileId ) const
725 {
726 if ( m_pSoundDataManager == NULL ) return NULL;
727
728 return m_pSoundDataManager->detail_GetFileAddress( fileId );
729 }
730
detail_SetupSound(SoundHandle * handle,u32 soundId,bool holdFlag,const StartInfo * startInfo)731 SoundStartable::StartResult SoundArchivePlayer::detail_SetupSound(
732 SoundHandle* handle,
733 u32 soundId,
734 bool holdFlag,
735 const StartInfo* startInfo
736 )
737 {
738 return detail_SetupSoundImpl(
739 handle,
740 soundId,
741 NULL,
742 NULL,
743 holdFlag,
744 startInfo
745 );
746 }
747
748 /*---------------------------------------------------------------------------*
749 Name: detail_SetupSoundImpl
750
751 Description: 再生の実装関数
752
753 Arguments: handle - サウンドハンドル
754 soundId - サウンドID
755 ambientArgInfo - 外部パラメータ
756 actor - サウンドアクター
757 holdFlag - ホールドサウンドフラグ
758
759 Returns: 結果コード
760 *---------------------------------------------------------------------------*/
detail_SetupSoundImpl(SoundHandle * handle,u32 soundId,internal::BasicSound::AmbientInfo * ambientArgInfo,SoundActor * actor,bool holdFlag,const StartInfo * startInfo)761 SoundStartable::StartResult SoundArchivePlayer::detail_SetupSoundImpl(
762 SoundHandle* handle,
763 u32 soundId,
764 internal::BasicSound::AmbientInfo* ambientArgInfo,
765 SoundActor* actor,
766 bool holdFlag,
767 const StartInfo* startInfo
768 )
769 {
770 NW_NULL_ASSERT( handle );
771
772 if ( ! IsAvailable() )
773 {
774 SoundStartable::StartResult
775 result( SoundStartable::StartResult::START_ERR_NOT_AVAILABLE );
776 return result;
777 }
778
779 // サウンドハンドルを古いサウンドから切断
780 if ( handle->IsAttachedSound() ) {
781 handle->DetachSound();
782 }
783
784 // サウンドアーカイブからサウンド情報の取得
785 SoundArchive::SoundInfo soundInfo;
786 if ( ! m_pSoundArchive->ReadSoundInfo( soundId, &soundInfo ) )
787 {
788 SoundStartable::StartResult
789 result( SoundStartable::StartResult::START_ERR_INVALID_SOUNDID );
790 return result;
791 }
792
793 // StartInfoの処理
794 SoundStartable::StartInfo::StartOffsetType startOffsetType =
795 SoundStartable::StartInfo::START_OFFSET_TYPE_MILLISEC;
796 int startOffset = 0;
797 int playerPriority = soundInfo.playerPriority;
798 SoundArchive::ItemId playerId = soundInfo.playerId;
799 int actorPlayerId = soundInfo.actorPlayerId;
800 const SoundStartable::StartInfo::SeqSoundInfo* seqInfo = NULL;
801 if ( startInfo != NULL )
802 {
803 if ( startInfo->enableFlag & StartInfo::ENABLE_START_OFFSET )
804 {
805 startOffsetType = startInfo->startOffsetType;
806 startOffset = startInfo->startOffset;
807 }
808 if ( startInfo->enableFlag & StartInfo::ENABLE_PLAYER_PRIORITY )
809 {
810 playerPriority = startInfo->playerPriority;
811 }
812 if ( startInfo->enableFlag & StartInfo::ENABLE_PLAYER_ID )
813 {
814 playerId = startInfo->playerId;
815 }
816 if ( startInfo->enableFlag & StartInfo::ENABLE_ACTOR_PLAYER_ID )
817 {
818 actorPlayerId = startInfo->actorPlayerId;
819 }
820 if ( startInfo->enableFlag & StartInfo::ENABLE_SEQ_SOUND_INFO )
821 {
822 seqInfo = &startInfo->seqSoundInfo;
823 }
824 }
825
826 // プライオリティの計算
827 int priority = playerPriority;
828 if ( holdFlag ) --priority; // HoldSoundで再生するときは同プライオリティで先着優先
829
830 int ambientPriority = 0;
831 if ( ambientArgInfo != NULL )
832 {
833 ambientPriority = internal::BasicSound::GetAmbientPriority( *ambientArgInfo, soundId );
834 }
835 int allocPriority = priority + ambientPriority;
836 allocPriority = ut::Clamp( allocPriority, internal::BasicSound::PRIORITY_MIN, internal::BasicSound::PRIORITY_MAX );
837
838 // ExternalSoundPlayer
839 internal::ExternalSoundPlayer* extPlayer = NULL;
840 if ( actor != NULL ) {
841 extPlayer = actor->detail_GetActorPlayer( actorPlayerId );
842 if ( extPlayer == NULL )
843 {
844 NW_WARNING(
845 false,
846 "actorPlayerId(%d) is out of range. (0-%d)",
847 actorPlayerId,
848 SoundActor::ACTOR_PLAYER_COUNT-1
849 );
850 return StartResult::START_ERR_INVALID_PARAMETER;
851 }
852 }
853
854 // プレイヤーの空きをチェック
855 SoundPlayer& player = GetSoundPlayer( playerId );
856 if ( ! player.detail_CanPlaySound( allocPriority ) ) {
857 return StartResult::START_ERR_LOW_PRIORITY;
858 }
859 if ( ( extPlayer != NULL ) && ( ! extPlayer->detail_CanPlaySound( allocPriority ) ) ) {
860 return StartResult::START_ERR_LOW_PRIORITY;
861 }
862
863 // サウンドのアロケート
864 internal::BasicSound* sound = NULL;
865 internal::SequenceSound* seqSound = NULL;
866 internal::StreamSound* strmSound = NULL;
867 internal::WaveSound* waveSound = NULL;
868
869 switch ( m_pSoundArchive->GetSoundType( soundId ) )
870 {
871 case SoundArchive::SOUND_TYPE_SEQ:
872 seqSound = AllocSound<internal::SequenceSound>(
873 &m_SequenceSoundInstanceManager,
874 soundId,
875 priority,
876 ambientPriority,
877 ambientArgInfo
878 );
879 if ( seqSound == NULL )
880 {
881 NW_WARNING(
882 ! internal::Debug_GetWarningFlag( DEBUG_WARNING_NOT_ENOUGH_SEQSOUND ),
883 "Failed to start sound (id:0x%08x) for not enough SequenceSound instance.",
884 soundId
885 );
886 SoundStartable::StartResult
887 result( SoundStartable::StartResult::START_ERR_NOT_ENOUGH_INSTANCE );
888 return result;
889 }
890 sound = seqSound;
891 break;
892
893 case SoundArchive::SOUND_TYPE_STRM:
894 strmSound = AllocSound<internal::StreamSound>(
895 &m_StreamSoundInstanceManager,
896 soundId,
897 priority,
898 ambientPriority,
899 ambientArgInfo
900 );
901 if ( strmSound == NULL )
902 {
903 NW_WARNING(
904 ! internal::Debug_GetWarningFlag( DEBUG_WARNING_NOT_ENOUGH_STRMSOUND ),
905 "Failed to start sound (id:0x%08x) for not enough StreamSound instance.",
906 soundId
907 );
908 SoundStartable::StartResult
909 result( SoundStartable::StartResult::START_ERR_NOT_ENOUGH_INSTANCE );
910 return result;
911 }
912 sound = strmSound;
913 break;
914
915 case SoundArchive::SOUND_TYPE_WAVE:
916 waveSound = AllocSound<internal::WaveSound>(
917 &m_WaveSoundInstanceManager,
918 soundId,
919 priority,
920 ambientPriority,
921 ambientArgInfo
922 );
923 if ( waveSound == NULL )
924 {
925 NW_WARNING(
926 ! internal::Debug_GetWarningFlag( DEBUG_WARNING_NOT_ENOUGH_WAVESOUND ),
927 "Failed to start sound (id:0x%08x) for not enough WaveSound instance.",
928 soundId
929 );
930 SoundStartable::StartResult
931 result( SoundStartable::StartResult::START_ERR_NOT_ENOUGH_INSTANCE );
932 return result;
933 }
934 sound = waveSound;
935 break;
936
937 default:
938 {
939 SoundStartable::StartResult
940 result( SoundStartable::StartResult::START_ERR_INVALID_SOUNDID );
941 return result;
942 }
943 }
944
945 // サウンドプレイヤーに登録
946 if ( ! player.detail_AppendSound( sound ) )
947 {
948 sound->Finalize();
949 SoundStartable::StartResult
950 result( SoundStartable::StartResult::START_ERR_UNKNOWN );
951 return result;
952 }
953
954 // フロントバイパス設定
955 sound->SetFrontBypass( soundInfo.isFrontBypass );
956
957 // サウンドのプリペア
958 switch ( m_pSoundArchive->GetSoundType( soundId ) )
959 {
960 case SoundArchive::SOUND_TYPE_SEQ:
961 {
962 NW_NULL_ASSERT( seqSound );
963
964 // プレイヤーヒープの確保
965 (void)player.detail_AllocPlayerHeap( seqSound );
966
967 // シーケンスサウンド情報の取得
968 SoundArchive::SequenceSoundInfo info;
969 if ( ! m_pSoundArchive->ReadSequenceSoundInfo( soundId, &info ) ) {
970 seqSound->Finalize();
971 SoundStartable::StartResult
972 result( SoundStartable::StartResult::START_ERR_INVALID_SOUNDID );
973 return result;
974 }
975
976 // バンクの上書き (必要であれば)
977 if ( seqInfo != NULL )
978 {
979 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
980 {
981 SoundArchive::ItemId bankId = seqInfo->bankIds[ i ];
982 if ( bankId != SoundArchive::INVALID_ID )
983 {
984 info.bankIds[ i ] = seqInfo->bankIds[ i ];
985 }
986 }
987 }
988
989 // シーケンスサウンドの準備
990 StartResult result = PrepareSequenceSoundImpl(
991 seqSound,
992 &soundInfo,
993 &info,
994 startOffsetType,
995 startOffset,
996 seqInfo
997 );
998 if ( ! result.IsSuccess() )
999 {
1000 seqSound->Finalize();
1001 return result;
1002 }
1003 break;
1004 }
1005
1006 case SoundArchive::SOUND_TYPE_STRM:
1007 {
1008 NW_NULL_ASSERT( strmSound );
1009
1010 // ストリームサウンド情報の取得
1011 SoundArchive::StreamSoundInfo info;
1012 if ( ! m_pSoundArchive->detail_ReadStreamSoundInfo( soundId, &info ) ) {
1013 strmSound->Finalize();
1014 SoundStartable::StartResult
1015 result( SoundStartable::StartResult::START_ERR_INVALID_SOUNDID );
1016 return result;
1017 }
1018
1019 // ストリームサウンドの準備
1020 StartResult result = PrepareStreamSoundImpl(
1021 strmSound,
1022 &soundInfo,
1023 &info,
1024 startOffsetType,
1025 startOffset
1026 );
1027 if ( ! result.IsSuccess() )
1028 {
1029 strmSound->Finalize();
1030 return result;
1031 }
1032 break;
1033 }
1034
1035 case SoundArchive::SOUND_TYPE_WAVE:
1036 {
1037 NW_NULL_ASSERT( waveSound );
1038
1039 // プレイヤーヒープの確保
1040 (void)player.detail_AllocPlayerHeap( waveSound );
1041
1042 // ウェーブサウンド情報の取得
1043 SoundArchive::WaveSoundInfo info;
1044 if ( ! m_pSoundArchive->detail_ReadWaveSoundInfo( soundId, &info ) ) {
1045 waveSound->Finalize();
1046 SoundStartable::StartResult
1047 result( SoundStartable::StartResult::START_ERR_INVALID_SOUNDID );
1048 return result;
1049 }
1050
1051 // ウェーブサウンドの準備
1052 StartResult result = PrepareWaveSoundImpl(
1053 waveSound,
1054 &soundInfo,
1055 &info,
1056 startOffsetType,
1057 startOffset
1058 );
1059 if ( ! result.IsSuccess() )
1060 {
1061 waveSound->Finalize();
1062 return result;
1063 }
1064 break;
1065 }
1066
1067 default:
1068 NW_ASSERT( false );
1069 sound->Finalize();
1070 {
1071 return StartResult::START_ERR_INVALID_SOUNDID;
1072 }
1073 }
1074
1075 // 外部プレイヤーに登録
1076 if ( extPlayer != NULL )
1077 {
1078 if ( ! extPlayer->AppendSound( sound ) )
1079 {
1080 sound->Finalize();
1081 return StartResult::START_ERR_UNKNOWN;
1082 }
1083 }
1084
1085 // アクターに登録
1086 if ( actor != NULL )
1087 {
1088 sound->AttachSoundActor( actor );
1089 }
1090
1091 // プライオリティの再設定
1092 if ( holdFlag )
1093 {
1094 sound->SetPlayerPriority( playerPriority );
1095 }
1096
1097 // サウンドハンドルを確保したサウンドと接続
1098 handle->detail_AttachSound( sound );
1099
1100 SoundStartable::StartResult
1101 result( SoundStartable::StartResult::START_SUCCESS );
1102 return result;
1103 }
1104
1105 /*---------------------------------------------------------------------------*
1106 Name: PrepareSequenceSoundImpl
1107
1108 Description: シーケンスを再生
1109
1110 Arguments: playerId - プレイヤー番号
1111 playerPrio - プレイヤープライオリティ
1112 info - シーケンス情報構造体のポインタ
1113 seqId - シーケンス番号
1114
1115 Returns: 成功したかどうか
1116 *---------------------------------------------------------------------------*/
PrepareSequenceSoundImpl(internal::SequenceSound * sound,const SoundArchive::SoundInfo * commonInfo,const SoundArchive::SequenceSoundInfo * info,SoundStartable::StartInfo::StartOffsetType startOffsetType,int startOffset,const StartInfo::SeqSoundInfo * externalSeqInfo)1117 SoundStartable::StartResult SoundArchivePlayer::PrepareSequenceSoundImpl(
1118 internal::SequenceSound* sound,
1119 const SoundArchive::SoundInfo* commonInfo,
1120 const SoundArchive::SequenceSoundInfo* info,
1121 SoundStartable::StartInfo::StartOffsetType startOffsetType,
1122 int startOffset,
1123 const StartInfo::SeqSoundInfo* externalSeqInfo
1124 )
1125 {
1126 NW_NULL_ASSERT( info );
1127
1128 const internal::SequenceSoundFile* seqFile =
1129 reinterpret_cast<const internal::SequenceSoundFile*>(
1130 m_pSoundDataManager->detail_GetFileAddress( commonInfo->fileId ) );
1131 u32 seqOffset = info->startOffset;
1132 u32 allocTrackBitFlag = info->allocateTrackFlags;
1133
1134 // シーケンスデータの確定 (外部ファイルかどうか)
1135 if ( externalSeqInfo != NULL )
1136 {
1137 const void* extSeqFile = externalSeqInfo->seqDataAddress;
1138 if ( extSeqFile != NULL )
1139 {
1140 seqFile = reinterpret_cast<const internal::SequenceSoundFile*>( extSeqFile );
1141 }
1142
1143 internal::SequenceSoundFileReader seqFileReader( seqFile );
1144 const char* startLabel = externalSeqInfo->startLocationLabel;
1145 if ( startLabel != NULL )
1146 {
1147 if ( ! seqFileReader.GetOffsetByLabel( startLabel, &seqOffset ) )
1148 {
1149 SoundStartable::StartResult result(
1150 SoundStartable::StartResult::START_ERR_INVALID_SEQ_START_LOCATION_LABEL );
1151 return result;
1152 }
1153 seqOffset = internal::driver::MmlParser::ParseAllocTrack(
1154 seqFileReader.GetSequenceData(),
1155 seqOffset,
1156 &allocTrackBitFlag );
1157 }
1158 }
1159
1160 internal::PlayerHeap* pPlayerHeap = sound->GetPlayerHeap();
1161 bool isRegisterDataLoadTask = false;
1162 internal::LoadItemInfo loadSeq;
1163 internal::LoadItemInfo loadBanks[SoundArchive::SEQ_BANK_MAX];
1164 int fileAddressCount = 0;
1165
1166
1167 // 関連データがあるかどうかのチェック
1168 // 現実装では、SEQ/BANK/WARC/WARC内の各波形 が全てロードされているか確認している。
1169 // ロードされていないものがあれば、すぐわかるようなエラーコードを返す。
1170 // パフォーマンス的に問題がある場合は、問答無用で、タスクスレッド上で
1171 // LoadData( SEQ_ID ) のようにして数珠つなぎロードする。
1172
1173 // シーケンスデータがない場合は、プレイヤーヒープへのロードフラグを立てる
1174 loadSeq.itemId = sound->GetId();
1175 loadSeq.address = seqFile;
1176 if ( seqFile == NULL )
1177 {
1178 if ( pPlayerHeap == NULL )
1179 {
1180 SoundStartable::StartResult result(
1181 SoundStartable::StartResult::START_ERR_NOT_SEQ_LOADED );
1182 return result;
1183 }
1184 isRegisterDataLoadTask = true;
1185 }
1186
1187 // バンクデータがあるかチェック
1188 const void* bankFiles[ SoundArchive::SEQ_BANK_MAX ] = { NULL };
1189
1190 if ( externalSeqInfo != NULL )
1191 {
1192 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
1193 {
1194 loadBanks[i].itemId = externalSeqInfo->bankIds[ i ];
1195 }
1196 }
1197 else
1198 {
1199 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
1200 {
1201 loadBanks[i].itemId = info->bankIds[ i ];
1202 }
1203 }
1204
1205 for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
1206 {
1207 SoundArchive::BankInfo bankInfo;
1208 bool isReadBankInfo = GetSoundArchive().ReadBankInfo( loadBanks[i].itemId, &bankInfo );
1209 if ( isReadBankInfo )
1210 {
1211 const void* bankFile =
1212 m_pSoundDataManager->detail_GetFileAddress( bankInfo.fileId );
1213 loadBanks[i].address = bankFile;
1214
1215 // バンクデータがない場合は、プレイヤーヒープへのロードフラグを立てる
1216 if ( bankFile == NULL )
1217 {
1218 if ( pPlayerHeap == NULL )
1219 {
1220 SoundStartable::StartResult result(
1221 SoundStartable::StartResult::START_ERR_NOT_BANK_LOADED );
1222 return result;
1223 }
1224 isRegisterDataLoadTask = true;
1225 break;
1226 }
1227 // バンクデータがある場合は、波形アーカイブデータがあるかチェック
1228 else
1229 {
1230 bool isLoaded = internal::Util::IsLoadedWaveArchive(
1231 bankFile,
1232 *m_pSoundArchive,
1233 *m_pSoundDataManager );
1234 // 波形アーカイブ (および波形データ) が無い場合は、
1235 // プレイヤーヒープへのロードフラグを立てる
1236 if ( ! isLoaded )
1237 {
1238 if ( pPlayerHeap == NULL )
1239 {
1240 SoundStartable::StartResult result(
1241 SoundStartable::StartResult::START_ERR_NOT_WARC_LOADED );
1242 return result;
1243 }
1244 isRegisterDataLoadTask = true;
1245 break;
1246 }
1247 // 波形アーカイブがロード済みなら問題なし
1248 }
1249 }
1250 }
1251
1252 // コマンド化のため、トラックが足りないときのケアは無し
1253 sound->Setup(
1254 m_pSequenceTrackAllocator,
1255 allocTrackBitFlag,
1256 &m_SequenceCallback );
1257
1258 UpdateCommonSoundParam( sound, commonInfo );
1259
1260 sound->SetChannelPriority( info->channelPriority );
1261 sound->SetReleasePriorityFix( info->isReleasePriorityFix );
1262 sound->SetSequenceUserprocCallback(
1263 m_SequenceUserprocCallback, m_pSequenceUserprocCallbackArg );
1264
1265 internal::driver::SequenceSoundPlayer::OffsetType seqOffsetType;
1266 switch ( startOffsetType )
1267 {
1268 case SoundStartable::StartInfo::START_OFFSET_TYPE_MILLISEC:
1269 seqOffsetType = internal::driver::SequenceSoundPlayer::OFFSET_TYPE_MILLISEC;
1270 break;
1271 case SoundStartable::StartInfo::START_OFFSET_TYPE_TICK:
1272 seqOffsetType = internal::driver::SequenceSoundPlayer::OFFSET_TYPE_TICK;
1273 break;
1274 case SoundStartable::StartInfo::START_OFFSET_TYPE_SAMPLE:
1275 seqOffsetType = internal::driver::SequenceSoundPlayer::OFFSET_TYPE_TICK;
1276 startOffset = 0;
1277 break;
1278 default:
1279 seqOffsetType = internal::driver::SequenceSoundPlayer::OFFSET_TYPE_TICK;
1280 startOffset = 0;
1281 break;
1282 }
1283
1284 internal::SequenceSound::StartInfo startInfo =
1285 {
1286 static_cast<s32>( seqOffset ),
1287 seqOffsetType,
1288 startOffset
1289 };
1290
1291 if ( isRegisterDataLoadTask )
1292 {
1293 // 必要なデータが欠けている場合は、プレイヤーヒープへのロードタスクを投げる
1294 // (プリペアやバンクの設定は、タスク完了後のコールバック内で処理される)
1295 internal::SequenceSound::LoadInfo loadInfo =
1296 {
1297 m_pSoundArchive,
1298 m_pSoundDataManager,
1299 &loadSeq,
1300 loadBanks
1301 };
1302 bool result = sound->RegisterDataLoadTask( loadInfo, startInfo );
1303 if ( result == false )
1304 {
1305 SoundStartable::StartResult startResult(
1306 SoundStartable::StartResult::START_ERR_NOT_ENOUGH_PLAYER_HEAP );
1307 return startResult;
1308 }
1309 }
1310 else
1311 {
1312 // 必要なデータが全部揃っている場合は、プリペア処理を行う
1313 internal::SequenceSoundFileReader seqFileReader( seqFile );
1314 sound->Prepare( seqFileReader.GetSequenceData(), startInfo );
1315
1316 // バンクもセット
1317 sound->SetBankData( loadBanks );
1318 }
1319
1320 SoundStartable::StartResult startResult(
1321 SoundStartable::StartResult::START_SUCCESS );
1322 return startResult;
1323 }
1324
1325 /*---------------------------------------------------------------------------*
1326 Name: PrepareStreamSoundImpl
1327
1328 Description: ストリームを再生
1329
1330 Arguments: playerId - プレイヤー番号
1331 playerPrio - プレイヤープライオリティ
1332 info - ストリームの情報
1333 strmId - ストリーム番号
1334
1335 Returns: 成功したかどうか
1336 *---------------------------------------------------------------------------*/
PrepareStreamSoundImpl(internal::StreamSound * sound,const SoundArchive::SoundInfo * commonInfo,const SoundArchive::StreamSoundInfo * info,SoundStartable::StartInfo::StartOffsetType startOffsetType,int startOffset)1337 SoundStartable::StartResult SoundArchivePlayer::PrepareStreamSoundImpl(
1338 internal::StreamSound* sound,
1339 const SoundArchive::SoundInfo* commonInfo,
1340 const SoundArchive::StreamSoundInfo* info,
1341 SoundStartable::StartInfo::StartOffsetType startOffsetType,
1342 int startOffset
1343 )
1344 {
1345 // プレイヤーのセットアップ
1346 #if 0
1347 internal::driver::StreamSoundPlayer::SetupResult setupResult = sound->Initialize(
1348 &m_StreamBufferPool,
1349 info->allocChannelCount,
1350 info->allocTrackCount
1351 );
1352
1353 while ( setupResult != internal::driver::StreamSoundPlayer::SETUP_SUCCESS )
1354 {
1355 if ( setupResult == internal::driver::StreamSoundPlayer::SETUP_ERR_CANNOT_ALLOCATE_BUFFER )
1356 {
1357 // バッファが足りない
1358 if ( m_StreamSoundInstanceManager.GetActiveCount() == 1 )
1359 {
1360 // ほかにサウンドを再生していないのにバッファが足りない
1361 NW_WARNING(
1362 ! internal::Debug_GetWarningFlag( DEBUG_WARNING_NOT_ENOUGH_SEQTRACK ),
1363 "Failed to start sound (id:%d) for not enough StrmChannel instance.",
1364 sound->GetId()
1365 );
1366 SoundStartable::StartResult result(
1367 SoundStartable::StartResult::START_ERR_NOT_ENOUGH_INSTANCE );
1368 return result;
1369 }
1370
1371 internal::StreamSound* lowest = m_StreamSoundInstanceManager.GetLowestPrioritySound();
1372 if ( sound == lowest )
1373 {
1374 // 自分が一番プライオリティが低い
1375 NW_WARNING(
1376 ! internal::Debug_GetWarningFlag( DEBUG_WARNING_NOT_ENOUGH_SEQTRACK ),
1377 "Failed to start sound (id:%d) for not enough StrmChannel instance.",
1378 sound->GetId()
1379 );
1380 SoundStartable::StartResult result(
1381 SoundStartable::StartResult::START_ERR_NOT_ENOUGH_INSTANCE );
1382 return result;
1383 }
1384
1385 // もう一度 Initialize
1386 NW_WARNING(
1387 ! internal::Debug_GetWarningFlag( DEBUG_WARNING_NOT_ENOUGH_STRMCHANNEL ),
1388 "Sound (id:%d) is stopped for not enough StrmChannel instance.",
1389 lowest->GetId()
1390 );
1391 lowest->Stop( 0 );
1392 setupResult = sound->Initialize(
1393 &m_StreamBufferPool,
1394 info->allocChannelCount,
1395 info->allocTrackCount
1396 );
1397 }
1398 else
1399 {
1400 SoundStartable::StartResult result(
1401 SoundStartable::StartResult::START_ERR_UNKNOWN );
1402 return result;
1403 }
1404 }
1405 #else
1406 // 再生失敗時のケア無し
1407
1408 sound->Setup(
1409 &m_StreamBufferPool,
1410 info->allocChannelCount,
1411 info->allocTrackCount
1412 );
1413 #endif
1414
1415 // プリペア
1416 internal::driver::StreamSoundPlayer::StartOffsetType strmStartOffsetType;
1417 switch ( startOffsetType )
1418 {
1419 case SoundStartable::StartInfo::START_OFFSET_TYPE_MILLISEC:
1420 strmStartOffsetType = internal::driver::StreamSoundPlayer::START_OFFSET_TYPE_MILLISEC;
1421 break;
1422 case SoundStartable::StartInfo::START_OFFSET_TYPE_TICK:
1423 strmStartOffsetType = internal::driver::StreamSoundPlayer::START_OFFSET_TYPE_SAMPLE;
1424 startOffset = 0;
1425 break;
1426 case SoundStartable::StartInfo::START_OFFSET_TYPE_SAMPLE:
1427 strmStartOffsetType = internal::driver::StreamSoundPlayer::START_OFFSET_TYPE_SAMPLE;
1428 break;
1429 default:
1430 strmStartOffsetType = internal::driver::StreamSoundPlayer::START_OFFSET_TYPE_SAMPLE;
1431 startOffset = 0;
1432 break;
1433 }
1434
1435 void* fileStreamBuffer = sound->GetFileStreamBuffer();
1436 NW_NULL_ASSERT( fileStreamBuffer );
1437 long fileStreamBufferSize = sound->GetFileStreamBufferSize();
1438 io::FileStream* fileStream =
1439 const_cast<SoundArchive*>(m_pSoundArchive)->detail_OpenFileStream(
1440 commonInfo->fileId,
1441 fileStreamBuffer,
1442 fileStreamBufferSize
1443 );
1444 if ( fileStream == NULL ) {
1445 SoundStartable::StartResult result(
1446 SoundStartable::StartResult::START_ERR_CANNOT_OPEN_FILE );
1447 return result;
1448 }
1449
1450 sound->Prepare(
1451 strmStartOffsetType,
1452 startOffset,
1453 fileStream
1454 );
1455
1456 // パラメータ設定
1457 UpdateCommonSoundParam( sound, commonInfo );
1458
1459 SoundStartable::StartResult startResult(
1460 SoundStartable::StartResult::START_SUCCESS );
1461 return startResult;
1462 }
1463
1464 /*---------------------------------------------------------------------------*
1465 Name: PrepareWaveSoundImpl
1466
1467 Description: ウェーブサウンドを再生
1468
1469 Arguments: playerId - プレイヤー番号
1470 bankId - バンク番号
1471 playerPrio - プレイヤープライオリティ
1472 info - シーケンス情報構造体のポインタ
1473 seqId - シーケンス番号
1474
1475 Returns: 成功したかどうか
1476 *---------------------------------------------------------------------------*/
PrepareWaveSoundImpl(internal::WaveSound * sound,const SoundArchive::SoundInfo * commonInfo,const SoundArchive::WaveSoundInfo * info,SoundStartable::StartInfo::StartOffsetType startOffsetType,int startOffset)1477 SoundStartable::StartResult SoundArchivePlayer::PrepareWaveSoundImpl(
1478 internal::WaveSound* sound,
1479 const SoundArchive::SoundInfo* commonInfo,
1480 const SoundArchive::WaveSoundInfo* info,
1481 SoundStartable::StartInfo::StartOffsetType startOffsetType,
1482 int startOffset
1483 )
1484 {
1485 NW_NULL_ASSERT( info );
1486
1487 internal::PlayerHeap* pPlayerHeap = sound->GetPlayerHeap();
1488 bool isRegisterDataLoadTask = false;
1489 internal::LoadItemInfo loadWsd;
1490 // internal::LoadItemWarc loadWarc;
1491
1492 // データの取得
1493 const void* wsdFile = m_pSoundDataManager->detail_GetFileAddress( commonInfo->fileId );
1494 loadWsd.itemId = sound->GetId();
1495 loadWsd.address = wsdFile;
1496 if ( wsdFile == NULL )
1497 {
1498 if ( pPlayerHeap == NULL )
1499 {
1500 SoundStartable::StartResult result(
1501 SoundStartable::StartResult::START_ERR_NOT_WSD_LOADED );
1502 return result;
1503 }
1504 isRegisterDataLoadTask = true;
1505 }
1506 else
1507 {
1508 bool isLoaded = internal::Util::IsLoadedWaveArchive(
1509 wsdFile,
1510 info->index,
1511 *m_pSoundArchive,
1512 *m_pSoundDataManager );
1513 if ( ! isLoaded )
1514 {
1515 if ( pPlayerHeap == NULL )
1516 {
1517 SoundStartable::StartResult result(
1518 SoundStartable::StartResult::START_ERR_NOT_WARC_LOADED );
1519 return result;
1520 }
1521 isRegisterDataLoadTask = true;
1522 }
1523 }
1524
1525 internal::driver::WaveSoundPlayer::StartOffsetType wsdStartOffsetType;
1526 switch ( startOffsetType )
1527 {
1528 case SoundStartable::StartInfo::START_OFFSET_TYPE_MILLISEC:
1529 wsdStartOffsetType = internal::driver::WaveSoundPlayer::START_OFFSET_TYPE_MILLISEC;
1530 break;
1531 case SoundStartable::StartInfo::START_OFFSET_TYPE_TICK:
1532 wsdStartOffsetType = internal::driver::WaveSoundPlayer::START_OFFSET_TYPE_SAMPLE;
1533 startOffset = 0;
1534 break;
1535 case SoundStartable::StartInfo::START_OFFSET_TYPE_SAMPLE:
1536 wsdStartOffsetType = internal::driver::WaveSoundPlayer::START_OFFSET_TYPE_SAMPLE;
1537 break;
1538 default:
1539 wsdStartOffsetType = internal::driver::WaveSoundPlayer::START_OFFSET_TYPE_SAMPLE;
1540 startOffset = 0;
1541 break;
1542 }
1543
1544 internal::WaveSound::StartInfo startInfo =
1545 {
1546 static_cast<s32>( info->index ),
1547 wsdStartOffsetType,
1548 startOffset,
1549 &m_WaveSoundCallback,
1550 commonInfo->fileId
1551 };
1552
1553 if ( isRegisterDataLoadTask )
1554 {
1555 // 必要なデータが欠けている場合は、プレイヤーヒープへのロードタスクを投げる
1556 // (プリペアは、タスク完了後のコールバック内で処理される)
1557 internal::WaveSound::LoadInfo loadInfo =
1558 {
1559 m_pSoundArchive,
1560 m_pSoundDataManager,
1561 &loadWsd
1562 };
1563 bool result = sound->RegisterDataLoadTask( loadInfo, startInfo );
1564 }
1565 else
1566 {
1567 // 必要なデータが全部揃っている場合は、プリペア処理を行う
1568 sound->Prepare( wsdFile, startInfo );
1569 }
1570
1571 // パラメータ設定
1572 UpdateCommonSoundParam( sound, commonInfo );
1573 sound->SetChannelPriority( info->channelPriority );
1574 sound->SetReleasePriorityFix( info->isReleasePriorityFix );
1575
1576 SoundStartable::StartResult startResult(
1577 SoundStartable::StartResult::START_SUCCESS );
1578 return startResult;
1579 }
1580
1581 /*---------------------------------------------------------------------------*
1582 Name: UpdateCommonSoundParam
1583
1584 Description: サウンド共通パラメータの更新
1585
1586 Arguments: sound - 更新対象のサウンド
1587 commonInfo - サウンド共通パラメータ
1588
1589 Returns: None.
1590 *---------------------------------------------------------------------------*/
UpdateCommonSoundParam(internal::BasicSound * sound,const SoundArchive::SoundInfo * commonInfo)1591 void SoundArchivePlayer::UpdateCommonSoundParam(
1592 internal::BasicSound* sound,
1593 const SoundArchive::SoundInfo* commonInfo
1594 )
1595 {
1596 NW_NULL_ASSERT(sound);
1597 NW_NULL_ASSERT(commonInfo);
1598
1599 sound->SetInitialVolume( static_cast<float>( commonInfo->volume ) / 127.0f );
1600 sound->SetPanMode( commonInfo->panMode );
1601 sound->SetPanCurve( commonInfo->panCurve );
1602 }
1603
1604
1605 /*---------------------------------------------------------------------------*
1606 Name: SetSequenceUserprocCallback
1607
1608 Description: シーケンスコマンド'userproc'で呼び出されるコールバックを登録する
1609
1610 Arguments: callback - コールバック
1611 arg - コールバック引数
1612
1613 Returns:
1614 *---------------------------------------------------------------------------*/
SetSequenceUserprocCallback(SequenceUserprocCallback callback,void * callbackArg)1615 void SoundArchivePlayer::SetSequenceUserprocCallback( SequenceUserprocCallback callback, void* callbackArg )
1616 {
1617 m_SequenceUserprocCallback = callback;
1618 m_pSequenceUserprocCallbackArg = callbackArg;
1619 }
1620
1621 /*---------------------------------------------------------------------------*
1622 Name: NoteOn
1623
1624 Description: シーケンスサウンドのノートオン処理
1625
1626 Arguments:
1627
1628 Returns: None.
1629 *---------------------------------------------------------------------------*/
NoteOn(internal::driver::SequenceSoundPlayer * seqPlayer,u8 bankIndex,const internal::driver::NoteOnInfo & noteOnInfo)1630 internal::driver::Channel* SoundArchivePlayer::SequenceNoteOnCallback::NoteOn(
1631 internal::driver::SequenceSoundPlayer* seqPlayer,
1632 u8 bankIndex,
1633 const internal::driver::NoteOnInfo& noteOnInfo
1634 )
1635 {
1636 if ( ! m_pSoundArchivePlayer.IsAvailable() ) return NULL;
1637
1638 const SoundArchive& sndArc = m_pSoundArchivePlayer.GetSoundArchive();
1639
1640 // 当該ノートに該当する波形アーカイブ ID・波形アーカイブ内インデックス取得
1641 internal::driver::Bank bank;
1642 internal::driver::Channel* channel = bank.NoteOn(
1643 seqPlayer->GetBankFile( bankIndex ),
1644 noteOnInfo,
1645 sndArc,
1646 m_pSoundArchivePlayer,
1647 seqPlayer->GetPlayerHeapDataManager()
1648 );
1649
1650 internal::driver::SoundThread::GetInstance().IncrNoteOnCount();
1651 return channel;
1652 }
1653
1654 /* ========================================================================
1655 SoundArchivePlayer::WaveSoundCallback class
1656 ======================================================================== */
1657
1658 /*---------------------------------------------------------------------------*
1659 Name: GetWaveSoundData
1660
1661 Description: ウェーブサウンドの波形取得処理
1662
1663 Arguments:
1664
1665 Returns: None.
1666 *---------------------------------------------------------------------------*/
GetWaveSoundData(internal::WaveSoundInfo * info,internal::WaveSoundNoteInfo * noteInfo,internal::WaveInfo * waveInfo,const internal::driver::WaveSoundPlayer::WaveSoundCallbackArg & arg) const1667 bool SoundArchivePlayer::WaveSoundCallback::GetWaveSoundData(
1668 internal::WaveSoundInfo* info,
1669 internal::WaveSoundNoteInfo* noteInfo,
1670 internal::WaveInfo* waveInfo,
1671 const internal::driver::WaveSoundPlayer::WaveSoundCallbackArg& arg ) const
1672 {
1673 if ( ! m_pSoundArchivePlayer.IsAvailable() ) {
1674 return false;
1675 }
1676
1677 // ウェーブサウンド情報および、ノート情報を取得
1678 {
1679 internal::WaveSoundFileReader reader( arg.wsdFile );
1680 if ( ! reader.ReadWaveSoundInfo( info, arg.wsdIndex ) )
1681 {
1682 return false;
1683 }
1684 if ( ! reader.ReadNoteInfo( noteInfo, arg.wsdIndex, arg.noteIndex ) )
1685 {
1686 return false;
1687 }
1688 }
1689
1690 // 波形アーカイブ取得
1691 const SoundArchive& sndArc = m_pSoundArchivePlayer.GetSoundArchive();
1692
1693 // 波形ファイル取得
1694 const void* waveFile = internal::Util::GetWaveFile(
1695 noteInfo->waveArchiveId, noteInfo->waveIndex,
1696 sndArc, m_pSoundArchivePlayer );
1697 if ( waveFile == NULL )
1698 {
1699 if ( arg.dataMgr != NULL )
1700 {
1701 waveFile = internal::Util::GetWaveFile(
1702 noteInfo->waveArchiveId, noteInfo->waveIndex, sndArc, arg.dataMgr );
1703 if ( waveFile == NULL )
1704 {
1705 return NULL;
1706 }
1707 }
1708 else
1709 {
1710 return false;
1711 }
1712 }
1713
1714 // 波形ファイル情報取得
1715 {
1716 internal::WaveFileReader reader( waveFile );
1717 if ( ! reader.ReadWaveInfo( waveInfo ) )
1718 {
1719 return false;
1720 }
1721 }
1722
1723 return true;
1724 }
1725
1726 } // namespace nw::snd
1727 } // namespace nw
1728
1729