jarikomppa / soloud

Free, easy, portable audio engine for games
http://soloud-audio.com
Other
1.69k stars 270 forks source link

setProtectVoice does nothing #298

Open klein-j opened 3 years ago

klein-j commented 3 years ago

Version "SoLoud 20200207" (most recent as of today)

I have a scene with plenty of 3D voices and 2D background music. I want the music to be always audible, however when the 3D sounds become too loud, the music is paused.

I used setProtectVoice and verified the state change via getProtectVoice, but there is no effect.

I searched through the source code, and apparently this feature is just not implemented. The only time the flag is used outside the setter/getter is in "findFreeVoice_internal", which looks for a free spot in the 1024 voice slots.

The problem is however than there is a very limited number of sounds that can play concurrently (e.g. 8) and my music is often kicked out of this selection. This seems to happen in calcActiveVoices_internal, but this function does not seem to care at all about the PROTECTED flag.

klein-j commented 3 years ago

Suggested fix

In Soloud::calcActiveVoices_internal() replace the old sorting code which is

int left = 0, stack[24], pos = 0, right;
        int len = candidates - mustlive;
        unsigned int *data = mActiveVoice + mustlive;
        int k = mActiveVoiceCount;
        for (;;) 
        {                                 
            for (; left + 1 < len; len++) 
            {                
                if (pos == 24) len = stack[pos = 0]; 
                int pivot = data[left];
                float pivotvol = mVoice[pivot]->mOverallVolume;
                stack[pos++] = len;      
                for (right = left - 1;;) 
                {
                    do 
                    {
                        right++;
                    } 
                    while (mVoice[data[right]]->mOverallVolume > pivotvol);
                    do
                    {
                        len--;
                    }
                    while (pivotvol > mVoice[data[len]]->mOverallVolume);
                    if (right >= len) break;       
                    int temp = data[right];
                    data[right] = data[len];
                    data[len] = temp;
                }                        
            }
            if (pos == 0) break;         
            if (left >= k) break;
            left = len;                  
            len = stack[--pos];          
        }

By

        auto comp = [this](const unsigned int & a, const unsigned int & b)
        {
            // Test a>b
            if((mVoice[a]->mFlags & AudioSourceInstance::PROTECTED) && !(mVoice[b]->mFlags & AudioSourceInstance::PROTECTED))
                return true;
            if((mVoice[b]->mFlags & AudioSourceInstance::PROTECTED) && !(mVoice[a]->mFlags & AudioSourceInstance::PROTECTED))
                return false;
            return mVoice[a]->mOverallVolume > mVoice[b]->mOverallVolume;
        };

        std::stable_sort(&mActiveVoice[0+mustlive], &mActiveVoice[candidates], comp);

and include .

Explanation: Sounds that are protected should always compare as louder than unprotected ones. I tried for about an hour to implement this in the given sort algorithm, but it was completely impossible to understand what it actually does. Besides, since sorting is a solved problem there is really no reason to implement your own sorting algorithm. The provided fix is much shorter and much much easier to understand or adapt in the future.

In my tests, it seemed to work as expected. Please comment.

Anuken commented 3 years ago

I had this exact problem, and can confirm that your change fixed it.

klein-j commented 3 years ago

Nice to hear. I attached a diff file in case others want to use the code as well. (The index in line 2 belongs to my repository, maybe the patch can't be applied directly to other repos)

Sad to see that the author is not responding to the issues here. SoLoud is a nice library but has so many issues that this sort of polishing through the community really needs to happen and also be applied to the official versions.

soloud.cpp.txt

klein-j commented 3 months ago

I uploaded my fix (along with some others) here:

https://github.com/klein-j/soloud_fixed/tree/soloud_fixed

alnitak commented 3 months ago

@klein-j thank you!