diff --git a/.gitmodules b/.gitmodules index fb181e64b1..6a79e8891c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,3 +12,6 @@ path = llvm url = https://github.com/llvm-mirror/llvm.git branch = release_35 +[submodule "minidx9"] + path = minidx9 + url = https://github.com/hrydgard/minidx9.git diff --git a/minidx9 b/minidx9 new file mode 160000 index 0000000000..ec19e64346 --- /dev/null +++ b/minidx9 @@ -0,0 +1 @@ +Subproject commit ec19e643461c84dbb256f6faaaab02cba61d4edc diff --git a/rpcs3/Emu/Audio/AL/OpenALThread.cpp b/rpcs3/Emu/Audio/AL/OpenALThread.cpp index 5d24514d46..f63fda6dc6 100644 --- a/rpcs3/Emu/Audio/AL/OpenALThread.cpp +++ b/rpcs3/Emu/Audio/AL/OpenALThread.cpp @@ -15,7 +15,7 @@ static const ALenum g_audio_format = Ini.AudioConvertToU16.GetValue() ? AL_FORMA void printAlError(ALenum err, const char* situation) { - if(err != AL_NO_ERROR) + if (err != AL_NO_ERROR) { LOG_ERROR(HLE, "%s: OpenAL error 0x%04x", situation, err); Emu.Pause(); @@ -24,7 +24,7 @@ void printAlError(ALenum err, const char* situation) void printAlcError(ALCenum err, const char* situation) { - if(err != ALC_NO_ERROR) + if (err != ALC_NO_ERROR) { LOG_ERROR(HLE, "%s: OpenALC error 0x%04x", situation, err); Emu.Pause(); @@ -63,7 +63,7 @@ void OpenALThread::Play() alGetSourcei(m_source, AL_SOURCE_STATE, &state); checkForAlError("OpenALThread::Play -> alGetSourcei"); - if(state != AL_PLAYING) + if (state != AL_PLAYING) { alSourcePlay(m_source); checkForAlError("alSourcePlay"); @@ -74,7 +74,7 @@ void OpenALThread::Close() { alSourceStop(m_source); checkForAlError("alSourceStop"); - if (alIsSource(m_source)) + if (alIsSource(m_source)) alDeleteSources(1, &m_source); alDeleteBuffers(g_al_buffers_count, m_buffers); @@ -87,7 +87,7 @@ void OpenALThread::Stop() checkForAlError("alSourceStop"); } -void OpenALThread::Open(const void* src, ALsizei size) +void OpenALThread::Open(const void* src, int size) { alGenSources(1, &m_source); checkForAlError("alGenSources"); @@ -100,9 +100,10 @@ void OpenALThread::Open(const void* src, ALsizei size) m_buffer_size = size; - for(uint i=0; i alGetSourcei"); - - while(size) + + while (size) { - if(buffers_count-- <= 0) + if (buffers_count-- <= 0) { Play(); alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &buffers_count); checkForAlError("OpenALThread::AddData(in loop) -> alGetSourcei"); - + continue; } @@ -135,8 +136,9 @@ void OpenALThread::AddData(const void* src, ALsizei size) checkForAlError("alSourceUnqueueBuffers"); int bsize = size < m_buffer_size ? size : m_buffer_size; - if (!AddBlock(buffer, bsize, bsrc)) - LOG_ERROR(HLE, "OpenALThread::AddBlock: invalid block size: %d", bsize); + + alBufferData(buffer, g_audio_format, bsrc, bsize, 48000); + checkForAlError("alBufferData"); alSourceQueueBuffers(m_source, 1, &buffer); checkForAlError("alSourceQueueBuffers"); @@ -146,14 +148,4 @@ void OpenALThread::AddData(const void* src, ALsizei size) } Play(); -} - -bool OpenALThread::AddBlock(const ALuint buffer_id, const ALsizei size, const void* src) -{ - if (size < 1) return false; - - alBufferData(buffer_id, g_audio_format, src, size, 48000); - checkForAlError("alBufferData"); - - return true; -} +} \ No newline at end of file diff --git a/rpcs3/Emu/Audio/AL/OpenALThread.h b/rpcs3/Emu/Audio/AL/OpenALThread.h index 49d4dd4f79..4d8f72a821 100644 --- a/rpcs3/Emu/Audio/AL/OpenALThread.h +++ b/rpcs3/Emu/Audio/AL/OpenALThread.h @@ -1,8 +1,9 @@ #pragma once +#include "Emu/Audio/AudioThread.h" #include "OpenAL/include/alext.h" -class OpenALThread +class OpenALThread : public AudioThread { private: static const uint g_al_buffers_count = 16; @@ -14,15 +15,13 @@ private: ALsizei m_buffer_size; public: - ~OpenALThread(); - - void Init(); - void Quit(); - void Play(); - void Open(const void* src, ALsizei size); - void Close(); - void Stop(); - bool AddBlock(const ALuint buffer_id, ALsizei size, const void* src); - void AddData(const void* src, ALsizei size); -}; + virtual ~OpenALThread(); + virtual void Init(); + virtual void Quit(); + virtual void Play(); + virtual void Open(const void* src, int size); + virtual void Close(); + virtual void Stop(); + virtual void AddData(const void* src, int size); +}; \ No newline at end of file diff --git a/rpcs3/Emu/Audio/AudioManager.cpp b/rpcs3/Emu/Audio/AudioManager.cpp index 1207e61d6b..8e19fc7542 100644 --- a/rpcs3/Emu/Audio/AudioManager.cpp +++ b/rpcs3/Emu/Audio/AudioManager.cpp @@ -1,24 +1,28 @@ #include "stdafx.h" #include "rpcs3/Ini.h" #include "AudioManager.h" +#include "AL/OpenALThread.h" +#include "Null/NullAudioThread.h" +#include "XAudio2/XAudio2Thread.h" -OpenALThread* m_audio_out; - -AudioManager::AudioManager() +AudioManager::AudioManager() : m_audio_out(nullptr) { } void AudioManager::Init() { - if(m_audio_out) return; + if (m_audio_out) return; m_audio_info.Init(); - switch(Ini.AudioOutMode.GetValue()) + switch (Ini.AudioOutMode.GetValue()) { default: - case 0: m_audio_out = nullptr; break; + case 0: m_audio_out = new NullAudioThread(); break; case 1: m_audio_out = new OpenALThread(); break; +#if defined (_WIN32) + case 2: m_audio_out = new XAudio2Thread(); break; +#endif } } diff --git a/rpcs3/Emu/Audio/AudioManager.h b/rpcs3/Emu/Audio/AudioManager.h index dc448b7ced..f66482f7ae 100644 --- a/rpcs3/Emu/Audio/AudioManager.h +++ b/rpcs3/Emu/Audio/AudioManager.h @@ -1,17 +1,17 @@ #pragma once #include "sysutil_audio.h" -#include "AL/OpenALThread.h" +#include "AudioThread.h" struct AudioInfo { struct { - u8 type; + u8 type; u8 channel; - u8 encoder; + u8 encoder; u8 fs; - u32 layout; - u32 downMixer; + u32 layout; + u32 downMixer; } mode; AudioInfo() @@ -32,16 +32,15 @@ struct AudioInfo class AudioManager { AudioInfo m_audio_info; + AudioThread* m_audio_out; public: AudioManager(); void Init(); void Close(); + AudioThread& GetAudioOut() { assert(m_audio_out); return *m_audio_out; } AudioInfo& GetInfo() { return m_audio_info; } u8 GetState(); -}; - -extern OpenALThread* m_audio_out; - +}; \ No newline at end of file diff --git a/rpcs3/Emu/Audio/AudioThread.h b/rpcs3/Emu/Audio/AudioThread.h new file mode 100644 index 0000000000..fa600ba9cb --- /dev/null +++ b/rpcs3/Emu/Audio/AudioThread.h @@ -0,0 +1,15 @@ +#pragma once + +class AudioThread +{ +public: + virtual ~AudioThread() {} + + virtual void Init() = 0; + virtual void Quit() = 0; + virtual void Play() = 0; + virtual void Open(const void* src, int size) = 0; + virtual void Close() = 0; + virtual void Stop() = 0; + virtual void AddData(const void* src, int size) = 0; +}; \ No newline at end of file diff --git a/rpcs3/Emu/Audio/Null/NullAudioThread.h b/rpcs3/Emu/Audio/Null/NullAudioThread.h new file mode 100644 index 0000000000..15dd40e12c --- /dev/null +++ b/rpcs3/Emu/Audio/Null/NullAudioThread.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Emu/Audio/AudioThread.h" + +class NullAudioThread : public AudioThread +{ +public: + NullAudioThread() {} + virtual ~NullAudioThread() {} + + virtual void Init() {} + virtual void Quit() {} + virtual void Play() {} + virtual void Open(const void* src, int size) {} + virtual void Close() {} + virtual void Stop() {} + virtual void AddData(const void* src, int size) {} +}; \ No newline at end of file diff --git a/rpcs3/Emu/Audio/XAudio2/XAudio2Thread.cpp b/rpcs3/Emu/Audio/XAudio2/XAudio2Thread.cpp new file mode 100644 index 0000000000..f6da9b75fb --- /dev/null +++ b/rpcs3/Emu/Audio/XAudio2/XAudio2Thread.cpp @@ -0,0 +1,132 @@ +#include "stdafx.h" +#include "Utilities/Log.h" +#include "Emu/System.h" +#include "rpcs3/Ini.h" + +#if defined (_WIN32) +#include "XAudio2Thread.h" + +XAudio2Thread::~XAudio2Thread() +{ + Quit(); +} + +void XAudio2Thread::Init() +{ + HRESULT hr = S_OK; + + hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : CoInitializeEx() failed(0x%08x)", hr); + Emu.Pause(); + return; + } + + hr = XAudio2Create(&m_xaudio2_instance, 0, XAUDIO2_DEFAULT_PROCESSOR); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : XAudio2Create() failed(0x%08x)", hr); + Emu.Pause(); + return; + } + + hr = m_xaudio2_instance->CreateMasteringVoice(&m_master_voice); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : CreateMasteringVoice() failed(0x%08x)", hr); + m_xaudio2_instance->Release(); + Emu.Pause(); + } +} + +void XAudio2Thread::Quit() +{ + Stop(); + m_source_voice->DestroyVoice(); + m_source_voice = nullptr; + m_master_voice->DestroyVoice(); + m_master_voice = nullptr; + m_xaudio2_instance->StopEngine(); + m_xaudio2_instance->Release(); + m_xaudio2_instance = nullptr; +} + +void XAudio2Thread::Play() +{ + HRESULT hr = m_source_voice->Start(); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : Start() failed(0x%08x)", hr); + Emu.Pause(); + } +} + +void XAudio2Thread::Close() +{ + Stop(); + HRESULT hr = m_source_voice->FlushSourceBuffers(); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : FlushSourceBuffers() failed(0x%08x)", hr); + Emu.Pause(); + } +} + +void XAudio2Thread::Stop() +{ + HRESULT hr = m_source_voice->Stop(); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : Stop() failed(0x%08x)", hr); + Emu.Pause(); + } +} + +void XAudio2Thread::Open(const void* src, int size) +{ + HRESULT hr; + + WAVEFORMATEX waveformatex; + waveformatex.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + waveformatex.nChannels = 2; + waveformatex.nSamplesPerSec = 48000; + waveformatex.nAvgBytesPerSec = 48000 * 2 * sizeof(float); + waveformatex.nBlockAlign = 2 * sizeof(float); + waveformatex.wBitsPerSample = 32; + waveformatex.cbSize = 0; + + hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : CreateSourceVoice() failed(0x%08x)", hr); + Emu.Pause(); + return; + } + + AddData(src, size); + Play(); +} + +void XAudio2Thread::AddData(const void* src, int size) +{ + XAUDIO2_BUFFER buffer; + + buffer.AudioBytes = size; + buffer.Flags = 0; + buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION; + buffer.LoopCount = 0; + buffer.LoopLength = 0; + buffer.pAudioData = (const BYTE*)src; + buffer.pContext = 0; + buffer.PlayBegin = 0; + buffer.PlayLength = 256; + + HRESULT hr = m_source_voice->SubmitSourceBuffer(&buffer); + if (FAILED(hr)) + { + LOG_ERROR(GENERAL, "XAudio2Thread : AddData() failed(0x%08x)", hr); + Emu.Pause(); + } +} +#endif \ No newline at end of file diff --git a/rpcs3/Emu/Audio/XAudio2/XAudio2Thread.h b/rpcs3/Emu/Audio/XAudio2/XAudio2Thread.h new file mode 100644 index 0000000000..3a362714ad --- /dev/null +++ b/rpcs3/Emu/Audio/XAudio2/XAudio2Thread.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Emu/Audio/AudioThread.h" +#if defined (_WIN32) + +// forced define Win7, delete this for using XAudio2 2.8 +#define WINVER 0x0601 +#define _WIN32_WINNT 0x0601 + +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) +#include +#pragma comment(lib,"xaudio2.lib") +#else +#include "XAudio2.h" // XAudio2 2.8 available only on Win8+, used XAudio2 2.7 from dxsdk +#endif + +class XAudio2Thread : public AudioThread +{ +private: + IXAudio2* m_xaudio2_instance; + IXAudio2MasteringVoice* m_master_voice; + IXAudio2SourceVoice* m_source_voice; + +public: + virtual ~XAudio2Thread(); + + virtual void Init(); + virtual void Quit(); + virtual void Play(); + virtual void Open(const void* src, int size); + virtual void Close(); + virtual void Stop(); + virtual void AddData(const void* src, int size); +}; +#endif \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index afbf9dbaa6..6ebbce0d14 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -81,16 +81,14 @@ int cellAudioInit() std::vector keys; - if(m_audio_out) - { - m_audio_out->Init(); + Emu.GetAudioManager().GetAudioOut().Init(); - // Note: What if the ini value changes? - if (g_is_u16) - m_audio_out->Open(oal_buffer[0].get(), oal_buffer_size * sizeof(s16)); - else - m_audio_out->Open(oal_buffer_float[0].get(), oal_buffer_size * sizeof(float)); - } + // Note: What if the ini value changes? + if (g_is_u16) + Emu.GetAudioManager().GetAudioOut().Open(oal_buffer[0].get(), oal_buffer_size * sizeof(s16)); + else + Emu.GetAudioManager().GetAudioOut().Open(oal_buffer_float[0].get(), oal_buffer_size * sizeof(float)); + m_config.start_time = get_system_time(); @@ -112,7 +110,7 @@ int cellAudioInit() { if (oal_buffer) { - m_audio_out->AddData(oal_buffer, oal_buffer_size * sizeof(s16)); + Emu.GetAudioManager().GetAudioOut().AddData(oal_buffer, oal_buffer_size * sizeof(s16)); continue; } } @@ -120,7 +118,7 @@ int cellAudioInit() { if (oal_buffer_float) { - m_audio_out->AddData(oal_buffer_float, oal_buffer_size * sizeof(float)); + Emu.GetAudioManager().GetAudioOut().AddData(oal_buffer_float, oal_buffer_size * sizeof(float)); continue; } } @@ -366,14 +364,10 @@ int cellAudioInit() if(oal_buffer_offset >= oal_buffer_size) { - if(m_audio_out) - { - if (g_is_u16) - queue.push(&oal_buffer[oal_pos][0]); - - queue_float.push(&oal_buffer_float[oal_pos][0]); - } + if (g_is_u16) + queue.push(&oal_buffer[oal_pos][0]); + queue_float.push(&oal_buffer_float[oal_pos][0]); oal_buffer_offset = 0; } diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 595d207423..5c13cc2f9f 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -474,6 +474,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_audio_out->Append("Null"); cbox_audio_out->Append("OpenAL"); +#if defined (_WIN32) + cbox_audio_out->Append("XAudio2"); +#endif cbox_camera->Append("Null"); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 65060fbd04..b3694d79b4 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -84,6 +84,7 @@ + @@ -300,6 +301,9 @@ + + + @@ -597,24 +601,34 @@ .\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - .\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include + .\;..\;..\minidx9\Include;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include $(Platform)\$(Configuration)\emucore\ + $(LibraryPath) + $(ExcludePath) - .\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include + .\;..\;..\minidx9\Include;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include $(Platform)\$(Configuration)\emucore\ + $(LibraryPath) + $(ExcludePath) - .\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include + .\;..\;..\minidx9\Include;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include $(Platform)\$(Configuration)\emucore\ + $(LibraryPath) + $(ExcludePath) - .\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include + .\;..\;..\minidx9\Include;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include $(Platform)\$(Configuration)\emucore\ + $(LibraryPath) + $(ExcludePath) - .\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include + .\;..\;..\minidx9\Include;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include $(Platform)\$(Configuration)\emucore\ + $(LibraryPath) + $(ExcludePath) @@ -662,6 +676,9 @@ _UNICODE;UNICODE;%(PreprocessorDefinitions) stdafx.h Async + + + false true @@ -676,6 +693,8 @@ _UNICODE;UNICODE;LLVM_AVAILABLE;%(PreprocessorDefinitions) stdafx.h Async + + true @@ -694,6 +713,8 @@ _UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions) stdafx.h Async + + true @@ -741,6 +762,8 @@ Use stdafx.h Async + + true @@ -759,6 +782,8 @@ stdafx.h Async LLVM_AVAILABLE;%(PreprocessorDefinitions) + + true diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 6cc6e711d0..2f0baf5d6f 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -81,6 +81,12 @@ {6f1da5b2-52c5-416b-9b5c-b9897bc1b300} + + {1eae80f6-5aef-4049-81a0-bbfd7602f8f6} + + + {1d6abf72-0f18-43ec-9351-1fed1a3d1a1e} + @@ -653,6 +659,9 @@ Utilities + + Emu\Audio\XAudio2 + @@ -1261,5 +1270,14 @@ Utilities + + Emu\Audio\Null + + + Emu\Audio + + + Emu\Audio\XAudio2 + \ No newline at end of file