Skip to content

Commit

Permalink
Audio: downmix to stereo
Browse files Browse the repository at this point in the history
  • Loading branch information
Nekotekina committed Apr 9, 2017
1 parent 4c741e9 commit 77aa314
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 28 deletions.
14 changes: 12 additions & 2 deletions rpcs3/Emu/Audio/AL/OpenALThread.cpp
Expand Up @@ -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")
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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");
}

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Audio/AL/OpenALThread.h
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions rpcs3/Emu/Audio/ALSA/ALSAThread.cpp
Expand Up @@ -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};

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

Expand Down
7 changes: 4 additions & 3 deletions rpcs3/Emu/Audio/XAudio2/XAudio27Thread.cpp
Expand Up @@ -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{};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions rpcs3/Emu/Audio/XAudio2/XAudio28Thread.cpp
Expand Up @@ -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{};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
42 changes: 24 additions & 18 deletions rpcs3/Emu/Cell/Modules/cellAudio.cpp
Expand Up @@ -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)
{
Expand All @@ -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())
{
Expand Down Expand Up @@ -225,24 +226,28 @@ 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];
}
}
}

const u64 stamp1 = get_system_time();

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)
Expand All @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions rpcs3/Gui/SettingsDialog.cpp
Expand Up @@ -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");
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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());
Expand Down

0 comments on commit 77aa314

Please sign in to comment.