diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2011-03-15 23:09:12 +0000 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2011-03-15 23:09:12 +0000 |
| commit | 41c98f982eb44e89416fcb9c0139b6a922e14b0f (patch) | |
| tree | 579d7e73ec6d73244a469a7317bc9be22725e2b2 /Source/Core/AudioCommon | |
| parent | e77059d30c57a688e6a353abbcdc89603b08e55e (diff) | |
A bit of cleanup to Core Init/Stop, Frame, and Main. Cleanup XAudio2 to attempt to fix the crash on stop(didn't help :p). For some reason CFrame::DoStop is called twice.(might be the issue)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7353 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/AudioCommon')
| -rw-r--r-- | Source/Core/AudioCommon/Src/XAudio2Stream.cpp | 241 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/XAudio2Stream.h | 94 |
2 files changed, 173 insertions, 162 deletions
diff --git a/Source/Core/AudioCommon/Src/XAudio2Stream.cpp b/Source/Core/AudioCommon/Src/XAudio2Stream.cpp index ae93b781a8..f60842d960 100644 --- a/Source/Core/AudioCommon/Src/XAudio2Stream.cpp +++ b/Source/Core/AudioCommon/Src/XAudio2Stream.cpp @@ -18,136 +18,119 @@ #include "AudioCommon.h" #include "XAudio2Stream.h" -struct StreamingVoiceContext : public IXAudio2VoiceCallback -{ - IXAudio2SourceVoice* pSourceVoice; - CMixer *m_mixer; - Common::Event *soundSyncEvent; - short *xaBuffer; +const int NUM_BUFFERS = 3; +const int SAMPLES_PER_BUFFER = 96; - StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event *pSyncEvent) - { +const int NUM_CHANNELS = 2; +const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS; +const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16); - m_mixer = pMixer; - soundSyncEvent = pSyncEvent; - - WAVEFORMATEXTENSIBLE wfx; - - memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE)); - wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate(); - wfx.Format.nChannels = 2; - wfx.Format.wBitsPerSample = 16; - wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8; - wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; - wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); - wfx.Samples.wValidBitsPerSample = 16; - wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; - wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - - // create source voice - HRESULT hr; - if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, XAUDIO2_VOICE_NOSRC, 1.0f, this))) - PanicAlertT("XAudio2 CreateSourceVoice failed: %#X", hr); - - pSourceVoice->FlushSourceBuffers(); - pSourceVoice->Start(); - - xaBuffer = new s16[NUM_BUFFERS * BUFFER_SIZE]; - memset(xaBuffer, 0, NUM_BUFFERS * BUFFER_SIZE_BYTES); - - //start buffers with silence - for(int i=0; i < NUM_BUFFERS; i++) - { - XAUDIO2_BUFFER buf = {0}; - buf.AudioBytes = BUFFER_SIZE_BYTES; - buf.pAudioData = (BYTE *) &xaBuffer[i * BUFFER_SIZE]; - buf.pContext = (void *) buf.pAudioData; - - pSourceVoice->SubmitSourceBuffer(&buf); - } +void StreamingVoiceContext::SubmitBuffer(PBYTE buf_data) +{ + XAUDIO2_BUFFER buf = {}; + buf.AudioBytes = BUFFER_SIZE_BYTES; + buf.pContext = buf_data; + buf.pAudioData = buf_data; - } - - ~StreamingVoiceContext() - { - IXAudio2SourceVoice* temp = pSourceVoice; - pSourceVoice = NULL; - temp->FlushSourceBuffers(); - temp->DestroyVoice(); - safe_delete_array(xaBuffer); - } - - void StreamingVoiceContext::Stop() { - if (pSourceVoice) - pSourceVoice->Stop(); - } + m_source_voice->SubmitSourceBuffer(&buf); +} - void StreamingVoiceContext::Play() { - if (pSourceVoice) - pSourceVoice->Start(); +StreamingVoiceContext::StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event& pSyncEvent) + : m_mixer(pMixer) + , m_sound_sync_event(pSyncEvent) + , xaudio_buffer(new BYTE[NUM_BUFFERS * BUFFER_SIZE_BYTES]()) +{ + WAVEFORMATEXTENSIBLE wfx = {}; + + wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate(); + wfx.Format.nChannels = 2; + wfx.Format.wBitsPerSample = 16; + wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample / 8; + wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; + wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + wfx.Samples.wValidBitsPerSample = 16; + wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + // create source voice + HRESULT hr; + if (FAILED(hr = pXAudio2->CreateSourceVoice(&m_source_voice, &wfx.Format, XAUDIO2_VOICE_NOSRC, 1.0f, this))) + { + PanicAlertT("XAudio2 CreateSourceVoice failed: %#X", hr); + return; } - - STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {} - STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {} - STDMETHOD_(void, OnVoiceProcessingPassEnd) () {} - STDMETHOD_(void, OnBufferStart) (void*) {} - STDMETHOD_(void, OnLoopEnd) (void*) {} - STDMETHOD_(void, OnStreamEnd) () {} - STDMETHOD_(void, OnBufferEnd) (void* context) - { // - // buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer - // - if( !pSourceVoice || !context) return; - - //soundSyncEvent->Wait(); //sync - //soundSyncEvent->Spin(); //or tight sync - - //if (!pSourceVoice) return; - m_mixer->Mix((short *)context, SAMPLES_PER_BUFFER); + m_source_voice->Start(); + // start buffers with silence + for (int i = 0; i != NUM_BUFFERS; ++i) + SubmitBuffer(xaudio_buffer.get() + (i * BUFFER_SIZE_BYTES)); +} - XAUDIO2_BUFFER buf = {0}; - buf.AudioBytes = BUFFER_SIZE_BYTES; - buf.pAudioData = (byte*)context; - buf.pContext = context; +StreamingVoiceContext::~StreamingVoiceContext() +{ + if (m_source_voice) + { + m_source_voice->Stop(); + m_source_voice->DestroyVoice(); + } +} - pSourceVoice->SubmitSourceBuffer(&buf); - } -}; +void StreamingVoiceContext::Stop() +{ + if (m_source_voice) + m_source_voice->Stop(); +} +void StreamingVoiceContext::Play() +{ + if (m_source_voice) + m_source_voice->Start(); +} -StreamingVoiceContext* pVoiceContext = 0; +void StreamingVoiceContext::OnBufferEnd(void* context) +{ + // buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer + + if (!m_source_voice || !context) + return; + + //m_sound_sync_event->Wait(); // sync + //m_sound_sync_event->Spin(); // or tight sync + + m_mixer->Mix(static_cast<short*>(context), SAMPLES_PER_BUFFER); + SubmitBuffer(static_cast<BYTE*>(context)); +} bool XAudio2::Start() { - // XAudio2 init - CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT hr; - if(FAILED(hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_ANY_PROCESSOR))) //callback dosent seem to run on a speecific cpu anyways - { - PanicAlertT("XAudio2 init failed: %#X", hr); - CoUninitialize(); + + // callback dosent seem to run on a speecific cpu anyways + IXAudio2* xaudptr; + if (FAILED(hr = XAudio2Create(&xaudptr, 0, XAUDIO2_DEFAULT_PROCESSOR))) + { + PanicAlertT("XAudio2 init failed: %#X", hr); + Stop(); return false; - } + } + m_xaudio2 = std::unique_ptr<IXAudio2, Releaser>(xaudptr); - // XAudio2 master voice + // XAudio2 master voice // XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion? - if(FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, 2, m_mixer->GetSampleRate()))) - { - PanicAlertT("XAudio2 master voice creation failed: %#X", hr); - safe_release(pXAudio2); - CoUninitialize(); + if (FAILED(hr = m_xaudio2->CreateMasteringVoice(&m_mastering_voice, 2, m_mixer->GetSampleRate()))) + { + PanicAlertT("XAudio2 master voice creation failed: %#X", hr); + Stop(); return false; - } + } // Volume - if (pMasteringVoice) - pMasteringVoice->SetVolume(m_volume); + m_mastering_voice->SetVolume(m_volume); - if (pXAudio2) - pVoiceContext = new StreamingVoiceContext(pXAudio2, m_mixer, &soundSyncEvent); + m_voice_context = std::unique_ptr<StreamingVoiceContext> + (new StreamingVoiceContext(m_xaudio2.get(), m_mixer, m_sound_sync_event)); return true; } @@ -157,24 +140,22 @@ void XAudio2::SetVolume(int volume) //linear 1- .01 m_volume = (float)volume / 100.f; - if (pMasteringVoice) - pMasteringVoice->SetVolume(m_volume); - + if (m_mastering_voice) + m_mastering_voice->SetVolume(m_volume); } - -//XAUDIO2_PERFORMANCE_DATA perfData; -//int xi = 0; void XAudio2::Update() { - //soundSyncEvent.Set(); + //m_sound_sync_event.Set(); - //xi++; - //if (xi == 100000) { + //static int xi = 0; + //if (100000 == ++xi) + //{ // xi = 0; + // XAUDIO2_PERFORMANCE_DATA perfData; // pXAudio2->GetPerformanceData(&perfData); - // NOTICE_LOG(DSPHLE, "XAudio2 latency (samples): %i",perfData.CurrentLatencyInSamples); - // NOTICE_LOG(DSPHLE, "XAudio2 total glitches: %i",perfData.GlitchesSinceEngineStarted); + // NOTICE_LOG(DSPHLE, "XAudio2 latency (samples): %i", perfData.CurrentLatencyInSamples); + // NOTICE_LOG(DSPHLE, "XAudio2 total glitches: %i", perfData.GlitchesSinceEngineStarted); //} } @@ -182,26 +163,26 @@ void XAudio2::Clear(bool mute) { m_muted = mute; - if (pVoiceContext) + if (m_voice_context) { if (m_muted) - pVoiceContext->Stop(); + m_voice_context->Stop(); else - pVoiceContext->Play(); + m_voice_context->Play(); } } void XAudio2::Stop() { - //soundSyncEvent.Set(); + //m_sound_sync_event.Set(); - safe_delete(pVoiceContext); - pVoiceContext = NULL; + m_voice_context.reset(); - if(pMasteringVoice) - pMasteringVoice->DestroyVoice(); + if (m_mastering_voice) + { + m_mastering_voice->DestroyVoice(); + m_mastering_voice = nullptr; + } - safe_release(pXAudio2); - pMasteringVoice = NULL; - CoUninitialize(); + m_xaudio2.reset(); // release interface } diff --git a/Source/Core/AudioCommon/Src/XAudio2Stream.h b/Source/Core/AudioCommon/Src/XAudio2Stream.h index cecb587663..658f73f48f 100644 --- a/Source/Core/AudioCommon/Src/XAudio2Stream.h +++ b/Source/Core/AudioCommon/Src/XAudio2Stream.h @@ -23,59 +23,89 @@ #ifdef _WIN32 #include "Thread.h" #include <xaudio2.h> +#include <memory> -const int NUM_BUFFERS = 3; -const int SAMPLES_PER_BUFFER = 96; - -const int NUM_CHANNELS = 2; -const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS; -const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16); - +struct StreamingVoiceContext : public IXAudio2VoiceCallback +{ +private: + CMixer* const m_mixer; + Common::Event& m_sound_sync_event; + IXAudio2SourceVoice* m_source_voice; + std::unique_ptr<BYTE[]> xaudio_buffer; -#ifndef safe_delete_array -#define safe_delete_array(p) { if(p) { delete[] (p); (p)=NULL; } } -#endif -#ifndef safe_delete -#define safe_delete(a) if( (a) != NULL ) delete (a); (a) = NULL; -#endif -#ifndef safe_release -#define safe_release(p) { if(p) { (p)->Release(); (p)=NULL; } } -#endif + void SubmitBuffer(PBYTE buf_data); +public: + StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event& pSyncEvent); + + ~StreamingVoiceContext(); + + void StreamingVoiceContext::Stop(); + void StreamingVoiceContext::Play(); + + STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {} + STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {} + STDMETHOD_(void, OnVoiceProcessingPassEnd) () {} + STDMETHOD_(void, OnBufferStart) (void*) {} + STDMETHOD_(void, OnLoopEnd) (void*) {} + STDMETHOD_(void, OnStreamEnd) () {} + + STDMETHOD_(void, OnBufferEnd) (void* context); +}; #endif class XAudio2 : public SoundStream { #ifdef _WIN32 - IXAudio2 *pXAudio2; - IXAudio2MasteringVoice *pMasteringVoice; - IXAudio2SourceVoice *pSourceVoice; - Common::Event soundSyncEvent; + class Releaser + { + public: + template <typename R> + void operator()(R* ptr) + { + ptr->Release(); + } + }; + +private: + std::unique_ptr<IXAudio2, Releaser> m_xaudio2; + std::unique_ptr<StreamingVoiceContext> m_voice_context; + IXAudio2MasteringVoice *m_mastering_voice; + + Common::Event m_sound_sync_event; float m_volume; + const bool m_cleanup_com; - bool Init(); public: XAudio2(CMixer *mixer) - : SoundStream(mixer), - pXAudio2(0), - pMasteringVoice(0), - pSourceVoice(0), - m_volume(1.0f) {} + : SoundStream(mixer) + , m_mastering_voice(nullptr) + , m_volume(1.0f) + , m_cleanup_com(SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) + {} - virtual ~XAudio2() {} + virtual ~XAudio2() + { + Stop(); + if (m_cleanup_com) + CoUninitialize(); + } virtual bool Start(); - virtual void SetVolume(int volume); - virtual void Stop(); + virtual void Stop(); + + virtual void Update(); virtual void Clear(bool mute); - static bool isValid() { return true; } - virtual bool usesMixer() const { return true; } - virtual void Update(); + virtual void SetVolume(int volume); + virtual bool usesMixer() const { return true; } + + static bool isValid() { return true; } #else + public: XAudio2(CMixer *mixer, void *hWnd = NULL) : SoundStream(mixer) |
