Audio: downmix to stereo

This commit is contained in:
Nekotekina 2017-04-09 23:43:53 +03:00
parent 4c741e93c3
commit 77aa3142a9
7 changed files with 52 additions and 28 deletions

View File

@ -5,6 +5,7 @@
#include "OpenALThread.h"
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
extern cfg::bool_entry g_cfg_audio_downmix_to_2ch;
#ifdef _MSC_VER
#pragma comment(lib, "OpenAL32.lib")
@ -44,6 +45,15 @@ OpenALThread::OpenALThread()
alcMakeContextCurrent(m_context);
checkForAlcError("alcMakeContextCurrent");
if (g_cfg_audio_downmix_to_2ch)
{
m_format = g_cfg_audio_convert_to_u16 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;
}
else
{
m_format = g_cfg_audio_convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32;
}
}
OpenALThread::~OpenALThread()
@ -102,7 +112,7 @@ void OpenALThread::Open(const void* src, int size)
for (uint i = 0; i<g_al_buffers_count; ++i)
{
alBufferData(m_buffers[i], g_cfg_audio_convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, src, m_buffer_size, 48000);
alBufferData(m_buffers[i], m_format, src, m_buffer_size, 48000);
checkForAlError("alBufferData");
}
@ -137,7 +147,7 @@ void OpenALThread::AddData(const void* src, int size)
int bsize = size < m_buffer_size ? size : m_buffer_size;
alBufferData(buffer, g_cfg_audio_convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, bsrc, bsize, 48000);
alBufferData(buffer, m_format, bsrc, bsize, 48000);
checkForAlError("alBufferData");
alSourceQueueBuffers(m_source, 1, &buffer);

View File

@ -8,6 +8,7 @@ class OpenALThread : public AudioThread
private:
static const uint g_al_buffers_count = 24;
ALint m_format;
ALuint m_source;
ALuint m_buffers[g_al_buffers_count];
ALsizei m_buffer_size;

View File

@ -10,6 +10,7 @@
#include <alsa/asoundlib.h>
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
extern cfg::bool_entry g_cfg_audio_downmix_to_2ch;
thread_local static snd_pcm_t* s_tls_handle{nullptr};
@ -59,7 +60,7 @@ ALSAThread::ALSAThread()
if (!check(snd_pcm_hw_params_set_rate(s_tls_handle, hw_params, 48000, 0), "snd_pcm_hw_params_set_rate_near"))
return;
if (!check(snd_pcm_hw_params_set_channels(s_tls_handle, hw_params, 8), "snd_pcm_hw_params_set_channels"))
if (!check(snd_pcm_hw_params_set_channels(s_tls_handle, hw_params, g_cfg_audio_downmix_to_2ch ? 2 : 8), "snd_pcm_hw_params_set_channels"))
return;
if (!check(snd_pcm_hw_params_set_buffer_size(s_tls_handle, hw_params, 64 * 256), "snd_pcm_hw_params_set_buffer_size"))
@ -105,7 +106,8 @@ void ALSAThread::Open(const void* src, int size)
void ALSAThread::AddData(const void* src, int size)
{
size /= g_cfg_audio_convert_to_u16 ? 2 * 8 : 4 * 8;
size /= g_cfg_audio_convert_to_u16 ? 2 : 4;
size /= g_cfg_audio_downmix_to_2ch ? 2 : 8;
int res;

View File

@ -9,6 +9,7 @@
#include "3rdparty/XAudio2_7/XAudio2.h"
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
extern cfg::bool_entry g_cfg_audio_downmix_to_2ch;
static thread_local HMODULE s_tls_xaudio2_lib{};
static thread_local IXAudio2* s_tls_xaudio2_instance{};
@ -37,7 +38,7 @@ void XAudio2Thread::xa27_init(void* lib2_7)
return;
}
hr = s_tls_xaudio2_instance->CreateMasteringVoice(&s_tls_master_voice, 8, 48000);
hr = s_tls_xaudio2_instance->CreateMasteringVoice(&s_tls_master_voice, g_cfg_audio_downmix_to_2ch ? 2 : 8, 48000);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateMasteringVoice() failed(0x%08x)", (u32)hr);
@ -105,7 +106,7 @@ void XAudio2Thread::xa27_open()
HRESULT hr;
WORD sample_size = g_cfg_audio_convert_to_u16 ? sizeof(u16) : sizeof(float);
WORD channels = 8;
WORD channels = g_cfg_audio_downmix_to_2ch ? 2 : 8;
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg_audio_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
@ -124,7 +125,7 @@ void XAudio2Thread::xa27_open()
return;
}
s_tls_source_voice->SetVolume(4.0);
s_tls_source_voice->SetVolume(g_cfg_audio_downmix_to_2ch ? 1.0 : 4.0);
}
void XAudio2Thread::xa27_add(const void* src, int size)

