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