From 020af80cd0c5c604bfa278034146d7a50437b7ea Mon Sep 17 00:00:00 2001 From: Pavel Solodovnikov Date: Wed, 24 Jan 2024 22:01:19 +0300 Subject: [PATCH 1/2] openal_track.cpp: convert `active_streams` to `std::list` Also, remove `next` pointer from `AUDIO_STREAM` structure. Signed-off-by: Pavel Solodovnikov --- lib/sound/openal_track.cpp | 48 +++++++++----------------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/lib/sound/openal_track.cpp b/lib/sound/openal_track.cpp index 55f9b5f6910..5f34056bc22 100644 --- a/lib/sound/openal_track.cpp +++ b/lib/sound/openal_track.cpp @@ -25,6 +25,7 @@ #include "lib/framework/frame.h" #include "lib/framework/math_ext.h" #include "lib/framework/frameresource.h" +#include "lib/framework/object_list_iteration.h" #include "lib/exceptionhandler/dumpinfo.h" #include @@ -38,6 +39,7 @@ #include #include #include +#include #include "tracklib.h" #include "audio.h" @@ -66,9 +68,6 @@ struct AUDIO_STREAM // Callbacks std::function onFinished; const void *user_data = nullptr; - - // Linked list pointer - AUDIO_STREAM *next = nullptr; }; struct SAMPLE_LIST @@ -80,7 +79,7 @@ struct SAMPLE_LIST static SAMPLE_LIST *active_samples = nullptr; /* actives openAL-Sources */ -static AUDIO_STREAM *active_streams = nullptr; +static std::list active_streams; static ALfloat sfx_volume = 1.0; static ALfloat sfx3d_volume = 1.0; @@ -371,7 +370,6 @@ static void sound_UpdateStreams(void); void sound_ShutdownLibrary(void) { - AUDIO_STREAM *stream; SAMPLE_LIST *aSample = active_samples, * tmpSample = nullptr; if (!openal_initialized) @@ -381,7 +379,7 @@ void sound_ShutdownLibrary(void) debug(LOG_SOUND, "starting shutdown"); // Stop all streams, sound_UpdateStreams() will deallocate all stopped streams - for (stream = active_streams; stream != nullptr; stream = stream->next) + for (AUDIO_STREAM* stream : active_streams) { sound_StopStream(stream); } @@ -1064,8 +1062,7 @@ AUDIO_STREAM *sound_PlayStream(const char* fileName, stream->user_data = user_data; // Prepend this stream to the linked list - stream->next = active_streams; - active_streams = stream; + active_streams.emplace_front(stream); return stream; @@ -1342,43 +1339,20 @@ static void sound_DestroyStream(AUDIO_STREAM *stream) */ static void sound_UpdateStreams() { - AUDIO_STREAM *stream = active_streams, *previous = nullptr, *next = nullptr; - - while (stream != nullptr) + mutating_list_iterate(active_streams, [](typename std::list::iterator streamIt) { - next = stream->next; - // Attempt to update the current stream, if we find that impossible, // destroy it instead. - if (!sound_UpdateStream(stream)) + if (!sound_UpdateStream(*streamIt)) { + AUDIO_STREAM* stream = *streamIt; // First remove our current stream from the linked list - if (previous) - { - // Make the previous item skip over the current to the next item - previous->next = next; - } - else - { - // Apparently this is the first item in the list, so make the - // next item the list-head. - active_streams = next; - } - + active_streams.erase(streamIt); // Now actually destroy the current stream sound_DestroyStream(stream); - - // Make sure the current stream pointer is intact again - stream = next; - - // Skip regular style iterator incrementing - continue; } - - // Increment our iterator pair - previous = stream; - stream = stream->next; - } + return IterationResult::CONTINUE_ITERATION; + }); } //* From fdb5baa656e9cc96a5fc34377e3700e8ce6d6cdf Mon Sep 17 00:00:00 2001 From: Pavel Solodovnikov Date: Thu, 25 Jan 2024 00:22:58 +0300 Subject: [PATCH 2/2] openal_track.cpp: remove `SAMPLE_LIST` and convert it to `std::list` Signed-off-by: Pavel Solodovnikov --- lib/sound/openal_track.cpp | 175 ++++++++++++------------------------- 1 file changed, 56 insertions(+), 119 deletions(-) diff --git a/lib/sound/openal_track.cpp b/lib/sound/openal_track.cpp index 5f34056bc22..a37407f8a5e 100644 --- a/lib/sound/openal_track.cpp +++ b/lib/sound/openal_track.cpp @@ -70,13 +70,7 @@ struct AUDIO_STREAM const void *user_data = nullptr; }; -struct SAMPLE_LIST -{ - AUDIO_SAMPLE *curr; - SAMPLE_LIST *next; -}; - -static SAMPLE_LIST *active_samples = nullptr; +static std::list active_samples; /* actives openAL-Sources */ static std::list active_streams; @@ -92,32 +86,6 @@ static LPALCGETSTRINGISOFT alcGetStringiSOFT = nullptr; static LPALCRESETDEVICESOFT alcResetDeviceSOFT = nullptr; #endif - -/** Removes the given sample from the "active_samples" linked list - * \param previous either NULL (if \c to_remove is the first item in the - * list) or the item occurring just before \c to_remove in - * the list - * \param to_remove the item to actually remove from the list - */ -static void sound_RemoveSample(SAMPLE_LIST *previous, SAMPLE_LIST *to_remove) -{ - if (previous != nullptr && previous != to_remove) - { - // Verify that the given two samples actually follow eachother in the list - ASSERT(previous->next == to_remove, "Sound samples don't follow eachother in the list, we're probably removing the wrong item."); - - // Remove the item to remove from the linked list by skipping - // it in the pointer sequence. - previous->next = to_remove->next; - } - else - { - // Apparently we're removing the first item from the list. So - // make the next one the list's head. - active_samples = to_remove->next; - } -} - ALCint HRTFModeToALCint(HRTFMode mode) { #if defined(ALC_SOFT_HRTF) @@ -370,8 +338,6 @@ static void sound_UpdateStreams(void); void sound_ShutdownLibrary(void) { - SAMPLE_LIST *aSample = active_samples, * tmpSample = nullptr; - if (!openal_initialized) { return; @@ -403,38 +369,27 @@ void sound_ShutdownLibrary(void) } device = nullptr; - while (aSample) - { - tmpSample = aSample->next; - free(aSample); - aSample = tmpSample; - } - active_samples = nullptr; + active_samples.clear(); } -/** Deletes the given sample and updates the \c previous and \c current iterators - * \param previous iterator to the previous sample in the list - * \param sample iterator to the current sample in the list which you want to delete +/** Deletes the given sample and performs additional OpenAL cleanup procedures. + * \param sample iterator to the current sample in the list which you want to delete, invalidated upon return */ -static void sound_DestroyIteratedSample(SAMPLE_LIST **previous, SAMPLE_LIST **sample) +static void sound_DestroyIteratedSample(typename std::list::iterator it) { + AUDIO_SAMPLE* sample = *it; // If an OpenAL source is associated with this sample, release it - if ((*sample)->curr->iSample != (ALuint)AL_INVALID) + if (sample->iSample != (ALuint)AL_INVALID) { - alDeleteSources(1, &(*sample)->curr->iSample); + alDeleteSources(1, &sample->iSample); sound_GetError(); } // Do the cleanup of this sample - sound_FinishedCallback((*sample)->curr); + sound_FinishedCallback(sample); // Remove the sample from the list - sound_RemoveSample(*previous, *sample); - // Free it - free(*sample); - - // Get a pointer to the next node, the previous pointer doesn't change - *sample = (*previous != nullptr) ? (*previous)->next : active_samples; + active_samples.erase(it); } /** Counts the number of samples in active_samples @@ -442,23 +397,12 @@ static void sound_DestroyIteratedSample(SAMPLE_LIST **previous, SAMPLE_LIST **sa */ unsigned int sound_GetActiveSamplesCount() { - unsigned int num = 0; - SAMPLE_LIST *node = active_samples; - - while (node) - { - num++; - node = node->next; - } - return num; + return static_cast(active_samples.size()); } /* gets called in audio.cpp: audio_update(), which gets called in renderLoop() */ void sound_Update() { - SAMPLE_LIST *node = active_samples; - SAMPLE_LIST *previous = nullptr; - ALfloat gain; if (!openal_initialized) { @@ -468,23 +412,26 @@ void sound_Update() // Update all streaming audio sound_UpdateStreams(); - while (node != nullptr) + mutating_list_iterate(active_samples, [](typename std::list::iterator sampleIt) { ALenum state, err; + ALfloat gain; + + AUDIO_SAMPLE* sample = *sampleIt; // query what the gain is for this sample - alGetSourcef(node->curr->iSample, AL_GAIN, &gain); + alGetSourcef(sample->iSample, AL_GAIN, &gain); err = sound_GetError(); // if gain is 0, then we can't hear it, so we kill it. if (gain == 0.0f) { - sound_DestroyIteratedSample(&previous, &node); - continue; + sound_DestroyIteratedSample(sampleIt); + return IterationResult::CONTINUE_ITERATION; } //ASSERT(alIsSource(node->curr->iSample), "Not a valid source!"); - alGetSourcei(node->curr->iSample, AL_SOURCE_STATE, &state); + alGetSourcei(sample->iSample, AL_SOURCE_STATE, &state); // Check whether an error occurred while retrieving the state. // If one did, the state returned is useless. So instead of @@ -493,11 +440,11 @@ void sound_Update() if (err != AL_NO_ERROR) { // Make sure to invoke the "finished" callback - sound_FinishedCallback(node->curr); + sound_FinishedCallback(sample); // Destroy this object and move to the next object - sound_DestroyIteratedSample(&previous, &node); - continue; + sound_DestroyIteratedSample(sampleIt); + return IterationResult::CONTINUE_ITERATION; } switch (state) @@ -510,18 +457,17 @@ void sound_Update() // sound_SetObjectPosition(i->curr->iSample, i->curr->x, i->curr->y, i->curr->z); // Move to the next object - previous = node; - node = node->next; - break; + return IterationResult::CONTINUE_ITERATION; - // NOTE: if it isn't playing | paused, then it is most likely either done - // or a error. In either case, we want to kill the sample in question. + // NOTE: if it isn't playing | paused, then it is most likely either done + // or a error. In either case, we want to kill the sample in question. default: - sound_DestroyIteratedSample(&previous, &node); + sound_DestroyIteratedSample(sampleIt); break; } - } + return IterationResult::CONTINUE_ITERATION; + }); // Reset the current error state alcGetError(device); @@ -539,7 +485,7 @@ void sound_Update() // ======================================================================================================================= // ======================================================================================================================= // -bool sound_QueueSamplePlaying(void) +bool sound_QueueSamplePlaying() { ALenum state; @@ -569,24 +515,23 @@ bool sound_QueueSamplePlaying(void) if (current_queue_sample != (ALuint)AL_INVALID) { - SAMPLE_LIST *node = active_samples; - SAMPLE_LIST *previous = nullptr; - - // We need to remove it from the queue of actively played samples - while (node != nullptr) + bool sampleFound = false; + mutating_list_iterate(active_samples, [&sampleFound](typename std::list::iterator sampleIt) { - if (node->curr->iSample == current_queue_sample) + if ((*sampleIt)->iSample == current_queue_sample) { - sound_DestroyIteratedSample(&previous, &node); + sound_DestroyIteratedSample(sampleIt); current_queue_sample = AL_INVALID; - return false; - } - previous = node; - if (node) - { - node = node->next; + sampleFound = true; + return IterationResult::BREAK_ITERATION; } + return IterationResult::CONTINUE_ITERATION; + }); + if (sampleFound) + { + return false; } + debug(LOG_ERROR, "Sample %u not deleted because it wasn't in the active queue!", current_queue_sample); current_queue_sample = AL_INVALID; } @@ -713,41 +658,33 @@ void sound_FreeTrack(TRACK *psTrack) static void sound_AddActiveSample(AUDIO_SAMPLE *psSample) { - SAMPLE_LIST *tmp = (SAMPLE_LIST *) malloc(sizeof(SAMPLE_LIST)); - // Prepend the given sample to our list of active samples - tmp->curr = psSample; - tmp->next = active_samples; - active_samples = tmp; + active_samples.emplace_front(psSample); } /** Routine gets rid of the psObj's sound sample and reference in active_samples. */ void sound_RemoveActiveSample(AUDIO_SAMPLE *psSample) { - SAMPLE_LIST *node = active_samples; - SAMPLE_LIST *previous = nullptr; - - while (node != nullptr) + mutating_list_iterate(active_samples, [psSample](typename std::list::iterator sampleIt) { - if (node->curr->psObj == psSample->psObj) + AUDIO_SAMPLE* currSample = *sampleIt; + if (currSample->psObj != psSample->psObj) { - debug(LOG_MEMORY, "Removing object 0x%p from active_samples list 0x%p\n", static_cast(psSample->psObj), static_cast(node)); + // Move to the next sample object + return IterationResult::CONTINUE_ITERATION; + } + debug(LOG_MEMORY, "Removing object 0x%p from active_samples list\n", static_cast(psSample->psObj)); - // Buginator: should we wait for it to finish, or just stop it? - sound_StopSample(node->curr); + // Buginator: should we wait for it to finish, or just stop it? + sound_StopSample(currSample); - sound_FinishedCallback(node->curr); //tell the callback it is finished. + sound_FinishedCallback(currSample); //tell the callback it is finished. - sound_DestroyIteratedSample(&previous, &node); - } - else - { - // Move to the next sample object - previous = node; - node = node->next; - } - } + sound_DestroyIteratedSample(sampleIt); + + return IterationResult::CONTINUE_ITERATION; + }); } static bool sound_SetupChannel(AUDIO_SAMPLE *psSample)