Skip to content

Commit

Permalink
Don't destroy voice when it is output to other voices
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Gofman authored and flibitijibibo committed Feb 27, 2024
1 parent bebb082 commit c00b01c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
5 changes: 5 additions & 0 deletions include/FAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,11 @@ FAUDIOAPI void FAudioVoice_GetOutputMatrix(
/* Removes this voice from the audio graph and frees memory. */
FAUDIOAPI void FAudioVoice_DestroyVoice(FAudioVoice *voice);

/*
* Returns S_OK on success and E_FAIL if voice could not be destroyed (e. g., because it is in use).
*/
FAUDIOAPI uint32_t FAudioVoice_DestroyVoiceSafeEXT(FAudioVoice *voice);

/* FAudioSourceVoice Interface */

/* Starts processing for a source voice.
Expand Down
68 changes: 67 additions & 1 deletion src/FAudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2265,11 +2265,71 @@ void FAudioVoice_GetOutputMatrix(
LOG_API_EXIT(voice->audio)
}

void FAudioVoice_DestroyVoice(FAudioVoice *voice)
static uint32_t check_for_sends_to_voice(FAudioVoice *voice)
{
FAudio *audio = voice->audio;
uint32_t ret = 0;
FAudioSourceVoice *source;
FAudioSubmixVoice *submix;
LinkedList *list;
uint32_t i;

FAudio_PlatformLockMutex(audio->sourceLock);
list = audio->sources;
while (list != NULL)
{
source = (FAudioSourceVoice*) list->entry;
for (i = 0; i < source->sends.SendCount; i += 1)
if (source->sends.pSends[i].pOutputVoice == voice)
{
ret = 0x80004005; /* E_FAIL */
break;
}
if (ret)
break;
list = list->next;
}
FAudio_PlatformUnlockMutex(audio->sourceLock);

if (ret)
return ret;

FAudio_PlatformLockMutex(audio->submixLock);
list = audio->submixes;
while (list != NULL)
{
submix = (FAudioSubmixVoice*) list->entry;
for (i = 0; i < submix->sends.SendCount; i += 1)
if (submix->sends.pSends[i].pOutputVoice == voice)
{
ret = 0x80004005; /* E_FAIL */
break;
}
if (ret)
break;
list = list->next;
}
FAudio_PlatformUnlockMutex(audio->submixLock);

return ret;
}

uint32_t FAudioVoice_DestroyVoiceSafeEXT(FAudioVoice *voice)
{
uint32_t i, ret;
LOG_API_ENTER(voice->audio)

if ((ret = check_for_sends_to_voice(voice)))
{
LOG_ERROR(
voice->audio,
"Voice %p is an output for other voice(s)",
voice
)
LOG_API_EXIT(voice->audio)
return ret;
}

/* TODO: Check for dependencies and remove from audio graph first! */
FAudio_OPERATIONSET_ClearAllForVoice(voice);

Expand Down Expand Up @@ -2443,6 +2503,12 @@ void FAudioVoice_DestroyVoice(FAudioVoice *voice)
LOG_API_EXIT(voice->audio)
FAudio_Release(voice->audio);
voice->audio->pFree(voice);
return 0;
}

void FAudioVoice_DestroyVoice(FAudioVoice *voice)
{
FAudioVoice_DestroyVoiceSafeEXT(voice);
}

/* FAudioSourceVoice Interface */
Expand Down

0 comments on commit c00b01c

Please sign in to comment.