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