NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
snd_SoundInstanceManager.h
1#ifndef NW4R_SND_SOUND_INSTANCE_MANAGER_H
2#define NW4R_SND_SOUND_INSTANCE_MANAGER_H
3
4/*******************************************************************************
5 * headers
6 */
7
8#include <new>
9
10#include <types.h>
11
12#include "nw4r/snd/snd_InstancePool.h"
13
14#include "nw4r/ut/ut_Lock.h"
15#include "nw4r/ut/ut_algorithm.h"
16
17#include <revolution/OS/OSMutex.h>
18
19#include "nw4r/NW4RAssert.hpp"
20
21/*******************************************************************************
22 * classes and functions
23 */
24
25namespace nw4r { namespace snd { namespace detail
26{
27 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f03c, 0x30a63...
28 template <class Sound>
29 class SoundInstanceManager
30 {
31 // methods
32 public:
33 // cdtors
34 SoundInstanceManager() { OSInitMutex(&mMutex); }
35
36 // methods
37 ulong Create(void *buffer, ulong size)
38 {
39 NW4RAssertPointerNonnull_Line(67, buffer);
40
42
43 return mPool.Create(buffer, size);
44 }
45
46 void Destroy(void *buffer, ulong size)
47 {
48 NW4RAssertPointerNonnull_Line(86, buffer);
49
51
52 mPool.Destroy(buffer, size);
53 }
54
55 Sound *Alloc(int priority, int ambientPriority)
56 {
57 int allocPriority =
58 ut::Clamp(priority + ambientPriority, Sound::PRIORITY_MIN,
59 Sound::PRIORITY_MAX);
60
62 Sound *sound = nullptr;
63
64 while (!sound)
65 {
66 if (void *ptr = mPool.Alloc())
67 {
68 sound = new (ptr) Sound(this, priority, ambientPriority);
69 continue;
70 }
71
72 Sound *sound = GetLowestPrioritySound();
73 if (!sound)
74 return nullptr;
75
76 if (allocPriority < sound->CalcCurrentPlayerPriority())
77 return nullptr;
78
79 OSUnlockMutex(&mMutex);
80
81 NW4RCheckMessage_Line(133,
82 !Debug_GetWarningFlag(
83 Debug_GetDebugWarningFlagFromSoundType(
84 sound->GetSoundType())),
85 "Sound (id:%d) is stopped for not enough %s sound "
86 "instance.",
87 sound->GetId(),
88 Debug_GetSoundTypeString(sound->GetSoundType()));
89
90 sound->Stop(0);
91
92 OSLockMutex(&mMutex);
93 }
94
95 InsertPriorityList(sound, allocPriority);
96 return sound;
97 }
98
99 void Free(Sound *sound)
100 {
101 NW4RAssertPointerNonnull_Line(158, sound);
102
104
105 if (mPriorityList.IsEmpty())
106 return;
107
108 RemovePriorityList(sound);
109 sound->~Sound();
110 mPool.Free(sound);
111 }
112
113 ulong GetActiveCount() const { return mPriorityList.GetSize(); }
114
115 Sound *GetLowestPrioritySound()
116 {
117 if (mPriorityList.IsEmpty())
118 return nullptr;
119
120 return &mPriorityList.GetFront();
121 }
122
123 void InsertPriorityList(Sound *sound, int priority)
124 {
125 decltype(mPriorityList.GetBeginIter()) itr =
126 mPriorityList.GetBeginIter();
127
128 for (; itr != mPriorityList.GetEndIter(); ++itr)
129 {
130 if (priority < itr->CalcCurrentPlayerPriority())
131 break;
132 }
133
134 mPriorityList.Insert(itr, sound);
135 }
136
137 void SortPriorityList()
138 {
139 int const TMP_NUM = Sound::PRIORITY_MAX + 1;
140
141 if (mPriorityList.GetSize() < 2)
142 return;
143
145
146 typename Sound::PriorityLinkList tmpList[TMP_NUM];
147
148 while (!mPriorityList.IsEmpty())
149 {
150 Sound &front = mPriorityList.GetFront();
151 mPriorityList.PopFront();
152
153 tmpList[front.CalcCurrentPlayerPriority()].PushBack(&front);
154 }
155
156 for (int i = 0; i < TMP_NUM; i++)
157 {
158 while (!tmpList[i].IsEmpty())
159 {
160 Sound &front = tmpList[i].GetFront();
161 tmpList[i].PopFront();
162
163 mPriorityList.PushBack(&front);
164 }
165 }
166 }
167
168 void RemovePriorityList(Sound *sound) { mPriorityList.Erase(sound); }
169
170 void UpdatePriority(Sound *sound, int priority)
171 {
173
174 RemovePriorityList(sound);
175 InsertPriorityList(sound, priority);
176 }
177
178 // members
179 private:
180 MemoryPool<Sound> mPool; // size 0x04, offset 0x00
181 typename Sound::PriorityLinkList mPriorityList; // size 0x0c, offset 0x04
182 OSMutex mMutex; // size 0x18, offset 0x10
183 }; // size 0x28
184}}} // namespace nw4r::snd::detail
185
186#endif // NW4R_SND_SOUND_INSTANCE_MANAGER_H