From c36655d5c7afdf743c86f1d70f44b42c5844d988 Mon Sep 17 00:00:00 2001 From: Misa Date: Sun, 26 Mar 2023 21:14:02 -0700 Subject: [PATCH] Don't use `FAudioVoice_GetVoiceDetails` We were using this function to check if the format of the existing voice is different from the format of the voice we intended to play. However, whereas the format we use is the FAudioWaveFormatEx struct, the only details we get from FAudioVoice_GetVoiceDetails is the FAudioVoiceDetails struct, which has much less details and is missing important things like whether the format is 8-bit or 16-bit or something else. And of course, if we don't check that the number of bits matches, then it still leads to playback issues as described in #953. There are no other functions in FAudio that operate on FAudioWaveFormatEx structs. So instead, we'll just have to do it ourselves, and store the format of the existing voice alongside the format of the intended voice. And then use SDL_memcmp to make sure the formats are the same before playing, and if not, then destroy and re-create the voice. Fixes #953. --- desktop_version/src/Music.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/desktop_version/src/Music.cpp b/desktop_version/src/Music.cpp index 8f2b6e47..ee0d2233 100644 --- a/desktop_version/src/Music.cpp +++ b/desktop_version/src/Music.cpp @@ -189,13 +189,11 @@ end: FAudioSourceVoice_GetState(voices[i], &voicestate, 0); if (voicestate.BuffersQueued == 0) { - FAudioVoiceDetails details; - FAudioVoice_GetVoiceDetails(voices[i], &details); - if (details.InputSampleRate != format.nSamplesPerSec || - details.InputChannels != format.nChannels) + if (SDL_memcmp(&voice_formats[i], &format, sizeof(format)) != 0) { VVV_freefunc(FAudioVoice_DestroyVoice, voices[i]); FAudio_CreateSourceVoice(faudioctx, &voices[i], &format, 0, 2.0f, NULL, NULL, NULL); + voice_formats[i] = format; } FAudioBuffer faudio_buffer = { FAUDIO_END_OF_STREAM, /* Flags */ @@ -250,6 +248,7 @@ end: format.nBlockAlign = format.nChannels * format.wBitsPerSample; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; format.cbSize = 0; + voice_formats[i] = format; if (FAudio_CreateSourceVoice(faudioctx, &voices[i], &format, 0, 2.0f, NULL, NULL, NULL)) { vlog_error("Unable to create source voice no. %i", i); @@ -309,9 +308,11 @@ end: bool valid; static FAudioSourceVoice** voices; + static FAudioWaveFormatEx voice_formats[VVV_MAX_CHANNELS]; static float volume; }; FAudioSourceVoice** SoundTrack::voices = NULL; +FAudioWaveFormatEx SoundTrack::voice_formats[VVV_MAX_CHANNELS]; float SoundTrack::volume = 0.0f; class MusicTrack @@ -382,12 +383,10 @@ end: if (!IsHalted()) { - FAudioVoiceDetails details; - FAudioVoice_GetVoiceDetails(musicVoice, &details); - if (details.InputSampleRate != format.nSamplesPerSec || - details.InputChannels != format.nChannels) + if (SDL_memcmp(&musicVoiceFormat, &format, sizeof(format)) != 0) { Halt(); + musicVoiceFormat = format; } } @@ -493,6 +492,7 @@ end: static bool paused; static FAudioSourceVoice* musicVoice; + static FAudioWaveFormatEx musicVoiceFormat; static void refillReserve(FAudioVoiceCallback* callback, void* ctx) { @@ -671,6 +671,7 @@ end: }; bool MusicTrack::paused = false; FAudioSourceVoice* MusicTrack::musicVoice = NULL; +FAudioWaveFormatEx MusicTrack::musicVoiceFormat; musicclass::musicclass(void) {