@@ -63,7 +63,58 @@ namespace Audio {
6363 sfxHandle_t newSfx;
6464 sfxHandle_t oldSfx;
6565 };
66- static entityLoop_t entityLoops[MAX_GENTITIES];
66+
67+ struct EntityMultiLoop {
68+ entityLoop_t loops[MAX_ENTITY_SOUNDS];
69+
70+ entityLoop_t& FindSlot ( const sfxHandle_t sfx ) {
71+ uint32_t bestSlot = 0 ;
72+ float minGain = FLT_MAX;
73+
74+ for ( entityLoop_t& loop : loops ) {
75+ if ( sfx == loop.oldSfx ) {
76+ return loop;
77+ }
78+
79+ if ( !loop.sound ) {
80+ return loop;
81+ }
82+
83+ if ( loop.sound ->currentGain < minGain ) {
84+ bestSlot = &loop - loops;
85+ minGain = loop.sound ->currentGain ;
86+ }
87+ }
88+
89+ return loops[bestSlot];
90+ }
91+
92+ void StopAll () {
93+ for ( entityLoop_t& loop : loops ) {
94+ if ( loop.sound ) {
95+ loop.sound ->Stop ();
96+ }
97+
98+ loop = { false , false , nullptr , -1 , -1 };
99+ }
100+ }
101+
102+ void ResetAll () {
103+ for ( entityLoop_t& loop : loops ) {
104+ loop = { false , false , nullptr , -1 , -1 };
105+ }
106+ }
107+
108+ void ClearLoopingSounds () {
109+ for ( entityLoop_t& loop : loops ) {
110+ if ( loop.sound ) {
111+ loop.addedThisFrame = false ;
112+ }
113+ }
114+ }
115+ };
116+
117+ static EntityMultiLoop entityLoops[MAX_GENTITIES];
67118
68119 static std::shared_ptr<StreamingSound> streams[N_STREAMS];
69120
@@ -148,8 +199,8 @@ namespace Audio {
148199
149200 UpdateListenerGain ();
150201
151- for (auto & loop : entityLoops) {
152- loop = { false , false , nullptr , - 1 , - 1 } ;
202+ for ( EntityMultiLoop& loop : entityLoops ) {
203+ loop. ResetAll () ;
153204 }
154205
155206 return true ;
@@ -161,11 +212,8 @@ namespace Audio {
161212 }
162213
163214 // Shuts down the wrapper
164- for (auto &loop : entityLoops) {
165- if (loop.sound ) {
166- loop.sound ->Stop ();
167- }
168- loop = {false , false , nullptr , -1 , -1 };
215+ for ( EntityMultiLoop& loop : entityLoops ) {
216+ loop.StopAll ();
169217 }
170218
171219 StopMusic ();
@@ -194,26 +242,29 @@ namespace Audio {
194242 return ;
195243 }
196244
197- for (int i = 0 ; i < MAX_GENTITIES; i++) {
198- entityLoop_t& loop = entityLoops[i];
199- if (loop.sound and not loop.addedThisFrame ) {
200- if ( loop.persistent ) {
201- loop.sound ->soundGain = 0 ;
202- } else {
203- // The loop wasn't added this frame, that means it has to be removed.
245+ for ( uint32_t i = 0 ; i < MAX_GENTITIES; i++ ) {
246+ EntityMultiLoop& multiLoop = entityLoops[i];
247+
248+ for ( entityLoop_t& loop : multiLoop.loops ) {
249+ if ( loop.sound and not loop.addedThisFrame ) {
250+ if ( loop.persistent ) {
251+ loop.sound ->soundGain = 0 ;
252+ } else {
253+ // The loop wasn't added this frame, that means it has to be removed.
254+ loop.sound ->FadeOutAndDie ();
255+ loop = { false , false , nullptr , -1 , -1 };
256+ }
257+ } else if ( loop.oldSfx != loop.newSfx ) {
258+ // The last sfx added in the frame is not the current one being played
259+ // To mimic the previous sound system's behavior we sart playing the new one.
204260 loop.sound ->FadeOutAndDie ();
205- loop = { false , false , nullptr , -1 , -1 };
206- }
207- } else if (loop.oldSfx != loop.newSfx ) {
208- // The last sfx added in the frame is not the current one being played
209- // To mimic the previous sound system's behavior we sart playing the new one.
210- loop.sound ->FadeOutAndDie ();
211261
212- int newSfx = loop.newSfx ;
213- bool persistent = loop.persistent ;
214- loop = {false , false , nullptr , -1 , -1 };
262+ int newSfx = loop.newSfx ;
263+ bool persistent = loop.persistent ;
264+ loop = { false , false , nullptr , -1 , -1 };
215265
216- AddEntityLoopingSound (i, newSfx, persistent);
266+ AddEntityLoopingSound ( i, newSfx, persistent );
267+ }
217268 }
218269 }
219270
@@ -224,15 +275,17 @@ namespace Audio {
224275 UpdateEmitters ();
225276 UpdateSounds ();
226277
227- for (auto &loop : entityLoops) {
228- loop.addedThisFrame = false ;
229- // if we are the unique owner of a loop pointer, then it means it was stopped, free it.
230- if (loop.sound .use_count () == 1 ) {
231- loop = {false , false , nullptr , -1 , -1 };
278+ for ( EntityMultiLoop& multiLoop : entityLoops ) {
279+ for ( entityLoop_t& loop : multiLoop.loops ) {
280+ loop.addedThisFrame = false ;
281+ // if we are the unique owner of a loop pointer, then it means it was stopped, free it.
282+ if ( loop.sound .use_count () == 1 ) {
283+ loop = { false , false , nullptr , -1 , -1 };
284+ }
232285 }
233286 }
234287
235- for (auto &stream : streams) {
288+ for ( std::shared_ptr<StreamingSound> &stream : streams ) {
236289 if (stream and stream.use_count () == 1 ) {
237290 stream = nullptr ;
238291 }
@@ -298,14 +351,15 @@ namespace Audio {
298351 return ;
299352 }
300353
301- entityLoop_t& loop = entityLoops[entityNum];
354+ entityLoop_t& loop = entityLoops[entityNum]. FindSlot ( sfx ) ;
302355
303356 // If we have no sound we can play the loop directly
304357 if (not loop.sound ) {
305358 loop.sound = std::make_shared<LoopingSound>(Sample::FromHandle (sfx));
306359 loop.oldSfx = sfx;
307360 AddSound (GetEmitterForEntity (entityNum), loop.sound , 1 );
308361 }
362+
309363 loop.addedThisFrame = true ;
310364 loop.persistent = persistent;
311365
@@ -328,9 +382,7 @@ namespace Audio {
328382 return ;
329383 }
330384
331- if (entityLoops[entityNum].sound ) {
332- entityLoops[entityNum].addedThisFrame = false ;
333- }
385+ entityLoops[entityNum].ClearLoopingSounds ();
334386 }
335387
336388 void StartMusic (Str::StringRef leadingSound, Str::StringRef loopSound) {
0 commit comments