mirror of
https://github.com/zeldaret/ss
synced 2026-06-01 01:39:17 -04:00
187 lines
4.0 KiB
C++
187 lines
4.0 KiB
C++
#ifndef NW4R_SND_SOUND_INSTANCE_MANAGER_H
|
|
#define NW4R_SND_SOUND_INSTANCE_MANAGER_H
|
|
|
|
/*******************************************************************************
|
|
* headers
|
|
*/
|
|
|
|
#include <new>
|
|
|
|
#include "common.h"
|
|
|
|
#include "nw4r/snd/snd_InstancePool.h"
|
|
|
|
#include "nw4r/ut/ut_Lock.h"
|
|
#include "nw4r/ut/ut_algorithm.h"
|
|
|
|
#include <rvl/OS/OSMutex.h>
|
|
|
|
#include "nw4r/NW4RAssert.hpp"
|
|
|
|
/*******************************************************************************
|
|
* classes and functions
|
|
*/
|
|
|
|
namespace nw4r { namespace snd { namespace detail
|
|
{
|
|
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f03c, 0x30a63...
|
|
template <class Sound>
|
|
class SoundInstanceManager
|
|
{
|
|
// methods
|
|
public:
|
|
// cdtors
|
|
SoundInstanceManager() { OSInitMutex(&mMutex); }
|
|
|
|
// methods
|
|
u32 Create(void *buffer, u32 size)
|
|
{
|
|
NW4RAssertPointerNonnull_Line(67, buffer);
|
|
|
|
ut::detail::AutoLock<OSMutex> lock(mMutex);
|
|
|
|
return mPool.Create(buffer, size);
|
|
}
|
|
|
|
void Destroy(void *buffer, u32 size)
|
|
{
|
|
NW4RAssertPointerNonnull_Line(86, buffer);
|
|
|
|
ut::detail::AutoLock<OSMutex> lock(mMutex);
|
|
|
|
mPool.Destroy(buffer, size);
|
|
}
|
|
|
|
Sound *Alloc(int priority, int ambientPriority)
|
|
{
|
|
int allocPriority =
|
|
ut::Clamp(priority + ambientPriority, Sound::PRIORITY_MIN,
|
|
Sound::PRIORITY_MAX);
|
|
|
|
ut::detail::AutoLock<OSMutex> lock(mMutex);
|
|
Sound *sound = nullptr;
|
|
|
|
while (!sound)
|
|
{
|
|
if (void *ptr = mPool.Alloc())
|
|
{
|
|
sound = new (ptr) Sound(this, priority, ambientPriority);
|
|
continue;
|
|
}
|
|
|
|
Sound *sound = GetLowestPrioritySound();
|
|
if (!sound)
|
|
return nullptr;
|
|
|
|
if (allocPriority < sound->CalcCurrentPlayerPriority())
|
|
return nullptr;
|
|
|
|
OSUnlockMutex(&mMutex);
|
|
|
|
NW4RCheckMessage_Line(133,
|
|
!Debug_GetWarningFlag(
|
|
Debug_GetDebugWarningFlagFromSoundType(
|
|
sound->GetSoundType())),
|
|
"Sound (id:%d) is stopped for not enough %s sound "
|
|
"instance.",
|
|
sound->GetId(),
|
|
Debug_GetSoundTypeString(sound->GetSoundType()));
|
|
|
|
sound->Stop(0);
|
|
|
|
OSLockMutex(&mMutex);
|
|
}
|
|
|
|
InsertPriorityList(sound, allocPriority);
|
|
return sound;
|
|
}
|
|
|
|
void Free(Sound *sound)
|
|
{
|
|
NW4RAssertPointerNonnull_Line(158, sound);
|
|
|
|
ut::detail::AutoLock<OSMutex> lock(mMutex);
|
|
|
|
if (mPriorityList.IsEmpty())
|
|
return;
|
|
|
|
RemovePriorityList(sound);
|
|
sound->~Sound();
|
|
mPool.Free(sound);
|
|
}
|
|
|
|
u32 GetActiveCount() const { return mPriorityList.GetSize(); }
|
|
|
|
Sound *GetLowestPrioritySound()
|
|
{
|
|
if (mPriorityList.IsEmpty())
|
|
return nullptr;
|
|
|
|
return &mPriorityList.GetFront();
|
|
}
|
|
|
|
void InsertPriorityList(Sound *sound, int priority)
|
|
{
|
|
decltype(mPriorityList.GetBeginIter()) itr =
|
|
mPriorityList.GetBeginIter();
|
|
|
|
for (; itr != mPriorityList.GetEndIter(); ++itr)
|
|
{
|
|
if (priority < itr->CalcCurrentPlayerPriority())
|
|
break;
|
|
}
|
|
|
|
mPriorityList.Insert(itr, sound);
|
|
}
|
|
|
|
void SortPriorityList()
|
|
{
|
|
int const TMP_NUM = Sound::PRIORITY_MAX + 1;
|
|
|
|
if (mPriorityList.GetSize() < 2)
|
|
return;
|
|
|
|
ut::detail::AutoLock<OSMutex> lock(mMutex);
|
|
|
|
typename Sound::PriorityLinkList tmpList[TMP_NUM];
|
|
|
|
while (!mPriorityList.IsEmpty())
|
|
{
|
|
Sound &front = mPriorityList.GetFront();
|
|
mPriorityList.PopFront();
|
|
|
|
tmpList[front.CalcCurrentPlayerPriority()].PushBack(&front);
|
|
}
|
|
|
|
for (int i = 0; i < TMP_NUM; i++)
|
|
{
|
|
while (!tmpList[i].IsEmpty())
|
|
{
|
|
Sound &front = tmpList[i].GetFront();
|
|
tmpList[i].PopFront();
|
|
|
|
mPriorityList.PushBack(&front);
|
|
}
|
|
}
|
|
}
|
|
|
|
void RemovePriorityList(Sound *sound) { mPriorityList.Erase(sound); }
|
|
|
|
void UpdatePriority(Sound *sound, int priority)
|
|
{
|
|
ut::detail::AutoLock<OSMutex> lock(mMutex);
|
|
|
|
RemovePriorityList(sound);
|
|
InsertPriorityList(sound, priority);
|
|
}
|
|
|
|
// members
|
|
private:
|
|
MemoryPool<Sound> mPool; // size 0x04, offset 0x00
|
|
typename Sound::PriorityLinkList mPriorityList; // size 0x0c, offset 0x04
|
|
OSMutex mMutex; // size 0x18, offset 0x10
|
|
}; // size 0x28
|
|
}}} // namespace nw4r::snd::detail
|
|
|
|
#endif // NW4R_SND_SOUND_INSTANCE_MANAGER_H
|