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