diff --git a/rpcs3/Emu/Audio/AL/OpenALThread.cpp b/rpcs3/Emu/Audio/AL/OpenALThread.cpp index 4d0bba8005..ef912dc0f2 100644 --- a/rpcs3/Emu/Audio/AL/OpenALThread.cpp +++ b/rpcs3/Emu/Audio/AL/OpenALThread.cpp @@ -7,6 +7,8 @@ ALCenum g_last_alc_error = ALC_NO_ERROR; #define checkForAlError(sit) if((g_last_al_error = alGetError()) != AL_NO_ERROR) printAlError(g_last_al_error, sit) #define checkForAlcError(sit) if((g_last_alc_error = alcGetError(m_device)) != ALC_NO_ERROR) printAlcError(g_last_alc_error, sit) +static const ALenum g_audio_format = Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32; + void printAlError(ALenum err, const char* situation) { if(err != AL_NO_ERROR) @@ -142,11 +144,11 @@ void OpenALThread::AddData(const void* src, ALsizei size) Play(); } -bool OpenALThread::AddBlock(const ALuint buffer_id, ALsizei size, const void* src) +bool OpenALThread::AddBlock(const ALuint buffer_id, const ALsizei size, const void* src) { if (size < 1) return false; - alBufferData(buffer_id, AL_FORMAT_STEREO_FLOAT32, src, size, 48000); + alBufferData(buffer_id, g_audio_format, src, size, 48000); checkForAlError("alBufferData"); return true; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index ccbeef54ac..c9e64e9f08 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -13,6 +13,8 @@ static SMutexGeneral audioMutex; AudioConfig m_config; +static const bool g_is_u16 = Ini.AudioConvertToU16.GetValue(); + // libaudio Functions int cellAudioInit() @@ -55,43 +57,80 @@ int cellAudioInit() float buf8ch[8 * 256]; // intermediate buffer for 8 channels uint oal_buffer_offset = 0; - uint oal_buffer_size = sizeof(buf2ch) / sizeof(float); - std::unique_ptr oal_buffer[32]; - SQueue queue; + const uint oal_buffer_size = sizeof(buf2ch) / sizeof(float); + + std::unique_ptr oal_buffer[32]; + SQueue queue; + + std::unique_ptr oal_buffer_float[32]; + SQueue queue_float; + for (u32 i = 0; i < sizeof(oal_buffer) / sizeof(oal_buffer[0]); i++) { - oal_buffer[i] = std::unique_ptr(new float[oal_buffer_size]); - memset(oal_buffer[i].get(), 0, oal_buffer_size * sizeof(float)); + oal_buffer[i] = std::unique_ptr(new s16[oal_buffer_size]); + memset(oal_buffer[i].get(), 0, oal_buffer_size * sizeof(s16)); } queue.Clear(); + for (u32 i = 0; i < sizeof(oal_buffer_float) / sizeof(oal_buffer_float[0]); i++) + { + oal_buffer_float[i] = std::unique_ptr(new float[oal_buffer_size]); + memset(oal_buffer_float[i].get(), 0, oal_buffer_size * sizeof(float)); + } + queue_float.Clear(); + std::vector keys; if(m_audio_out) { m_audio_out->Init(); - m_audio_out->Open(oal_buffer[0].get(), oal_buffer_size * sizeof(float)); + + if (g_is_u16) + m_audio_out->Open(oal_buffer[0].get(), oal_buffer_size * sizeof(s16)); + + m_audio_out->Open(oal_buffer_float[0].get(), oal_buffer_size * sizeof(float)); } m_config.start_time = get_system_time(); volatile bool internal_finished = false; - thread iat("Internal Audio Thread", [oal_buffer_size, &queue, &internal_finished]() + thread iat("Internal Audio Thread", [oal_buffer_size, &queue, &queue_float, &internal_finished]() { while (true) { - float* oal_buffer = nullptr; - queue.Pop(oal_buffer); + s16* oal_buffer = nullptr; + float* oal_buffer_float = nullptr; + + if (g_is_u16) + queue.Pop(oal_buffer); + + queue_float.Pop(oal_buffer_float); - if (oal_buffer) + if (g_is_u16) { - m_audio_out->AddData(oal_buffer, oal_buffer_size * sizeof(float)); + if (oal_buffer) + { + m_audio_out->AddData(oal_buffer, oal_buffer_size * sizeof(s16)); + } + else + { + internal_finished = true; + return; + } } + else { - internal_finished = true; - return; + if (oal_buffer_float) + { + m_audio_out->AddData(oal_buffer_float, oal_buffer_size * sizeof(float)); + } + else + { + internal_finished = true; + return; + } } } }); @@ -119,6 +158,7 @@ int cellAudioInit() m_config.counter++; const u32 oal_pos = m_config.counter % (sizeof(oal_buffer) / sizeof(oal_buffer[0])); + const u32 oal_pos_float = m_config.counter % (sizeof(oal_buffer_float) / sizeof(oal_buffer_float[0])); if (Emu.IsPaused()) { @@ -299,38 +339,45 @@ int cellAudioInit() // convert the data from float to u16 with clipping: if (!first_mix) { - +#ifndef _M_X64 for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++) { - // Probably, use later? - /* - // for x86 - //oal_buffer[oal_pos][oal_buffer_offset + i] = (s16)(min(max(buf2ch[i] * 0x8000, -0x8000), 0x7fff)); + if (g_is_u16) + oal_buffer[oal_pos][oal_buffer_offset + i] = (s16)(min(max(buf2ch[i] * 0x8000, -0x8000), 0x7fff)); + + oal_buffer_float[oal_pos_float][oal_buffer_offset + i] = buf2ch[i]; + } +#else + // 2x MULPS + // 2x MAXPS (optional) + // 2x MINPS (optional) + // 2x CVTPS2DQ (converts float to s32) + // PACKSSDW (converts s32 to s16 with clipping) - // for x64 - // 2x MULPS - // 2x MAXPS (optional) - // 2x MINPS (optional) - // 2x CVTPS2DQ (converts float to s32) - // PACKSSDW (converts s32 to s16 with clipping) + if (g_is_u16) + { for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 8) { static const __m128 float2u16 = { 0x8000, 0x8000, 0x8000, 0x8000 }; (__m128i&)(oal_buffer[oal_pos][oal_buffer_offset + i]) = _mm_packs_epi32( _mm_cvtps_epi32(_mm_mul_ps((__m128&)(buf2ch[i]), float2u16)), _mm_cvtps_epi32(_mm_mul_ps((__m128&)(buf2ch[i + 4]), float2u16))); - }*/ - - oal_buffer[oal_pos][oal_buffer_offset + i] = buf2ch[i]; + } } + for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++) + { + oal_buffer_float[oal_pos_float][oal_buffer_offset + i] = buf2ch[i]; + } +#endif } const u64 stamp1 = get_system_time(); if (first_mix) { - memset(&oal_buffer[oal_pos][0], 0, oal_buffer_size * sizeof(float)); + memset(&oal_buffer[oal_pos][0], 0, oal_buffer_size * sizeof(s16)); + memset(&oal_buffer_float[oal_pos_float][0], 0, oal_buffer_size * sizeof(float)); } oal_buffer_offset += sizeof(buf2ch) / sizeof(float); @@ -338,7 +385,10 @@ int cellAudioInit() { if(m_audio_out) { - queue.Push(&oal_buffer[oal_pos][0]); + if (g_is_u16) + queue.Push(&oal_buffer[oal_pos][0]); + + queue_float.Push(&oal_buffer_float[oal_pos_float][0]); } oal_buffer_offset = 0; @@ -405,6 +455,7 @@ int cellAudioInit() ConLog.Write("Audio finished"); abort: queue.Push(nullptr); + queue_float.Push(nullptr); if(do_dump) m_dump.Finalize(); diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 6b5d46f1d4..688835f4c7 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -372,9 +372,10 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log vertex/fragment programs"); wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write Depth Buffer"); wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write Color Buffers"); - wxCheckBox* chbox_skip_pamf = new wxCheckBox(p_graphics, wxID_ANY, "Skip Pamf"); + wxCheckBox* chbox_skip_pamf = new wxCheckBox(p_graphics, wxID_ANY, "Skip Pamf"); wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync"); 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_hle_logging = new wxCheckBox(p_hle, wxID_ANY, "Log all SysCalls"); wxCheckBox* chbox_hle_hook_stfunc = new wxCheckBox(p_hle, wxID_ANY, "Hook static functions"); wxCheckBox* chbox_hle_savetty = new wxCheckBox(p_hle, wxID_ANY, "Save TTY output to file"); @@ -452,6 +453,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) chbox_skip_pamf ->SetValue(Ini.SkipPamf.GetValue()); chbox_gs_vsync ->SetValue(Ini.GSVSyncEnable.GetValue()); chbox_audio_dump ->SetValue(Ini.AudioDumpToFile.GetValue()); + chbox_audio_conv ->SetValue(Ini.AudioConvertToU16.GetValue()); chbox_hle_logging ->SetValue(Ini.HLELogging.GetValue()); chbox_hle_hook_stfunc ->SetValue(Ini.HLEHookStFunc.GetValue()); chbox_hle_savetty ->SetValue(Ini.HLESaveTTY.GetValue()); @@ -473,6 +475,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) // Enable / Disable parameters chbox_audio_dump->Enable(Emu.IsStopped()); + chbox_audio_conv->Enable(Emu.IsStopped()); chbox_hle_logging->Enable(Emu.IsStopped()); chbox_hle_hook_stfunc->Enable(Emu.IsStopped()); @@ -517,6 +520,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) // Audio 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()); // HLE / Misc. s_subpanel_hle->Add(s_round_hle_log_lvl, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -563,6 +567,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) Ini.MouseHandlerMode.SetValue(cbox_mouse_handler->GetSelection()); Ini.AudioOutMode.SetValue(cbox_audio_out->GetSelection()); Ini.AudioDumpToFile.SetValue(chbox_audio_dump->GetValue()); + Ini.AudioConvertToU16.SetValue(chbox_audio_conv->GetValue()); Ini.HLELogging.SetValue(chbox_hle_logging->GetValue()); Ini.HLEHookStFunc.SetValue(chbox_hle_hook_stfunc->GetValue()); Ini.HLESaveTTY.SetValue(chbox_hle_savetty->GetValue()); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index aa3263667f..1d9044bac4 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -111,6 +111,7 @@ public: IniEntry MouseHandlerMode; IniEntry AudioOutMode; IniEntry AudioDumpToFile; + IniEntry AudioConvertToU16; IniEntry HLELogging; IniEntry HLEHookStFunc; IniEntry HLESaveTTY; @@ -200,6 +201,7 @@ public: path = DefPath + "/" + "Audio"; AudioOutMode.Init("AudioOutMode", path); AudioDumpToFile.Init("AudioDumpToFile", path); + AudioConvertToU16.Init("AudioConvertToU16", path); path = DefPath + "/" + "HLE"; HLELogging.Init("HLELogging", path); @@ -230,7 +232,8 @@ public: KeyboardHandlerMode.Load(0); MouseHandlerMode.Load(0); AudioOutMode.Load(1); - AudioDumpToFile.Load(0); + AudioDumpToFile.Load(false); + AudioConvertToU16.Load(false); HLELogging.Load(false); HLEHookStFunc.Load(false); HLESaveTTY.Load(false); @@ -283,6 +286,7 @@ public: MouseHandlerMode.Save(); AudioOutMode.Save(); AudioDumpToFile.Save(); + AudioConvertToU16.Save(); HLELogging.Save(); HLEHookStFunc.Save(); HLESaveTTY.Save();