29    class SoundInstanceManager
 
   34        SoundInstanceManager() { OSInitMutex(&mMutex); }
 
   37        ulong Create(
void *buffer, ulong size)
 
   39            NW4RAssertPointerNonnull_Line(67, buffer);
 
   43            return mPool.Create(buffer, size);
 
   46        void Destroy(
void *buffer, ulong size)
 
   48            NW4RAssertPointerNonnull_Line(86, buffer);
 
   52            mPool.Destroy(buffer, size);
 
   55        Sound *Alloc(
int priority, 
int ambientPriority)
 
   58                ut::Clamp(priority + ambientPriority, Sound::PRIORITY_MIN,
 
   62            Sound *sound = 
nullptr;
 
   66                if (
void *ptr = mPool.Alloc())
 
   68                    sound = 
new (ptr) Sound(
this, priority, ambientPriority);
 
   72                Sound *sound = GetLowestPrioritySound();
 
   76                if (allocPriority < sound->CalcCurrentPlayerPriority())
 
   79                OSUnlockMutex(&mMutex);
 
   81                NW4RCheckMessage_Line(133,
 
   82                    !Debug_GetWarningFlag(
 
   83                        Debug_GetDebugWarningFlagFromSoundType(
 
   84                            sound->GetSoundType())),
 
   85                    "Sound (id:%d) is stopped for not enough %s sound " 
   88                    Debug_GetSoundTypeString(sound->GetSoundType()));
 
   95            InsertPriorityList(sound, allocPriority);
 
   99        void Free(Sound *sound)
 
  101            NW4RAssertPointerNonnull_Line(158, sound);
 
  105            if (mPriorityList.IsEmpty())
 
  108            RemovePriorityList(sound);
 
  113        ulong GetActiveCount()
 const { 
return mPriorityList.GetSize(); }
 
  115        Sound *GetLowestPrioritySound()
 
  117            if (mPriorityList.IsEmpty())
 
  120            return &mPriorityList.GetFront();
 
  123        void InsertPriorityList(Sound *sound, 
int priority)
 
  125            decltype(mPriorityList.GetBeginIter()) itr =
 
  126                mPriorityList.GetBeginIter();
 
  128            for (; itr != mPriorityList.GetEndIter(); ++itr)
 
  130                if (priority < itr->CalcCurrentPlayerPriority())
 
  134            mPriorityList.Insert(itr, sound);
 
  137        void SortPriorityList()
 
  139            int const TMP_NUM = Sound::PRIORITY_MAX + 1;
 
  141            if (mPriorityList.GetSize() < 2)
 
  146            typename Sound::PriorityLinkList tmpList[TMP_NUM];
 
  148            while (!mPriorityList.IsEmpty())
 
  150                Sound &front = mPriorityList.GetFront();
 
  151                mPriorityList.PopFront();
 
  153                tmpList[front.CalcCurrentPlayerPriority()].PushBack(&front);
 
  156            for (
int i = 0; i < TMP_NUM; i++)
 
  158                while (!tmpList[i].IsEmpty())
 
  160                    Sound &front = tmpList[i].GetFront();
 
  161                    tmpList[i].PopFront();
 
  163                    mPriorityList.PushBack(&front);
 
  168        void RemovePriorityList(Sound *sound) { mPriorityList.Erase(sound); }
 
  170        void UpdatePriority(Sound *sound, 
int priority)
 
  174            RemovePriorityList(sound);
 
  175            InsertPriorityList(sound, priority);
 
  181        typename Sound::PriorityLinkList    mPriorityList;