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