View File

@ -9,6 +9,7 @@
#include "3rdparty/minidx12/Include/xaudio2.h"
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
extern cfg::bool_entry g_cfg_audio_downmix_to_2ch;
static thread_local HMODULE s_tls_xaudio2_lib{};
static thread_local IXAudio2* s_tls_xaudio2_instance{};
@ -39,7 +40,7 @@ void XAudio2Thread::xa28_init(void* lib)
return;
}
hr = s_tls_xaudio2_instance->CreateMasteringVoice(&s_tls_master_voice, 8, 48000);
hr = s_tls_xaudio2_instance->CreateMasteringVoice(&s_tls_master_voice, g_cfg_audio_downmix_to_2ch ? 2 : 8, 48000);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateMasteringVoice() failed(0x%08x)", (u32)hr);
@ -107,7 +108,7 @@ void XAudio2Thread::xa28_open()
HRESULT hr;
WORD sample_size = g_cfg_audio_convert_to_u16 ? sizeof(u16) : sizeof(float);
WORD channels = 8;
WORD channels = g_cfg_audio_downmix_to_2ch ? 2 : 8;
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg_audio_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
@ -126,7 +127,7 @@ void XAudio2Thread::xa28_open()
return;
}
s_tls_source_voice->SetVolume(4.0);
s_tls_source_voice->SetVolume(g_cfg_audio_downmix_to_2ch ? 1.0 : 4.0);
}
void XAudio2Thread::xa28_add(const void* src, int size)

View File

