1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_WaveSound.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: 28902 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_WaveSound.h>
19 
20 #include <nn/os.h>
21 #include <nw/snd/snd_SoundInstanceManager.h>
22 #include <nw/snd/snd_DriverCommandManager.h>
23 #include <nw/snd/snd_TaskManager.h>
24 
25 namespace nw {
26 namespace snd {
27 namespace internal {
28 
29 NW_UT_RUNTIME_TYPEINFO_DEFINITION(WaveSound,BasicSound);
30 
31 /* ========================================================================
32         member function
33    ======================================================================== */
34 
35 /*---------------------------------------------------------------------------*
36   Name:         WaveSound
37 
38   Description:  コンストラクタ
39 
40   Arguments:    None.
41 
42   Returns:      None.
43  *---------------------------------------------------------------------------*/
WaveSound(WaveSoundInstanceManager & manager)44 WaveSound::WaveSound(
45     WaveSoundInstanceManager& manager
46 )
47 : m_pManager( manager ),
48   m_InitializeFlag(false)
49 {
50 }
51 
Initialize()52 void WaveSound::Initialize()
53 {
54     BasicSound::Initialize();
55 
56     m_pTempSpecialHandle = NULL;
57     m_LoadingFlag = false;
58     m_PreparedFlag = false;
59 
60     m_InitializeFlag = true;
61 }
62 
63 /*---------------------------------------------------------------------------*
64   Name:         Shutdown
65 
66   Description:  サウンドの終了
67 
68   Arguments:    None.
69 
70   Returns:      None.
71  *---------------------------------------------------------------------------*/
Finalize()72 void WaveSound::Finalize()
73 {
74     if ( ! m_InitializeFlag ) return;
75     m_InitializeFlag = false;
76 
77     // プレイヤーヒープにロード中の場合にロードを停止する
78     if ( m_LoadingFlag )
79     {
80         TaskManager::GetInstance().CancelTask( &m_DataLoadTask );
81         m_DataLoadTask.Wait();
82     }
83 
84     BasicSound::Finalize();
85 
86     m_pManager.Free( this );
87 }
88 
89 /*---------------------------------------------------------------------------*
90   Name:         Prepare
91 
92   Description:  サウンド開始
93 
94   Arguments:    seqDataBase   - シーケンスデータベースアドレス
95                 seqDataOffset - シーケンスデータのオフセット
96                 bank          - バンクデータ
97 
98   Returns:      None.
99  *---------------------------------------------------------------------------*/
Prepare(const void * wsdFile,const StartInfo & startInfo)100 void WaveSound::Prepare( const void* wsdFile, const StartInfo& startInfo )
101 {
102     NW_NULL_ASSERT( wsdFile );
103     NW_NULL_ASSERT( startInfo.callback );
104 
105     DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance();
106     DriverCommandWaveSoundSetup* command =
107         cmdmgr.AllocCommand<DriverCommandWaveSoundSetup>();
108     command->id              = DRIVER_COMMAND_WAVESND_SETUP;
109     command->player          = &m_WaveSoundPlayerInstance;
110     command->wsdFile         = wsdFile;
111     command->waveSoundOffset = startInfo.index;
112     command->startOffsetType = startInfo.startOffsetType;
113     command->offset          = startInfo.startOffset;
114     command->callback        = startInfo.callback;
115     command->callbackData    = startInfo.callbackData;
116     cmdmgr.PushCommand(command);
117 
118     m_PreparedFlag = true;
119 }
120 
RegisterDataLoadTask(const LoadInfo & loadInfo,const StartInfo & startInfo)121 bool WaveSound::RegisterDataLoadTask( const LoadInfo& loadInfo, const StartInfo& startInfo )
122 {
123     PlayerHeap* heap = GetPlayerHeap();
124     if ( heap == NULL )
125     {
126         return false;
127     }
128     m_DataManager.Initialize( loadInfo.arc );
129     m_DataLoadTask.m_pDataManager = &m_DataManager;
130     m_DataLoadTask.m_pAllocator = heap;
131     m_DataLoadTask.m_Callback = NotifyAsyncLoadFinishedFunc;
132     m_DataLoadTask.m_CallbackData = this;
133 
134     m_DataLoadTask.m_pSoundDataManager = loadInfo.mgr;
135     m_DataLoadTask.m_pSoundArchive = loadInfo.arc;
136     m_DataLoadTask.m_LoadInfoWsd = *(loadInfo.wsd);
137     m_DataLoadTask.m_Index = startInfo.index;
138 
139     m_StartInfo = startInfo;
140 
141     TaskManager::GetInstance().AppendTask( &m_DataLoadTask, TaskManager::PRIORITY_MIDDLE );
142     return true;
143 }
144 
145 /*---------------------------------------------------------------------------*
146   Name:         SetChannelPriority
147 
148   Description:  発音プライオリティを変更
149 
150   Arguments:    priority - 発音プライオリティ
151 
152   Returns:      None.
153  *---------------------------------------------------------------------------*/
SetChannelPriority(int priority)154 void WaveSound::SetChannelPriority( int priority )
155 {
156     NW_MINMAX_ASSERT( priority, 0, 127 );
157 
158     DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance();
159     DriverCommandWaveSoundChannelPrio* command =
160         cmdmgr.AllocCommand<DriverCommandWaveSoundChannelPrio>();
161     command->id = DRIVER_COMMAND_WAVESND_CHANNELPRIO;
162     command->player = &m_WaveSoundPlayerInstance;
163     command->priority = priority;
164     cmdmgr.PushCommand(command);
165 }
166 
167 /*---------------------------------------------------------------------------*
168   Name:         SetReleasePriorityFix
169 
170   Description:  リリース時のプライオリティを変化しないようにする
171 
172   Arguments:    fix -
173 
174   Returns:      なし
175  *---------------------------------------------------------------------------*/
SetReleasePriorityFix(bool fix)176 void WaveSound::SetReleasePriorityFix( bool fix )
177 {
178     DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance();
179     DriverCommandWaveSoundPrioFix* command =
180         cmdmgr.AllocCommand<DriverCommandWaveSoundPrioFix>();
181     command->id = DRIVER_COMMAND_WAVESND_PRIOFIX;
182     command->player = &m_WaveSoundPlayerInstance;
183     command->priorityFix = fix;
184     cmdmgr.PushCommand(command);
185 }
186 
187 /*---------------------------------------------------------------------------*
188   Name:         OnUpdatePlayerPriority
189 
190   Description:  プレイヤープライオリティを変更
191 
192   Arguments:
193 
194   Returns:      None.
195  *---------------------------------------------------------------------------*/
OnUpdatePlayerPriority()196 void WaveSound::OnUpdatePlayerPriority()
197 {
198     int priority = CalcCurrentPlayerPriority();
199     m_pManager.UpdatePriority( this, priority );
200 }
201 
IsAttachedTempSpecialHandle()202 bool WaveSound::IsAttachedTempSpecialHandle()
203 {
204     return m_pTempSpecialHandle != NULL;
205 }
206 
DetachTempSpecialHandle()207 void WaveSound::DetachTempSpecialHandle()
208 {
209     // TODO: m_pTempSpecialHandle->DetachSound();
210 }
211 
ReadWaveSoundDataInfo(WaveSoundDataInfo * info) const212 bool WaveSound::ReadWaveSoundDataInfo( WaveSoundDataInfo* info ) const
213 {
214     if ( ! IsPlayerAvailable() ) return false;
215     return m_WaveSoundPlayerInstance.ReadWaveSoundDataInfo( info );
216 }
217 
GetPlaySamplePosition() const218 long WaveSound::GetPlaySamplePosition() const
219 {
220     if ( ! IsPlayerAvailable() ) return 0;
221     return m_WaveSoundPlayerInstance.GetPlaySamplePosition();
222 }
223 
NotifyAsyncLoadFinishedFunc(bool result,const LoadItemInfo * wsd,void * userData)224 void WaveSound::NotifyAsyncLoadFinishedFunc(
225     bool result,
226     const LoadItemInfo* wsd,
227     void* userData )
228 {
229     NW_NULL_ASSERT( userData );
230     WaveSound* sound = static_cast<WaveSound*>( userData );
231 
232     sound->m_LoadingFlag = false;
233 
234     if ( ! result )
235     {
236         sound->Stop( 0 );
237         return;
238     }
239 
240     // プリペア
241     sound->Prepare( wsd->address, sound->m_StartInfo );
242 
243     // プレイヤーヒープを SeqPlayer にセット
244     sound->m_WaveSoundPlayerInstance.SetPlayerHeapDataManager(
245             &sound->m_DataManager );
246 }
247 
DataLoadTask()248 WaveSound::DataLoadTask::DataLoadTask()
249 : m_pDataManager( NULL ),
250   m_pAllocator( NULL ),
251   m_Callback( NULL ),
252   m_CallbackData( NULL )
253 {
254 }
255 
Execute()256 void WaveSound::DataLoadTask::Execute()
257 {
258     m_pAllocator->Clear(); // あらかじめクリアしておく
259 
260     if ( ( m_LoadInfoWsd.address == NULL ) &&
261          ( m_LoadInfoWsd.itemId != SoundArchive::INVALID_ID ) )
262     {
263         SoundArchive::ItemId soundId = m_LoadInfoWsd.itemId;
264 
265         if ( ! m_pDataManager->LoadData( soundId, m_pAllocator, SoundArchiveLoader::LOAD_WSD ) )
266         {
267             NW_WARNING( false, "failed to load WSD(%08x) to PlayerHeap", soundId );
268             if ( m_Callback )
269             {
270                 m_Callback( false, NULL, m_CallbackData );
271                 return;
272             }
273         }
274         m_LoadInfoWsd.address = m_pDataManager->detail_GetFileAddressByItemId( soundId );
275     }
276 
277     // SoundDataManager 側で波形アーカイブがロード済みか?
278     bool result = Util::IsLoadedWaveArchive(
279             m_LoadInfoWsd.address, m_Index, *m_pSoundArchive, *m_pSoundDataManager );
280     if ( ! result )
281     {
282         // 未ロードなら、ここでロードする
283         if ( ! m_pDataManager->detail_LoadWaveArchiveByWaveSoundFile(
284                     m_LoadInfoWsd.address, m_Index, m_pAllocator ) )
285         {
286             NW_WARNING( false,
287                     "failed to load WSD(%08x)'s WARC to PlayerHeap", m_LoadInfoWsd.itemId );
288             if ( m_Callback )
289             {
290                 m_Callback( false, NULL, m_CallbackData );
291                 return;
292             }
293         }
294     }
295 
296     // ロード完了
297     if ( m_Callback )
298     {
299         m_Callback( true, &m_LoadInfoWsd, m_CallbackData );
300     }
301 }
302 
303 } // namespace nw::snd::internal
304 } // namespace nw::snd
305 } // namespace nw
306 
307