2021年3月16日星期二

Xaudio2 crashes if I exit application while sound is playing

I have been tying to setup xaudio2 and while I thought I succeeded, I quit the application while the sound is still playing and the program crashed. originally I made it so that when receiving a WM_CLOSE message I would make sure that the source voices had stopped. this drastically reduced the number of crashes, but still around 1/5 times I exit the application the program crashes. this is what it says "Exception thrown at 0x00007FF9974E38C7 (XAudio2_9.dll) in Game.exe: 0xC0000005: Access violation reading location 0x0000025274A680C4.". I am assuming that the xaudio2 thread is still trying to read the buffer even though I have disposed of it. I have set it up in a way so that there is a central SoundSystem class which has 2 vectors of Voices(another class), idleVoices and activeVoices. when I play a sound I grab a voice from the idle channels and play a sound, then when it is done I put it back in the idle channels and repeat.

here is the .h file

    #pragma once        #include <vector>      #include <memory>      #include <xaudio2.h>      #include <algorithm>      #include "Sound.h"          class SoundSystem      {            friend class Voice;          friend class Window;      public:            static SoundSystem& getInstance();                    SoundSystem(SoundSystem&) = delete;          SoundSystem& operator=(SoundSystem&) = delete;              void playSound(Sound& sound, float frequency = 1.0f, float volume = 1.0f);                ~SoundSystem();        private:            class Voice          {              friend class SoundSystem;              friend class Window;          public:                Voice()              {                }                Voice(SoundSystem* soundSystem);                      void playSound(Sound& sound, float frequency = 1.0f, float volume = 1.0f);              void stop();                  ~Voice();          private:                  class VoiceCallback : public IXAudio2VoiceCallback              {              public:                  void STDMETHODCALLTYPE OnStreamEnd() override                  {}                  void STDMETHODCALLTYPE OnVoiceProcessingPassEnd() override                  {}                  void STDMETHODCALLTYPE OnVoiceProcessingPassStart(UINT32 SamplesRequired) override                  {}                  void STDMETHODCALLTYPE OnBufferEnd(void* pBufferContext) override;                  void STDMETHODCALLTYPE OnBufferStart(void* pBufferContext) override                  {}                  void STDMETHODCALLTYPE OnLoopEnd(void* pBufferContext) override                  {}                  void STDMETHODCALLTYPE OnVoiceError(void* pBufferContext, HRESULT Error) override                  {}              };                  IXAudio2SourceVoice* sourceVoice = nullptr;              XAUDIO2_BUFFER buffer = { 0 };            };              void deactivateVoice(Voice* voice);            SoundSystem();            IXAudio2* audioEngine = nullptr;          IXAudio2MasteringVoice* masteringVoice = nullptr;              std::vector<std::unique_ptr<Voice>> idleVoices;          std::vector<std::unique_ptr<Voice>> activeVoices;          const unsigned int maxVoices = 256;        };                  

and the .cpp file

#include "SoundSystem.h"  #include "..\Exception.h"        SoundSystem::Voice::Voice(SoundSystem* soundSystem)  {          HRESULT errorCode;        static VoiceCallback voiceCallback;        buffer.pContext = this;            if (FAILED(errorCode = soundSystem->audioEngine->CreateSourceVoice(&sourceVoice, &WaveFile::validFormat, 0, 2, &voiceCallback)))      {          throw Exception::AudioException("CreateSourceVoice failed", __FILE__, __LINE__, errorCode);      }          }      void SoundSystem::Voice::playSound(Sound& sound, float frequency, float volume)  {        HRESULT errorCode;        buffer.AudioBytes = sound.audioSize;      buffer.pAudioData = sound.audioBuffer;      if (FAILED(errorCode = sourceVoice->SubmitSourceBuffer(&buffer, nullptr)))      {          throw Exception::AudioException("SubmitSourceBuffer failed", __FILE__, __LINE__, errorCode);      }      if (FAILED(errorCode = sourceVoice->SetFrequencyRatio(frequency)))      {          throw Exception::AudioException("SetFrequencyRatio failed", __FILE__, __LINE__, errorCode);      }      if (FAILED(errorCode = sourceVoice->SetVolume(volume)))      {          throw Exception::AudioException("SetVolume failed", __FILE__, __LINE__, errorCode);      }      if (FAILED(errorCode = sourceVoice->Start()))      {          throw Exception::AudioException("Start failed", __FILE__, __LINE__, errorCode);      }    }    void SoundSystem::Voice::stop()  {      sourceVoice->Stop();      sourceVoice->FlushSourceBuffers();  }    SoundSystem::Voice::~Voice()  {      stop();          sourceVoice->DestroyVoice();      sourceVoice = nullptr;      }            void __stdcall SoundSystem::Voice::VoiceCallback::OnBufferEnd(void* pBufferContext)  {      Voice* voice = reinterpret_cast<Voice*>(pBufferContext);        voice->stop();      SoundSystem::getInstance().deactivateVoice(voice);    }            SoundSystem& SoundSystem::getInstance()  {      static SoundSystem instance;      return instance;  }      void SoundSystem::deactivateVoice(Voice* voice)  {        auto it = std::find_if(activeVoices.begin(), activeVoices.end(), [&](const std::unique_ptr<Voice>& v) -> bool          {              return voice = v.get();          });      idleVoices.push_back(std::move(*it));      activeVoices.erase(it);      }    SoundSystem::SoundSystem()  {        HRESULT errorCode;        if (FAILED(errorCode = CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)))      {          throw Exception::AudioException("CoInitializeEx failed", __FILE__, __LINE__, errorCode);      }          if (FAILED(errorCode = XAudio2Create(&audioEngine, 0)))      {          throw Exception::AudioException("XAudio2Create failed", __FILE__, __LINE__, errorCode);      }        if (FAILED(errorCode = audioEngine->CreateMasteringVoice(&masteringVoice)))      {          throw Exception::AudioException("CreateMasteringVoice failed", __FILE__, __LINE__, errorCode);      }                    for (int i = 0; i < maxVoices; i++)      {          idleVoices.push_back(std::make_unique<Voice>(this));      }    }    void SoundSystem::playSound(Sound& sound, float frequency, float volume)  {      if (idleVoices.size() > 0)      {          activeVoices.push_back(std::move(idleVoices.back()));          idleVoices.pop_back();          activeVoices.back()->playSound(sound, frequency, volume);      }  }    SoundSystem::~SoundSystem()  {          for (auto& a : idleVoices)      {          a.reset();      }      for (auto& a : activeVoices)      {          a.reset();      }          audioEngine->Release();      audioEngine = nullptr;              masteringVoice = nullptr;        CoUninitialize();    }    

and here is the WM_CLOSE message handling

case WM_CLOSE:            for (auto& a : SoundSystem::getInstance().activeVoices)          {                            a.get()->stop();                    }              ApplicationEvent applicationEvent(ApplicationEventType::WindowClose);          EventSystem::getInstance().notify(&applicationEvent);            PostQuitMessage(0);          return 0;          break;  

I am assuming the close message handling has something to do with it, as stopping the source voices helped, but it still crashes. any help would be appreciated.

https://stackoverflow.com/questions/66667269/xaudio2-crashes-if-i-exit-application-while-sound-is-playing March 17, 2021 at 01:05PM

没有评论:

发表评论