@ -15,6 +15,7 @@ logs::channel cellAudio("cellAudio", logs::level::notice);
cfg::bool_entry g_cfg_audio_dump_to_file(cfg::root.audio, "Dump to file");
cfg::bool_entry g_cfg_audio_convert_to_u16(cfg::root.audio, "Convert to 16 bit");
cfg::bool_entry g_cfg_audio_downmix_to_2ch(cfg::root.audio, "Downmix to Stereo", true);
void audio_config::on_init(const std::shared_ptr<void>& _this)
{
@ -38,17 +39,17 @@ void audio_config::on_task()
float buf2ch[2 * BUFFER_SIZE]{}; // intermediate buffer for 2 channels
float buf8ch[8 * BUFFER_SIZE]{}; // intermediate buffer for 8 channels
static const size_t out_buffer_size = 8 * BUFFER_SIZE; // output buffer for 8 channels
const u32 buf_sz = BUFFER_SIZE * (g_cfg_audio_convert_to_u16 ? 2 : 4) * (g_cfg_audio_downmix_to_2ch ? 2 : 8);
std::unique_ptr<float[]> out_buffer[BUFFER_NUM];
for (u32 i = 0; i < BUFFER_NUM; i++)
{
out_buffer[i].reset(new float[out_buffer_size] {});
out_buffer[i].reset(new float[8 * BUFFER_SIZE] {});
}
const auto audio = Emu.GetCallbacks().get_audio();
audio->Open(buf8ch, out_buffer_size * (g_cfg_audio_convert_to_u16 ? 2 : 4));
audio->Open(buf8ch, buf_sz);
while (fxm::check<audio_config>() && !Emu.IsStopped())
{
@ -225,16 +226,20 @@ void audio_config::on_task()
if (!first_mix)
{
// copy output data (2 ch)
//for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++)
//{
// out_buffer[out_pos][i] = buf2ch[i];
//}
// copy output data (8 ch)
for (u32 i = 0; i < (sizeof(buf8ch) / sizeof(float)); i++)
// Copy output data (2ch or 8ch)
if (g_cfg_audio_downmix_to_2ch)
{
out_buffer[out_pos][i] = buf8ch[i];
for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++)
{
out_buffer[out_pos][i] = buf2ch[i];
}
}
else
{
for (u32 i = 0; i < (sizeof(buf8ch) / sizeof(float)); i++)
{
out_buffer[out_pos][i] = buf8ch[i];
}
}
}
@ -242,7 +247,7 @@ void audio_config::on_task()
if (first_mix)
{
memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float));
std::memset(out_buffer[out_pos].get(), 0, 8 * BUFFER_SIZE * sizeof(float));
}
if (g_cfg_audio_convert_to_u16)
@ -254,20 +259,21 @@ void audio_config::on_task()
// 2x CVTPS2DQ (converts float to s32)
// PACKSSDW (converts s32 to s16 with signed saturation)
u16 buf_u16[out_buffer_size];
for (size_t i = 0; i < out_buffer_size; i += 8)
__m128i buf_u16[BUFFER_SIZE];
for (size_t i = 0; i < 8 * BUFFER_SIZE; i += 8)
{
const auto scale = _mm_set1_ps(0x8000);
(__m128i&)(buf_u16[i]) = _mm_packs_epi32(
buf_u16[i / 8] = _mm_packs_epi32(
_mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(out_buffer[out_pos].get() + i), scale)),
_mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(out_buffer[out_pos].get() + i + 4), scale)));
}
audio->AddData(buf_u16, out_buffer_size * sizeof(u16));
audio->AddData(buf_u16, buf_sz);
}
else
{
audio->AddData(out_buffer[out_pos].get(), out_buffer_size * sizeof(float));
audio->AddData(out_buffer[out_pos].get(), buf_sz);
}
const u64 stamp2 = get_system_time();

View File

@ -325,6 +325,7 @@ SettingsDialog::SettingsDialog(wxWindow* parent, const std::string& path)
wxCheckBox* chbox_gs_gpu_texture_scaling = new wxCheckBox(p_graphics, wxID_ANY, "Use GPU texture scaling");
wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file");
wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit");
wxCheckBox* chbox_audio_dnmx = new wxCheckBox(p_audio, wxID_ANY, "Downmix to Stereo");
wxCheckBox* chbox_hle_exitonstop = new wxCheckBox(p_misc, wxID_ANY, "Exit RPCS3 when process finishes");
wxCheckBox* chbox_hle_always_start = new wxCheckBox(p_misc, wxID_ANY, "Always start after boot");
wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at System Call");
@ -405,6 +406,7 @@ SettingsDialog::SettingsDialog(wxWindow* parent, const std::string& path)
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Audio", "Renderer" }, cbox_audio_out));
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Dump to file" }, chbox_audio_dump));
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Convert to 16 bit" }, chbox_audio_conv));
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Downmix to Stereo" }, chbox_audio_dnmx));
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Pad" }, cbox_pad_handler));
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Keyboard" }, cbox_keyboard_handler));
@ -514,6 +516,7 @@ SettingsDialog::SettingsDialog(wxWindow* parent, const std::string& path)
s_subpanel_audio->Add(s_round_audio_out, wxSizerFlags().Border(wxALL, 5).Expand());
s_subpanel_audio->Add(chbox_audio_dump, wxSizerFlags().Border(wxALL, 5).Expand());
s_subpanel_audio->Add(chbox_audio_conv, wxSizerFlags().Border(wxALL, 5).Expand());
s_subpanel_audio->Add(chbox_audio_dnmx, wxSizerFlags().Border(wxALL, 5).Expand());
// Miscellaneous
s_subpanel_misc->Add(chbox_hle_exitonstop, wxSizerFlags().Border(wxALL, 5).Expand());