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