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