1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: snd_SoundInstanceManager.h 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 #ifndef NW_SND_SOUND_INSTANCE_MANAGER_H_ 19 #define NW_SND_SOUND_INSTANCE_MANAGER_H_ 20 21 #include <nw/ut/ut_LinkList.h> 22 #include <nw/snd/snd_InstancePool.h> 23 #include <nw/snd/snd_BasicSound.h> 24 25 namespace nw { 26 namespace snd { 27 namespace internal { 28 29 /* ======================================================================== 30 SoundInstanceManager class 31 ======================================================================== */ 32 33 template < typename Sound, typename Player > 34 class SoundInstanceManager 35 { 36 /* ------------------------------------------------------------------------ 37 typename definition 38 ------------------------------------------------------------------------ */ 39 public: 40 typedef ut::LinkList< Sound, offsetof(Sound,m_PriorityLink)> PriorityList; 41 typedef typename PriorityList::Iterator Iterator; 42 43 /* ------------------------------------------------------------------------ 44 class member 45 ------------------------------------------------------------------------ */ 46 public: SoundInstanceManager()47 SoundInstanceManager() 48 { 49 // m_CriticalSection.Initialize(); 50 } 51 ~SoundInstanceManager()52 ~SoundInstanceManager() 53 { 54 // m_CriticalSection.Finalize(); 55 } 56 GetRequiredMemSize(int instanceCount)57 unsigned long GetRequiredMemSize( int instanceCount ) 58 { 59 return sizeof(Sound) * instanceCount; 60 } 61 62 /*---------------------------------------------------------------------------* 63 Name: Create 64 65 Description: 指定したメモリ領域をインスタンスマネージャに割り当てます 66 67 Arguments: buffer - メモリ領域の開始アドレス 68 size - メモリ領域のサイズ 69 70 Returns: 無し 71 *---------------------------------------------------------------------------*/ Create(void * buffer,unsigned long size)72 unsigned long Create( void* buffer, unsigned long size ) 73 { 74 NW_NULL_ASSERT( buffer ); 75 // nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); 76 77 char* ptr = static_cast<char*>(buffer); 78 const unsigned long numObjects = size / sizeof(Sound); 79 for( unsigned long i=0 ;i<numObjects; i++ ){ 80 Sound* sound = new( ptr ) Sound( *this ); 81 m_FreeList.PushBack( sound ); 82 ptr += sizeof(Sound); 83 } 84 return numObjects; 85 } 86 87 /*---------------------------------------------------------------------------* 88 Name: Destroy 89 90 Description: 指定したメモリ領域をインスタンスマネージャから解放します 91 解放するためにはメモリ領域が Free されている必要があります。 92 93 Arguments: buffer - メモリ領域の開始アドレス 94 size - メモリ領域のサイズ 95 96 Returns: 無し 97 *---------------------------------------------------------------------------*/ Destroy(void * buffer,unsigned long size)98 void Destroy( void* buffer, unsigned long size ) 99 { 100 NW_NULL_ASSERT( buffer ); 101 NW_ASSERT( m_PriorityList.IsEmpty() ); 102 103 (void)buffer; 104 (void)size; 105 106 m_FreeList.Clear(); 107 m_PriorityList.Clear(); 108 // nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); 109 } 110 111 /*---------------------------------------------------------------------------* 112 Name: Alloc 113 114 Description: インスタンスを確保する 115 マネージャーからインスタンスを確保します。 116 117 Arguments: priority - プライオリティ 118 ambientPriority - アンビエントプライオリティ 119 120 Returns: 確保したインスタンス、確保できなければNULL 121 *---------------------------------------------------------------------------*/ Alloc(int priority,int ambientPriority)122 Sound* Alloc( int priority, int ambientPriority ) 123 { 124 int allocPriority = priority + ambientPriority; 125 allocPriority = ut::Clamp( allocPriority, BasicSound::PRIORITY_MIN, BasicSound::PRIORITY_MAX ); 126 127 // nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); 128 129 Sound* sound = NULL; 130 while( sound == NULL ) 131 { 132 if ( ! m_FreeList.IsEmpty() ) 133 { 134 sound = &m_FreeList.GetFront(); 135 m_FreeList.PopFront(); 136 } 137 else 138 { 139 // get lowest priority sound 140 Sound* lowPrioSound = GetLowestPrioritySound(); 141 if ( lowPrioSound == NULL ) return NULL; 142 if ( allocPriority < lowPrioSound->CalcCurrentPlayerPriority() ) return NULL; 143 144 // m_CriticalSection.Leave(); 145 146 NW_WARNING( 147 ! internal::Debug_GetWarningFlag( 148 internal::Debug_GetDebugWarningFlagFromSoundType( 149 lowPrioSound->GetSoundType() ) ), 150 "Sound (id:0x%08x) is stopped for not enough %s sound instance.", 151 lowPrioSound->GetId(), 152 internal::Debug_GetSoundTypeString( lowPrioSound->GetSoundType() ) 153 ); 154 lowPrioSound->Stop( 0 ); 155 156 // m_CriticalSection.Enter(); 157 } 158 } 159 160 sound->Initialize(); 161 sound->SetPriority( priority, ambientPriority ); 162 163 InsertPriorityList( sound, allocPriority ); 164 return sound; 165 } 166 167 /*---------------------------------------------------------------------------* 168 Name: Free 169 170 Description: インスタンスをマネージャーに解放する 171 指定したインスタンスをマネージャーに対して解放します。 172 解放するインスタンスは、あらかじめ停止されている必要があります。 173 174 Arguments: sound - インスタンス 175 176 Returns: 無し 177 *---------------------------------------------------------------------------*/ Free(Sound * sound)178 void Free( Sound* sound ) 179 { 180 NW_NULL_ASSERT( sound ); 181 182 // nn::os::CriticalSection::ScopedLock lock( m_CriticalSection ); 183 184 RemovePriorityList( sound ); 185 186 sound->Finalize(); 187 m_FreeList.PushBack( sound ); 188 } 189 190 /*---------------------------------------------------------------------------* 191 Name: UpdatePriority 192 193 Description: 引数に指定したサウンドのプライオリティをプライオリティリストに 194 反映させる 195 196 Arguments: sound - インスタンス 197 priority - プライオリティ 198 199 Returns: 無し 200 *---------------------------------------------------------------------------*/ UpdatePriority(Sound * sound,int priority)201 void UpdatePriority( Sound* sound, int priority ) 202 { 203 // nn::os::CriticalSection::ScopedLock lock( m_CriticalSection ); 204 205 RemovePriorityList( sound ); 206 InsertPriorityList( sound, priority ); 207 } 208 209 /*---------------------------------------------------------------------------* 210 Name: SortPriorityList 211 212 Description: プライオリティリストをソートする 213 214 Arguments: 無し 215 216 Returns: 無し 217 *---------------------------------------------------------------------------*/ SortPriorityList()218 void SortPriorityList() 219 { 220 if ( m_PriorityList.GetSize() < 2 ) return; 221 222 // nn::os::CriticalSection::ScopedLock lock( m_CriticalSection ); 223 224 static const int TMP_NUM = 225 internal::BasicSound::PRIORITY_MAX - internal::BasicSound::PRIORITY_MIN + 1; 226 PriorityList tmplist[ TMP_NUM ]; // notice: large stack 227 228 while ( !m_PriorityList.IsEmpty() ) 229 { 230 Sound& front = m_PriorityList.GetFront(); 231 m_PriorityList.PopFront(); 232 tmplist[ front.CalcCurrentPlayerPriority() ].PushBack( &front ); 233 } 234 for ( int i=0; i<TMP_NUM; i++ ) 235 { 236 while ( !tmplist[i].IsEmpty() ) 237 { 238 Sound& front = tmplist[i].GetFront(); 239 tmplist[i].PopFront(); 240 m_PriorityList.PushBack( &front ); 241 } 242 } 243 } 244 245 /*---------------------------------------------------------------------------* 246 Name: GetLowestPrioritySound 247 248 Description: 最もプライオリティの低いサウンドを取得する 249 250 Arguments: なし 251 252 Returns: 253 *---------------------------------------------------------------------------*/ GetLowestPrioritySound()254 Sound* GetLowestPrioritySound() 255 { 256 if ( m_PriorityList.IsEmpty() ) return NULL; 257 return &m_PriorityList.GetFront(); 258 } 259 260 /*---------------------------------------------------------------------------* 261 Name: GetActiveCount 262 263 Description: 現在アクティブなサウンド数を取得する 264 265 Arguments: なし 266 267 Returns: サウンド数 268 *---------------------------------------------------------------------------*/ GetActiveCount()269 unsigned long GetActiveCount() const 270 { 271 return m_PriorityList.GetSize(); 272 } 273 274 /*---------------------------------------------------------------------------* 275 Name: GetFreeCount 276 277 Description: マネージャーからAlloc可能な残りインスタンス数を取得する 278 279 Arguments: 無し 280 281 Returns: インスタンス数 282 *---------------------------------------------------------------------------*/ GetFreeCount()283 int GetFreeCount() const { return m_FreeList.GetSize(); } 284 285 private: InsertPriorityList(Sound * sound,int priority)286 void InsertPriorityList( Sound* sound, int priority ) 287 { 288 // プライオリティリストへ追加 289 Iterator itr = m_PriorityList.GetBeginIter(); 290 while ( itr != m_PriorityList.GetEndIter() ) 291 { 292 if ( priority < itr->CalcCurrentPlayerPriority() ) break; 293 (void)++itr; 294 } 295 m_PriorityList.Insert( itr, sound ); 296 } RemovePriorityList(Sound * sound)297 void RemovePriorityList( Sound* sound ) { m_PriorityList.Erase( sound ); } 298 299 PriorityList m_PriorityList; 300 PriorityList m_FreeList; 301 // nn::os::CriticalSection m_CriticalSection; 302 }; 303 304 } // namespace nw::snd::internal 305 } // namespace nw::snd 306 } // namespace nw 307 308 309 #endif /* NW_SND_SOUND_INSTANCE_MANAGER_H_ */ 310 311