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