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