1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 03:02:53 +01:00

Improved AudioThread interface, added XAudio2 audio output

This commit is contained in:
Oil 2015-01-11 03:46:10 +04:00
parent e6e60795b7
commit b5c33ec26b
12 changed files with 289 additions and 70 deletions

View File

@ -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");
@ -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<g_al_buffers_count; ++i)
for (uint i = 0; i<g_al_buffers_count; ++i)
{
AddBlock(m_buffers[i], m_buffer_size, src);
alBufferData(m_buffers[i], g_audio_format, src, m_buffer_size, 48000);
checkForAlError("alBufferData");
}
alSourceQueueBuffers(m_source, g_al_buffers_count, m_buffers);
@ -110,7 +111,7 @@ void OpenALThread::Open(const void* src, ALsizei size)
Play();
}
void OpenALThread::AddData(const void* src, ALsizei size)
void OpenALThread::AddData(const void* src, int size)
{
const char* bsrc = (const char*)src;
ALuint buffer;
@ -119,9 +120,9 @@ void OpenALThread::AddData(const void* src, ALsizei size)
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &buffers_count);
checkForAlError("OpenALThread::AddData -> alGetSourcei");
while(size)
while (size)
{
if(buffers_count-- <= 0)
if (buffers_count-- <= 0)
{
Play();
@ -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");
@ -147,13 +149,3 @@ 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;
}

View File

@ -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();
virtual ~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 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);
};

View File

@ -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
}
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "sysutil_audio.h"
#include "AL/OpenALThread.h"
#include "AudioThread.h"
struct 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;

View File

@ -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;
};

View File

@ -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) {}
};

View File

@ -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

View File

@ -0,0 +1,25 @@
#pragma once
#include "Emu/Audio/AudioThread.h"
#if defined (_WIN32)
#include "XAudio2.h" // XAudio2 2.8 available only on Win8+, used XAudio2 2.7 from dxsdk
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

View File

@ -81,16 +81,14 @@ int cellAudioInit()
std::vector<u64> keys;
if(m_audio_out)
{
m_audio_out->Init();
Emu.GetAudioManager().GetAudioOut().Init();
// 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));
// 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));
}
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;
}

View File

@ -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");

View File

@ -84,6 +84,7 @@
<ClCompile Include="Emu\Audio\AL\OpenALThread.cpp" />
<ClCompile Include="Emu\Audio\AudioDumper.cpp" />
<ClCompile Include="Emu\Audio\AudioManager.cpp" />
<ClCompile Include="Emu\Audio\XAudio2\XAudio2Thread.cpp" />
<ClCompile Include="Emu\Cell\MFC.cpp" />
<ClCompile Include="Emu\Cell\PPCDecoder.cpp" />
<ClCompile Include="Emu\Cell\PPCThread.cpp" />
@ -300,6 +301,9 @@
<ClInclude Include="Emu\Audio\AL\OpenALThread.h" />
<ClInclude Include="Emu\Audio\AudioDumper.h" />
<ClInclude Include="Emu\Audio\AudioManager.h" />
<ClInclude Include="Emu\Audio\AudioThread.h" />
<ClInclude Include="Emu\Audio\Null\NullAudioThread.h" />
<ClInclude Include="Emu\Audio\XAudio2\XAudio2Thread.h" />
<ClInclude Include="Emu\Cell\MFC.h" />
<ClInclude Include="Emu\Cell\PPCDecoder.h" />
<ClInclude Include="Emu\Cell\PPCDisAsm.h" />
@ -599,22 +603,32 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<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</IncludePath>
<IntDir>$(Platform)\$(Configuration)\emucore\</IntDir>
<LibraryPath>$(LibraryPath)</LibraryPath>
<ExcludePath>$(ExcludePath)</ExcludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">
<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</IncludePath>
<IntDir>$(Platform)\$(Configuration)\emucore\</IntDir>
<LibraryPath>$(LibraryPath)</LibraryPath>
<ExcludePath>$(ExcludePath)</ExcludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">
<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</IncludePath>
<IntDir>$(Platform)\$(Configuration)\emucore\</IntDir>
<LibraryPath>$(LibraryPath)</LibraryPath>
<ExcludePath>$(ExcludePath)</ExcludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<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</IncludePath>
<IntDir>$(Platform)\$(Configuration)\emucore\</IntDir>
<LibraryPath>$(LibraryPath)</LibraryPath>
<ExcludePath>$(ExcludePath)</ExcludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">
<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</IncludePath>
<IntDir>$(Platform)\$(Configuration)\emucore\</IntDir>
<LibraryPath>$(LibraryPath)</LibraryPath>
<ExcludePath>$(ExcludePath)</ExcludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -662,6 +676,8 @@
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<ExceptionHandling>Async</ExceptionHandling>
<AdditionalIncludeDirectories>.\minidx9\Include</AdditionalIncludeDirectories>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -676,6 +692,7 @@
<PreprocessorDefinitions>_UNICODE;UNICODE;LLVM_AVAILABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<ExceptionHandling>Async</ExceptionHandling>
<AdditionalIncludeDirectories>.\minidx9\Include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -694,6 +711,7 @@
<PreprocessorDefinitions>_UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<ExceptionHandling>Async</ExceptionHandling>
<AdditionalIncludeDirectories>.\minidx9\Include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -741,6 +759,7 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<ExceptionHandling>Async</ExceptionHandling>
<AdditionalIncludeDirectories>.\minidx9\Include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -759,6 +778,7 @@
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<ExceptionHandling>Async</ExceptionHandling>
<PreprocessorDefinitions>LLVM_AVAILABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.\minidx9\Include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -81,6 +81,12 @@
<Filter Include="Emu\GPU\RSX\GL">
<UniqueIdentifier>{6f1da5b2-52c5-416b-9b5c-b9897bc1b300}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\Audio\Null">
<UniqueIdentifier>{1eae80f6-5aef-4049-81a0-bbfd7602f8f6}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\Audio\XAudio2">
<UniqueIdentifier>{1d6abf72-0f18-43ec-9351-1fed1a3d1a1e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Crypto\aes.cpp">
@ -653,6 +659,9 @@
<ClCompile Include="..\Utilities\Thread.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="Emu\Audio\XAudio2\XAudio2Thread.cpp">
<Filter>Emu\Audio\XAudio2</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -1261,5 +1270,14 @@
<ClInclude Include="..\Utilities\Thread.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="Emu\Audio\Null\NullAudioThread.h">
<Filter>Emu\Audio\Null</Filter>
</ClInclude>
<ClInclude Include="Emu\Audio\AudioThread.h">
<Filter>Emu\Audio</Filter>
</ClInclude>
<ClInclude Include="Emu\Audio\XAudio2\XAudio2Thread.h">
<Filter>Emu\Audio\XAudio2</Filter>
</ClInclude>
</ItemGroup>
</Project>