diff --git a/3rdparty/cubeb/include/cubeb_export.h b/3rdparty/cubeb/include/cubeb_export.h index a049dacf71..dda45aca22 100644 --- a/3rdparty/cubeb/include/cubeb_export.h +++ b/3rdparty/cubeb/include/cubeb_export.h @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2020 PCSX2 Dev Team + * Copyright (C) 2002-2021 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- diff --git a/cmake/BuildParameters.cmake b/cmake/BuildParameters.cmake index a1ca1e10bd..519dee37d4 100644 --- a/cmake/BuildParameters.cmake +++ b/cmake/BuildParameters.cmake @@ -46,9 +46,8 @@ option(PACKAGE_MODE "Use this option to ease packaging of PCSX2 (developer/distr option(DISABLE_PCSX2_WRAPPER "Disable including the PCSX2-linux.sh file") option(DISABLE_SETCAP "Do not set files capabilities") option(XDG_STD "Use XDG standard path instead of the standard PCSX2 path") -option(PORTAUDIO_API "Build portaudio support on SPU2" ON) option(CUBEB_API "Build Cubeb support on SPU2" ON) -option(SDL2_API "Use SDL2 on SPU2 and PAD Linux (wxWidget mustn't be built with SDL1.2 support" ON) +option(SDL2_API "Use SDL2 on PAD Linux (wxWidget mustn't be built with SDL1.2 support" ON) option(GTK2_API "Use GTK2 api (legacy)") if(UNIX AND NOT APPLE) diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index cbe8670db3..850c92575c 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -12,7 +12,6 @@ if (WIN32) add_subdirectory(3rdparty/libsamplerate EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/baseclasses EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/freetype EXCLUDE_FROM_ALL) - add_subdirectory(3rdparty/portaudio EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/pthreads4w EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/soundtouch EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/wil EXCLUDE_FROM_ALL) @@ -144,9 +143,6 @@ else() endif() endif() - if(PORTAUDIO_API) - check_lib(PORTAUDIO portaudio portaudio.h pa_linux_alsa.h) - endif() check_lib(SOUNDTOUCH SoundTouch SoundTouch.h PATH_SUFFIXES soundtouch) check_lib(SAMPLERATE samplerate samplerate.h) diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 2d52c4bcb0..337f0cf11f 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -51,11 +51,6 @@ elseif("${PGO}" STREQUAL "use") target_compile_options(PCSX2_FLAGS INTERFACE -fprofile-use) endif() -if(TARGET PkgConfig::PORTAUDIO) - target_compile_definitions(PCSX2_FLAGS INTERFACE SPU2X_PORTAUDIO) - target_link_libraries(PCSX2_FLAGS INTERFACE PkgConfig::PORTAUDIO) -endif() - if(TARGET PulseAudio::PulseAudio) target_compile_definitions(PCSX2_FLAGS INTERFACE SPU2X_PULSEAUDIO) target_link_libraries(PCSX2_FLAGS INTERFACE PulseAudio::PulseAudio) @@ -293,17 +288,12 @@ set(pcsx2SPU2Sources SPU2/RegTable.cpp SPU2/Reverb.cpp SPU2/SndOut.cpp - SPU2/SndOut_SDL.cpp SPU2/spu2freeze.cpp SPU2/spu2sys.cpp SPU2/Timestretcher.cpp SPU2/Wavedump_wav.cpp ) -if(TARGET PkgConfig::PORTAUDIO) - list(APPEND pcsx2SPU2Sources SPU2/SndOut_Portaudio.cpp) -endif() - if(CUBEB_API) list(APPEND pcsx2SPU2Sources SPU2/SndOut_Cubeb.cpp) target_compile_definitions(PCSX2_FLAGS INTERFACE "SPU2X_CUBEB") diff --git a/pcsx2/SPU2/Linux/Config.cpp b/pcsx2/SPU2/Linux/Config.cpp index 9b149e9492..4784d059a8 100644 --- a/pcsx2/SPU2/Linux/Config.cpp +++ b/pcsx2/SPU2/Linux/Config.cpp @@ -64,10 +64,6 @@ bool _visual_debug_enabled = false; // Windows-only feature u32 OutputModule = 0; int SndOutLatencyMS = 100; int SynchMode = 0; // Time Stretch, Async or Disabled. -#ifdef SPU2X_PORTAUDIO -u32 OutputAPI = 0; -#endif -u32 SdlOutputAPI = 0; int numSpeakers = 0; int dplLevel = 0; @@ -105,54 +101,20 @@ void ReadSettings() VolumeAdjustSR = powf(10, VolumeAdjustSRdb / 10); VolumeAdjustLFE = powf(10, VolumeAdjustLFEdb / 10); +#ifdef SPU2X_CUBEB + const SndOutModule* const defaultModule = CubebOut; +#else + const SndOutModule* const defaultModule = NullOut; +#endif + wxString temp; - -#if SDL_MAJOR_VERSION >= 2 || !defined(SPU2X_PORTAUDIO) - CfgReadStr(L"OUTPUT", L"Output_Module", temp, SDLOut->GetIdent()); -#else - CfgReadStr(L"OUTPUT", L"Output_Module", temp, PortaudioOut->GetIdent()); -#endif + CfgReadStr(L"OUTPUT", L"Output_Module", temp, defaultModule->GetIdent()); OutputModule = FindOutputModuleById(temp.c_str()); // Find the driver index of this module... -// Find current API. -#ifdef SPU2X_PORTAUDIO -#ifdef __linux__ - CfgReadStr(L"PORTAUDIO", L"HostApi", temp, L"ALSA"); - if (temp == L"OSS") - OutputAPI = 1; - else if (temp == L"JACK") - OutputAPI = 2; - else // L"ALSA" - OutputAPI = 0; -#else - CfgReadStr(L"PORTAUDIO", L"HostApi", temp, L"OSS"); - OutputAPI = 0; // L"OSS" -#endif -#endif - -#if defined(__unix__) || defined(__APPLE__) - CfgReadStr(L"SDL", L"HostApi", temp, L"pulseaudio"); - SdlOutputAPI = 0; -#if SDL_MAJOR_VERSION >= 2 - // Yes, it sucks ... - for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) - { - if (!temp.Cmp(wxString(SDL_GetAudioDriver(i), wxConvUTF8))) - SdlOutputAPI = i; - } -#endif -#endif - SndOutLatencyMS = CfgReadInt(L"OUTPUT", L"Latency", 100); SynchMode = CfgReadInt(L"OUTPUT", L"Synch_Mode", 0); numSpeakers = CfgReadInt(L"OUTPUT", L"SpeakerConfiguration", 0); -#ifdef SPU2X_PORTAUDIO - PortaudioOut->ReadSettings(); -#endif -#if defined(__unix__) || defined(__APPLE__) - SDLOut->ReadSettings(); -#endif SoundtouchCfg::ReadSettings(); DebugConfig::ReadSettings(); @@ -164,8 +126,8 @@ void ReadSettings() if (mods[OutputModule] == nullptr) { Console.Warning("* SPU2: Unknown output module '%s' specified in configuration file.", temp.wc_str()); - Console.Warning("* SPU2: Defaulting to SDL (%s).", SDLOut->GetIdent()); - OutputModule = FindOutputModuleById(SDLOut->GetIdent()); + Console.Warning("* SPU2: Defaulting to %s (%s).", defaultModule->GetLongName(), defaultModule->GetIdent()); + OutputModule = FindOutputModuleById(defaultModule->GetIdent()); } WriteSettings(); @@ -200,12 +162,6 @@ void WriteSettings() CfgWriteInt(L"OUTPUT", L"Synch_Mode", SynchMode); CfgWriteInt(L"OUTPUT", L"SpeakerConfiguration", numSpeakers); -#ifdef SPU2X_PORTAUDIO - PortaudioOut->WriteSettings(); -#endif -#if defined(__unix__) || defined(__APPLE__) - SDLOut->WriteSettings(); -#endif SoundtouchCfg::WriteSettings(); DebugConfig::WriteSettings(); } diff --git a/pcsx2/SPU2/Linux/Config.h b/pcsx2/SPU2/Linux/Config.h index aa080fc9cd..3bac2dcd7d 100644 --- a/pcsx2/SPU2/Linux/Config.h +++ b/pcsx2/SPU2/Linux/Config.h @@ -78,11 +78,6 @@ extern int dspPluginModule; extern bool dspPluginEnabled; extern int SynchMode; -#ifdef SPU2X_PORTAUDIO -extern u32 OutputAPI; -#endif -extern u32 SdlOutputAPI; - #ifdef PCSX2_DEVBUILD const int LATENCY_MAX = 3000; #else diff --git a/pcsx2/SPU2/SndOut.cpp b/pcsx2/SPU2/SndOut.cpp index e92615d68b..de76481c86 100644 --- a/pcsx2/SPU2/SndOut.cpp +++ b/pcsx2/SPU2/SndOut.cpp @@ -49,50 +49,47 @@ StereoOut32 StereoOut16::UpSample() const class NullOutModule : public SndOutModule { public: - s32 Init() { return 0; } - void Close() {} - s32 Test() const { return 0; } - void Configure(uptr parent) {} - int GetEmptySampleCount() { return 0; } + s32 Init() override { return 0; } + void Close() override {} + s32 Test() const override { return 0; } + void Configure(uptr parent) override {} + int GetEmptySampleCount() override { return 0; } - const wchar_t* GetIdent() const + const wchar_t* GetIdent() const override { return L"nullout"; } - const wchar_t* GetLongName() const + const wchar_t* GetLongName() const override { return L"No Sound (Emulate SPU2 only)"; } - void ReadSettings() + void ReadSettings() override { } - void SetApiSettings(wxString api) + void SetApiSettings(wxString api) override { } - void WriteSettings() const + void WriteSettings() const override { } -} NullOut; +}; + +static NullOutModule s_NullOut; +SndOutModule* NullOut = &s_NullOut; SndOutModule* mods[] = { - &NullOut, -#ifdef _MSC_VER + NullOut, +#ifdef _WIN32 XAudio2Out, #endif -#if defined(SPU2X_PORTAUDIO) - PortaudioOut, -#endif #if defined(SPU2X_CUBEB) CubebOut, -#endif -#if defined(__linux__) || defined(__APPLE__) - SDLOut, #endif nullptr // signals the end of our list }; @@ -169,7 +166,7 @@ void SndBuffer::_InitFail() { // If a failure occurs, just initialize the NoSound driver. This'll allow // the game to emulate properly (hopefully), albeit without sound. - OutputModule = FindOutputModuleById(NullOut.GetIdent()); + OutputModule = FindOutputModuleById(NullOut->GetIdent()); mods[OutputModule]->Init(); } @@ -447,7 +444,7 @@ void SndBuffer::Write(const StereoOut32& Sample) if (WavRecordEnabled) RecordWrite(Sample.DownSample()); - if (mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p + if (mods[OutputModule] == NullOut) // null output doesn't need buffering or stretching! :p return; sndTempBuffer[sndTempProgress++] = Sample; @@ -464,7 +461,7 @@ void SndBuffer::Write(const StereoOut32& Sample) // Play silence std::fill_n(sndTempBuffer, SndOutPacketSize, StereoOut32{}); } -#ifndef __POSIX__ +#if defined(_WIN32) && !defined(PCSX2_CORE) if (dspPluginEnabled) { // Convert in, send to winamp DSP, and convert out. diff --git a/pcsx2/SPU2/SndOut.h b/pcsx2/SPU2/SndOut.h index 66066b0e14..09377b765e 100644 --- a/pcsx2/SPU2/SndOut.h +++ b/pcsx2/SPU2/SndOut.h @@ -663,17 +663,13 @@ public: virtual int GetEmptySampleCount() = 0; }; -#ifdef _MSC_VER -//internal +extern SndOutModule* NullOut; +#ifdef _WIN32 extern SndOutModule* XAudio2Out; #endif -#if defined(SPU2X_PORTAUDIO) -extern SndOutModule* PortaudioOut; -#endif #if defined(SPU2X_CUBEB) extern SndOutModule* CubebOut; #endif -extern SndOutModule* const SDLOut; extern SndOutModule* mods[]; // ===================================================================================================== diff --git a/pcsx2/SPU2/SndOut_Portaudio.cpp b/pcsx2/SPU2/SndOut_Portaudio.cpp deleted file mode 100644 index fb4ef75e61..0000000000 --- a/pcsx2/SPU2/SndOut_Portaudio.cpp +++ /dev/null @@ -1,757 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2021 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" -//#include "Mixer.h" -#include "Global.h" -#include "SndOut.h" - -#define _WIN32_DCOM -#ifdef _WIN32 -#include -#include "Windows/Dialogs.h" -#elif defined(__linux__) || defined(__APPLE__) -#include "portaudio.h" -#include "Linux/Dialogs.h" -#endif - - - -#include "wchar.h" - -#include - -#ifdef _WIN32 -#include -#endif -#include "Debug.h" - -int PaCallback(const void* inputBuffer, void* outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void* userData); - -class Portaudio : public SndOutModule -{ -private: - ////////////////////////////////////////////////////////////////////////////////////////// - // Configuration Vars (unused still) - - int m_ApiId; - wxString m_Device; - - bool m_UseHardware; - - bool m_WasapiExclusiveMode; - - bool m_SuggestedLatencyMinimal; - int m_SuggestedLatencyMS; - - ////////////////////////////////////////////////////////////////////////////////////////// - // Instance vars - - int writtenSoFar; - int writtenLastTime; - int availableLastTime; - - int actualUsedChannels; - - bool started; - PaStream* stream; - - ////////////////////////////////////////////////////////////////////////////////////////// - // Stuff necessary for speaker expansion - class SampleReader - { - public: - virtual int ReadSamples(const void* inputBuffer, void* outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void* userData) = 0; - }; - - template - class ConvertedSampleReader : public SampleReader - { - int* written; - - public: - ConvertedSampleReader(int* pWritten) - { - written = pWritten; - } - - virtual int ReadSamples(const void* inputBuffer, void* outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void* userData) - { - T* p1 = (T*)outputBuffer; - - int packets = framesPerBuffer / SndOutPacketSize; - - for (int p = 0; p < packets; p++, p1 += SndOutPacketSize) - SndBuffer::ReadSamples(p1); - - (*written) += packets * SndOutPacketSize; - - return 0; - } - }; - -public: - SampleReader* ActualPaCallback; - - Portaudio() - { - m_SuggestedLatencyMinimal = true; - m_UseHardware = false; - m_WasapiExclusiveMode = false; - started = false; - stream = nullptr; - ActualPaCallback = nullptr; - m_ApiId = -1; - m_SuggestedLatencyMS = 20; - actualUsedChannels = 0; - writtenSoFar = 0; - writtenLastTime = 0; - availableLastTime = 0; - } - - s32 Init() - { - started = false; - stream = nullptr; - - ReadSettings(); - - PaError err = Pa_Initialize(); - if (err != paNoError) - { - fprintf(stderr, "* SPU2: PortAudio error: %s\n", Pa_GetErrorText(err)); - return -1; - } - started = true; - - int deviceIndex = -1; - - fprintf(stderr, "* SPU2: Enumerating PortAudio devices:\n"); - for (int i = 0, j = 0; i < Pa_GetDeviceCount(); i++) - { - const PaDeviceInfo* info = Pa_GetDeviceInfo(i); - - if (info->maxOutputChannels > 0) - { - const PaHostApiInfo* apiinfo = Pa_GetHostApiInfo(info->hostApi); - - fprintf(stderr, " *** Device %d: '%s' (%s)", j, info->name, apiinfo->name); - - if (apiinfo->type == m_ApiId) - { - if (m_Device == wxString::FromUTF8(info->name)) - { - deviceIndex = i; - fprintf(stderr, " (selected)"); - } - } - fprintf(stderr, "\n"); - - j++; - } - } - fflush(stderr); - - if (deviceIndex < 0 && m_ApiId >= 0) - { - for (int i = 0; i < Pa_GetHostApiCount(); i++) - { - const PaHostApiInfo* apiinfo = Pa_GetHostApiInfo(i); - if (apiinfo->type == m_ApiId) - { - deviceIndex = apiinfo->defaultOutputDevice; - } - } - } - - if (deviceIndex >= 0) - { - void* infoPtr = nullptr; - - const PaDeviceInfo* devinfo = Pa_GetDeviceInfo(deviceIndex); - - int speakers; - switch (numSpeakers) // speakers = (numSpeakers + 1) *2; ? - { - case 0: - speakers = 2; - break; // Stereo - case 1: - speakers = 4; - break; // Quadrafonic - case 2: - speakers = 6; - break; // Surround 5.1 - case 3: - speakers = 8; - break; // Surround 7.1 - default: - speakers = 2; - } - actualUsedChannels = std::min(speakers, devinfo->maxOutputChannels); - - switch (actualUsedChannels) - { - case 2: - ConLog("* SPU2 > Using normal 2 speaker stereo output.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); - break; - - case 3: - ConLog("* SPU2 > 2.1 speaker expansion enabled.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); - break; - - case 4: - ConLog("* SPU2 > 4 speaker expansion enabled [quadraphenia]\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); - break; - - case 5: - ConLog("* SPU2 > 4.1 speaker expansion enabled.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); - break; - - case 6: - case 7: - switch (dplLevel) - { - case 0: - ConLog("* SPU2 > 5.1 speaker expansion enabled.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); //"normal" stereo upmix - break; - case 1: - ConLog("* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); // basic Dpl decoder without rear stereo balancing - break; - case 2: - ConLog("* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); //gigas PLII - break; - } - actualUsedChannels = 6; // we do not support 7.0 or 6.2 configurations, downgrade to 5.1 - break; - - default: // anything 8 or more gets the 7.1 treatment! - ConLog("* SPU2 > 7.1 speaker expansion enabled.\n"); - ActualPaCallback = new ConvertedSampleReader(&writtenSoFar); - actualUsedChannels = 8; // we do not support 7.2 or more, downgrade to 7.1 - break; - } - -#ifdef _WIN32 - PaWasapiStreamInfo info = { - sizeof(PaWasapiStreamInfo), - paWASAPI, - 1, - paWinWasapiExclusive}; - - if ((m_ApiId == paWASAPI) && m_WasapiExclusiveMode) - { - // Pass it the Exclusive mode enable flag - infoPtr = &info; - } -#endif - - PaStreamParameters outParams = { - - // PaDeviceIndex device; - // int channelCount; - // PaSampleFormat sampleFormat; - // PaTime suggestedLatency; - // void *hostApiSpecificStreamInfo; - deviceIndex, - actualUsedChannels, - paInt32, - m_SuggestedLatencyMinimal ? (SndOutPacketSize / (float)SampleRate) : (m_SuggestedLatencyMS / 1000.0f), - infoPtr}; - - err = Pa_OpenStream(&stream, - nullptr, &outParams, SampleRate, - SndOutPacketSize, - paNoFlag, - PaCallback, - - nullptr); - - if (err == paInvalidSampleRate && SampleRate == 48000) - { - DevCon.Warning("Failed to create device at 48khz, trying 96khz"); - SampleRate = 96000; - err = Pa_OpenStream(&stream, - nullptr, &outParams, SampleRate, - SndOutPacketSize, - paNoFlag, - PaCallback, - - nullptr); - } - - if (err == paInvalidSampleRate && SampleRate == 96000) // It didn't work, so lets just put the samplerate back - SampleRate = 48000; - } - else - { - err = Pa_OpenDefaultStream(&stream, - 0, actualUsedChannels, paInt32, 48000, - SndOutPacketSize, - PaCallback, - nullptr); - } - if (err != paNoError) - { - if (err == paInvalidSampleRate) - Console.Warning("Failed to create Port Audio Device %dkhz, Please use Exclusive Mode", SampleRate / 1000); - fprintf(stderr, "* SPU2: PortAudio error: %s\n", Pa_GetErrorText(err)); - Pa_Terminate(); - return -1; - } - - err = Pa_StartStream(stream); - if (err != paNoError) - { - fprintf(stderr, "* SPU2: PortAudio error: %s\n", Pa_GetErrorText(err)); - Pa_CloseStream(stream); - stream = nullptr; - Pa_Terminate(); - return -1; - } - - return 0; - } - - void Close() - { - PaError err; - if (started) - { - if (stream) - { - if (Pa_IsStreamActive(stream)) - { - err = Pa_StopStream(stream); - if (err != paNoError) - fprintf(stderr, "* SPU2: PortAudio error: %s\n", Pa_GetErrorText(err)); - } - - err = Pa_CloseStream(stream); - if (err != paNoError) - fprintf(stderr, "* SPU2: PortAudio error: %s\n", Pa_GetErrorText(err)); - - stream = nullptr; - } - - PaError err = Pa_Terminate(); - if( err != paNoError ) - fprintf(stderr,"* SPU2: PortAudio error: %s\n", Pa_GetErrorText( err ) ); - - started = false; - } - } - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -#ifdef _WIN32 -private: - bool _ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - int wmId, wmEvent; - int tSel = 0; - - switch (uMsg) - { - case WM_INITDIALOG: - { - wchar_t temp[128]; - - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_RESETCONTENT, 0, 0); - SendMessageA(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM) "Default Device"); - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETCURSEL, 0, 0); - - SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_RESETCONTENT, 0, 0); - SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_ADDSTRING, 0, (LPARAM) "Unspecified"); - int idx = 0; - for (int i = 0; i < Pa_GetHostApiCount(); i++) - { - const PaHostApiInfo* apiinfo = Pa_GetHostApiInfo(i); - if (apiinfo->deviceCount > 0) - { - SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_ADDSTRING, 0, (LPARAM)apiinfo->name); - SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_SETITEMDATA, i + 1, apiinfo->type); - } - if (apiinfo->type == m_ApiId) - { - idx = i + 1; - } - } - SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_SETCURSEL, idx, 0); - - if (idx > 0) - { - int api_idx = idx - 1; - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_RESETCONTENT, 0, 0); - SendMessageA(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM) "Default Device"); - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, 0, 0); - int _idx = 0; - int i = 1; - for (int j = 0; j < Pa_GetDeviceCount(); j++) - { - const PaDeviceInfo* info = Pa_GetDeviceInfo(j); - if (info->hostApi == api_idx && info->maxOutputChannels > 0) - { - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM)wxString::FromUTF8(info->name).wc_str()); - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, i, (LPARAM)info); - if (wxString::FromUTF8(info->name) == m_Device) - { - _idx = i; - } - i++; - } - } - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETCURSEL, _idx, 0); - } - - INIT_SLIDER(IDC_LATENCY, 10, 200, 10, 1, 1); - SendMessage(GetDlgItem(hWnd, IDC_LATENCY), TBM_SETPOS, TRUE, m_SuggestedLatencyMS); - swprintf_s(temp, L"%d ms", m_SuggestedLatencyMS); - SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp); - - if (m_SuggestedLatencyMinimal) - SET_CHECK(IDC_MINIMIZE, true); - else - SET_CHECK(IDC_MANUAL, true); - - SET_CHECK(IDC_EXCLUSIVE, m_WasapiExclusiveMode); - } - break; - - case WM_COMMAND: - { - //wchar_t temp[128]; - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - // Parse the menu selections: - switch (wmId) - { - case IDOK: - { - int idx = (int)SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETCURSEL, 0, 0); - m_ApiId = SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETITEMDATA, idx, 0); - - idx = (int)SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_GETCURSEL, 0, 0); - const PaDeviceInfo* info = (const PaDeviceInfo*)SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_GETITEMDATA, idx, 0); - if (info) - m_Device = wxString::FromUTF8(info->name); - else - m_Device = L"default"; - - m_SuggestedLatencyMS = (int)SendMessage(GetDlgItem(hWnd, IDC_LATENCY), TBM_GETPOS, 0, 0); - - if (m_SuggestedLatencyMS < 10) - m_SuggestedLatencyMS = 10; - if (m_SuggestedLatencyMS > 200) - m_SuggestedLatencyMS = 200; - - m_SuggestedLatencyMinimal = SendMessage(GetDlgItem(hWnd, IDC_MINIMIZE), BM_GETCHECK, 0, 0) == BST_CHECKED; - - m_WasapiExclusiveMode = SendMessage(GetDlgItem(hWnd, IDC_EXCLUSIVE), BM_GETCHECK, 0, 0) == BST_CHECKED; - - EndDialog(hWnd, 0); - } - break; - - case IDCANCEL: - EndDialog(hWnd, 0); - break; - - case IDC_PA_HOSTAPI: - { - if (wmEvent == CBN_SELCHANGE) - { - int api_idx = (int)SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETCURSEL, 0, 0) - 1; - int apiId = SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETITEMDATA, api_idx, 0); - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_RESETCONTENT, 0, 0); - SendMessageA(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM) "Default Device"); - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, 0, 0); - int idx = 0; - int i = 1; - for (int j = 0; j < Pa_GetDeviceCount(); j++) - { - const PaDeviceInfo* info = Pa_GetDeviceInfo(j); - if (info->hostApi == api_idx && info->maxOutputChannels > 0) - { - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM)wxString::FromUTF8(info->name).wc_str()); - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, i, (LPARAM)info); - i++; - } - } - SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETCURSEL, idx, 0); - } - } - break; - - default: - return FALSE; - } - } - break; - - case WM_HSCROLL: - { - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - switch (wmId) - { - case TB_LINEUP: - case TB_LINEDOWN: - case TB_PAGEUP: - case TB_PAGEDOWN: - case TB_TOP: - case TB_BOTTOM: - wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0); - case TB_THUMBPOSITION: - case TB_THUMBTRACK: - { - wchar_t temp[128]; - if (wmEvent < 10) - wmEvent = 10; - if (wmEvent > 200) - wmEvent = 200; - SendMessage((HWND)lParam, TBM_SETPOS, TRUE, wmEvent); - swprintf_s(temp, L"%d ms", wmEvent); - SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp); - break; - } - default: - return FALSE; - } - } - break; - - default: - return FALSE; - } - return TRUE; - } - - static BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext); - -public: - virtual void Configure(uptr parent) - { - PaError err = Pa_Initialize(); // Initialization can be done multiple times, PA keeps a counter - if (err != paNoError) - { - fprintf(stderr, "* SPU2: PortAudio error: %s\n", Pa_GetErrorText(err)); - return; - } - // keep portaudio initialized until the dialog closes - - INT_PTR ret; - ret = DialogBoxParam(nullptr, MAKEINTRESOURCE(IDD_PORTAUDIO), (HWND)parent, (DLGPROC)ConfigProc, 1); - if (ret == -1) - { - MessageBox((HWND)parent, L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND); - return; - } - - Pa_Terminate(); - } -#else - virtual void Configure(uptr parent) - { - } -#endif - - s32 Test() const - { - return 0; - } - - int GetEmptySampleCount() - { - long availableNow = Pa_GetStreamWriteAvailable(stream); - - int playedSinceLastTime = (writtenSoFar - writtenLastTime) + (availableNow - availableLastTime); - writtenLastTime = writtenSoFar; - availableLastTime = availableNow; - - // Lowest resolution here is the SndOutPacketSize we use. - return playedSinceLastTime; - } - - const wchar_t* GetIdent() const - { - return L"portaudio"; - } - - const wchar_t* GetLongName() const - { - return L"PortAudio (Cross-platform)"; - } - - void ReadSettings() - { - wxString api(L"EMPTYEMPTYEMPTY"); - m_Device = L"EMPTYEMPTYEMPTY"; -#ifdef __linux__ - // By default on linux use the ALSA API (+99% users) -- Gregory - CfgReadStr(L"PORTAUDIO", L"HostApi", api, L"ALSA"); -#elif defined(__APPLE__) - // Suppose OSX only has CoreAudio... - CfgReadStr(L"PORTAUDIO", L"HostApi", api, L"CoreAudio"); -#else - CfgReadStr(L"PORTAUDIO", L"HostApi", api, L"WASAPI"); -#endif - CfgReadStr(L"PORTAUDIO", L"Device", m_Device, L"default"); - - SetApiSettings(api); - - m_WasapiExclusiveMode = CfgReadBool(L"PORTAUDIO", L"Wasapi_Exclusive_Mode", false); - m_SuggestedLatencyMinimal = CfgReadBool(L"PORTAUDIO", L"Minimal_Suggested_Latency", true); - m_SuggestedLatencyMS = CfgReadInt(L"PORTAUDIO", L"Manual_Suggested_Latency_MS", 20); - - if (m_SuggestedLatencyMS < 10) - m_SuggestedLatencyMS = 10; - if (m_SuggestedLatencyMS > 200) - m_SuggestedLatencyMS = 200; - } - - void SetApiSettings(wxString api) - { - m_ApiId = -1; - if (api == L"InDevelopment") - m_ApiId = paInDevelopment; /* use while developing support for a new host API */ - if (api == L"DirectSound") - m_ApiId = paDirectSound; - if (api == L"MME") - m_ApiId = paMME; - if (api == L"ASIO") - m_ApiId = paASIO; - if (api == L"SoundManager") - m_ApiId = paSoundManager; - if (api == L"CoreAudio") - m_ApiId = paCoreAudio; - if (api == L"OSS") - m_ApiId = paOSS; - if (api == L"ALSA") - m_ApiId = paALSA; - if (api == L"AL") - m_ApiId = paAL; - if (api == L"BeOS") - m_ApiId = paBeOS; - if (api == L"WDMKS") - m_ApiId = paWDMKS; - if (api == L"JACK") - m_ApiId = paJACK; - if (api == L"WASAPI") - m_ApiId = paWASAPI; - if (api == L"AudioScienceHPI") - m_ApiId = paAudioScienceHPI; - } - - void WriteSettings() const - { - wxString api; - switch (m_ApiId) - { - case paInDevelopment: - api = L"InDevelopment"; - break; /* use while developing support for a new host API */ - case paDirectSound: - api = L"DirectSound"; - break; - case paMME: - api = L"MME"; - break; - case paASIO: - api = L"ASIO"; - break; - case paSoundManager: - api = L"SoundManager"; - break; - case paCoreAudio: - api = L"CoreAudio"; - break; - case paOSS: - api = L"OSS"; - break; - case paALSA: - api = L"ALSA"; - break; - case paAL: - api = L"AL"; - break; - case paBeOS: - api = L"BeOS"; - break; - case paWDMKS: - api = L"WDMKS"; - break; - case paJACK: - api = L"JACK"; - break; - case paWASAPI: - api = L"WASAPI"; - break; - case paAudioScienceHPI: - api = L"AudioScienceHPI"; - break; - default: - api = L"Unknown"; - } - - CfgWriteStr(L"PORTAUDIO", L"HostApi", api); - CfgWriteStr(L"PORTAUDIO", L"Device", m_Device); - - CfgWriteBool(L"PORTAUDIO", L"Wasapi_Exclusive_Mode", m_WasapiExclusiveMode); - CfgWriteBool(L"PORTAUDIO", L"Minimal_Suggested_Latency", m_SuggestedLatencyMinimal); - CfgWriteInt(L"PORTAUDIO", L"Manual_Suggested_Latency_MS", m_SuggestedLatencyMS); - } - -} static PA; - -int PaCallback(const void* inputBuffer, void* outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void* userData) -{ - return PA.ActualPaCallback->ReadSamples(inputBuffer, outputBuffer, framesPerBuffer, timeInfo, statusFlags, userData); -} - -#ifdef _WIN32 -BOOL CALLBACK Portaudio::ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return PA._ConfigProc(hWnd, uMsg, wParam, lParam); -} -#endif - -SndOutModule* PortaudioOut = &PA; diff --git a/pcsx2/SPU2/SndOut_SDL.cpp b/pcsx2/SPU2/SndOut_SDL.cpp deleted file mode 100644 index 36f1970751..0000000000 --- a/pcsx2/SPU2/SndOut_SDL.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2021 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - -#ifdef SDL_BUILD - -#include -#include - -#include "Global.h" -#include "SndOut.h" - -#if defined(_WIN32) -#include "Windows/Dialogs.h" -#else // BSD, Macos -#include "Linux/Dialogs.h" -#endif - -#include - -/* Using SDL2 requires other SDL dependencies in pcsx2 get upgraded as well, or the - * symbol tables would conflict. Other dependencies in Linux are wxwidgets (you can - * build wx without sdl support, though) and onepad at the time of writing this. */ -#include -#include -typedef StereoOut16 StereoOut_SDL; - -namespace -{ - /* Since spu2 only ever outputs stereo, we don't worry about emitting surround sound - * even though SDL2 supports it */ - const Uint8 channels = 2; - /* SDL2 supports s32 audio */ - /* Samples should vary from [512,8192] according to SDL spec. Take note this is the desired - * sample count and SDL may provide otherwise. Pulseaudio will cut this value in half if - * PA_STREAM_ADJUST_LATENCY is set in the backened, for example. */ - const Uint16 desiredSamples = 2048; - const Uint16 format = AUDIO_S16SYS; - - Uint16 samples = desiredSamples; - - void callback_fillBuffer(void* userdata, Uint8* stream, int len) - { - StereoOut16* out = (StereoOut16*)stream; - - // Length should always be samples in bytes. - assert(len / sizeof(StereoOut_SDL) == samples); - - for (Uint16 i = 0; i < samples; i += SndOutPacketSize) - SndBuffer::ReadSamples(&out[i]); - } -} // namespace - -struct SDLAudioMod : public SndOutModule -{ - static SDLAudioMod mod; - std::string m_api; - - s32 Init() - { - ReadSettings(); - -#if SDL_MAJOR_VERSION >= 2 - std::cerr << "Request SDL audio driver: " << m_api.c_str() << std::endl; -#endif - - /* SDL backends will mangle the AudioSpec and change the sample count. If we reopen - * the audio backend, we need to make sure we keep our desired samples in the spec */ - spec.samples = desiredSamples; - - // Mandatory otherwise, init will be redone in SDL_OpenAudio - if (SDL_Init(SDL_INIT_AUDIO) < 0) - { - std::cerr << "SPU2: SDL INIT audio error: " << SDL_GetError() << std::endl; - return -1; - } - -#if SDL_MAJOR_VERSION >= 2 - if (m_api.compare("pulseaudio")) - { - // Close the audio, but keep the subsystem open - SDL_AudioQuit(); - // Reopen the audio - if (SDL_AudioInit(m_api.c_str()) < 0) - { - std::cerr << "SPU2: SDL audio init error: " << SDL_GetError() << std::endl; - return -1; - } - } -#endif - - if (SDL_OpenAudio(&spec, nullptr) < 0) - { - std::cerr << "SPU2: SDL audio error: " << SDL_GetError() << std::endl; - return -1; - } - -#if SDL_MAJOR_VERSION >= 2 - std::cerr << "Opened SDL audio driver: " << SDL_GetCurrentAudioDriver() << std::endl; -#endif - - if (samples != spec.samples) - { - fprintf(stderr, "SPU2: SDL failed to get desired samples (%d) got %d samples instead\n", samples, spec.samples); - - // Samples must always be a multiple of packet size. - assert(spec.samples % SndOutPacketSize == 0); - samples = spec.samples; - } - SDL_PauseAudio(0); - return 0; - } - - const wchar_t* GetIdent() const { return L"SDLAudio"; } - const wchar_t* GetLongName() const { return L"SDL Audio"; } - - void Close() - { - // Related to SDL_Init(SDL_INIT_AUDIO) - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } - - ~SDLAudioMod() { Close(); } - - s32 Test() const { return 0; } - int GetEmptySampleCount() { return 0; } - - void Configure(uptr parent) {} - - void ReadSettings() - { - wxString api(L"EMPTYEMPTYEMPTY"); - CfgReadStr(L"SDL", L"HostApi", api, L"pulseaudio"); - SetApiSettings(api); - } - - void WriteSettings() const - { - CfgWriteStr(L"SDL", L"HostApi", wxString(m_api.c_str(), wxConvUTF8)); - }; - - void SetApiSettings(wxString api) - { -#if SDL_MAJOR_VERSION >= 2 - // Validate the api name - bool valid = false; - std::string api_name = std::string(api.utf8_str()); - for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) - { - valid |= (api_name.compare(SDL_GetAudioDriver(i)) == 0); - } - if (valid) - { - m_api = api.utf8_str(); - } - else - { - std::cerr << "SDL audio driver configuration is invalid!" << std::endl - << "It will be replaced by pulseaudio!" << std::endl; - m_api = "pulseaudio"; - } -#endif - } - - -private: - SDL_AudioSpec spec; - - SDLAudioMod() - : m_api("pulseaudio") - , spec({SampleRate, format, channels, 0, - desiredSamples, 0, 0, &callback_fillBuffer, nullptr}) - { - // Number of samples must be a multiple of packet size. - assert(samples % SndOutPacketSize == 0); - } -}; - -SDLAudioMod SDLAudioMod::mod; - -SndOutModule* const SDLOut = &SDLAudioMod::mod; - -#endif // SDL_BUILD diff --git a/pcsx2/SPU2/Windows/Config.cpp b/pcsx2/SPU2/Windows/Config.cpp index bf46cb3855..7d4e8bff3e 100644 --- a/pcsx2/SPU2/Windows/Config.cpp +++ b/pcsx2/SPU2/Windows/Config.cpp @@ -126,8 +126,6 @@ void ReadSettings() dspPluginModule = CfgReadInt(L"DSP PLUGIN", L"ModuleNum", 0); dspPluginEnabled = CfgReadBool(L"DSP PLUGIN", L"Enabled", false); - PortaudioOut->ReadSettings(); - SoundtouchCfg::ReadSettings(); DebugConfig::ReadSettings(); @@ -173,7 +171,6 @@ void WriteSettings() CfgWriteInt(L"DSP PLUGIN", L"ModuleNum", dspPluginModule); CfgWriteBool(L"DSP PLUGIN", L"Enabled", dspPluginEnabled); - PortaudioOut->WriteSettings(); SoundtouchCfg::WriteSettings(); DebugConfig::WriteSettings(); } @@ -181,16 +178,131 @@ void WriteSettings() void CheckOutputModule(HWND window) { OutputModule = SendMessage(GetDlgItem(window, IDC_OUTPUT), CB_GETCURSEL, 0, 0); - const bool IsConfigurable = mods[OutputModule] == PortaudioOut; + const bool IsConfigurable = mods[OutputModule] == CubebOut; const bool AudioExpansion = mods[OutputModule] == XAudio2Out || - mods[OutputModule] == PortaudioOut; + mods[OutputModule] == CubebOut; EnableWindow(GetDlgItem(window, IDC_OUTCONF), IsConfigurable); EnableWindow(GetDlgItem(window, IDC_SPEAKERS), AudioExpansion); EnableWindow(GetDlgItem(window, IDC_SPEAKERS_TEXT), AudioExpansion); } +static BOOL CALLBACK CubebConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + static constexpr wchar_t* cubeb_backend_names[][2] = { + {L"Unspecified", L""}, + {L"WASAPI", L"wasapi"}, + {L"WinMM", L"winmm"}}; + + const bool minimalLatency = CfgReadBool(L"Cubeb", L"MinimalSuggestedLatency", false); + const int suggestedLatencyMS = CfgReadInt(L"Cubeb", L"ManualSuggestedLatencyMS", 20); + wxString backend; + CfgReadStr(L"Cubeb", L"BackendName", backend, L""); + + SendMessage(GetDlgItem(hWnd, IDC_BACKEND), CB_RESETCONTENT, 0, 0); + + for (size_t i = 0; i < std::size(cubeb_backend_names); i++) + { + SendMessageW(GetDlgItem(hWnd, IDC_BACKEND), CB_ADDSTRING, (WPARAM)i, (LPARAM)cubeb_backend_names[i][0]); + SendMessageW(GetDlgItem(hWnd, IDC_BACKEND), CB_SETITEMDATA, (WPARAM)i, (LPARAM)cubeb_backend_names[i][1]); + if (backend == cubeb_backend_names[i][1]) + SendMessage(GetDlgItem(hWnd, IDC_BACKEND), CB_SETCURSEL, (WPARAM)i, 0); + } + + INIT_SLIDER(IDC_LATENCY, 10, 200, 10, 1, 1); + SendMessage(GetDlgItem(hWnd, IDC_LATENCY), TBM_SETPOS, TRUE, suggestedLatencyMS); + + wchar_t temp[128]; + swprintf_s(temp, L"%d ms", suggestedLatencyMS); + SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp); + + if (minimalLatency) + SET_CHECK(IDC_MINIMIZE, true); + else + SET_CHECK(IDC_MANUAL, true); + + return TRUE; + } + break; + + case WM_COMMAND: + { + const DWORD wmId = LOWORD(wParam); + const DWORD wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDOK: + { + int idx = (int)SendMessage(GetDlgItem(hWnd, IDC_BACKEND), CB_GETCURSEL, 0, 0); + const wchar_t* backend = (const wchar_t*)SendMessage(GetDlgItem(hWnd, IDC_BACKEND), CB_GETITEMDATA, idx, 0); + CfgWriteStr(L"Cubeb", L"BackendName", backend); + + const int suggestedLatencyMS = (int)SendMessage(GetDlgItem(hWnd, IDC_LATENCY), TBM_GETPOS, 0, 0); + const bool minimalLatency = SendMessage(GetDlgItem(hWnd, IDC_MINIMIZE), BM_GETCHECK, 0, 0) == BST_CHECKED; + CfgWriteBool(L"Cubeb", L"MinimalSuggestedLatency", minimalLatency); + CfgWriteInt(L"Cubeb", L"ManualSuggestedLatencyMS", suggestedLatencyMS); + + EndDialog(hWnd, 0); + return TRUE; + } + break; + + case IDCANCEL: + EndDialog(hWnd, 0); + return TRUE; + + default: + return FALSE; + } + } + break; + + case WM_HSCROLL: + { + const DWORD wmId = LOWORD(wParam); + DWORD wmEvent = HIWORD(wParam); + switch (wmId) + { + case TB_LINEUP: + case TB_LINEDOWN: + case TB_PAGEUP: + case TB_PAGEDOWN: + case TB_TOP: + case TB_BOTTOM: + wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0); + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + { + wchar_t temp[128]; + if (wmEvent < 10) + wmEvent = 10; + if (wmEvent > 200) + wmEvent = 200; + SendMessage((HWND)lParam, TBM_SETPOS, TRUE, wmEvent); + swprintf_s(temp, L"%d ms", wmEvent); + SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp); + break; + } + default: + return FALSE; + } + + return TRUE; + } + break; + + default: + return FALSE; + } + return FALSE; +} + BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; @@ -298,9 +410,11 @@ BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case IDC_OUTCONF: { const int module = (int)SendMessage(GetDlgItem(hWnd, IDC_OUTPUT), CB_GETCURSEL, 0, 0); - if (mods[module] == nullptr) + if (mods[module] != CubebOut) break; - mods[module]->Configure((uptr)hWnd); + + if (DialogBoxParam(nullptr, MAKEINTRESOURCE(IDD_CUBEB), hWnd, (DLGPROC)CubebConfigProc, 1) == -1) + MessageBox(hWnd, L"Error Opening the config dialog.", L"Error", MB_OK | MB_SETFOREGROUND); } break; diff --git a/pcsx2/SPU2/Windows/SPU2.rc b/pcsx2/SPU2/Windows/SPU2.rc index 00e1d2f62f..7354bb94c5 100644 --- a/pcsx2/SPU2/Windows/SPU2.rc +++ b/pcsx2/SPU2/Windows/SPU2.rc @@ -7,7 +7,6 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "svnrev.h" #include "common/afxresmw.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -175,25 +174,22 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // Dialog // -IDD_PORTAUDIO DIALOGEX 0, 0, 316, 166 +IDD_CUBEB DIALOGEX 0, 0, 316, 166 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Portaudio Output Module Settings" +CAPTION "Cubeb Output Module Settings" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,105,144,50,14 PUSHBUTTON "Cancel",IDCANCEL,161,144,50,14 - COMBOBOX IDC_PA_HOSTAPI,7,17,95,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Host API:",IDC_STATIC,7,7,32,8 - COMBOBOX IDC_PA_DEVICE,108,17,201,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Device Name:",IDC_STATIC,107,7,45,8 + COMBOBOX IDC_BACKEND,7,17,95,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Backend:",IDC_STATIC,7,7,32,8 CONTROL "",IDC_LATENCY,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,96,93,155,10 - LTEXT "NOTE: Depending on the hardware and drivers, the suggested manual latency might not be used, and portaudio will choose the closest possible value.",IDC_STATIC,12,111,286,19 + LTEXT "NOTE: Depending on the hardware and drivers, the suggested manual latency might not be used, and Cubeb will choose the closest possible value.",IDC_STATIC,12,111,286,19 CTEXT "20ms",IDC_LATENCY_LABEL,264,93,35,11 GROUPBOX "Output Latency",IDC_STATIC,7,57,302,79 CONTROL "Use smallest possible (may cause issues if the actual value is too small)",IDC_MINIMIZE, "Button",BS_AUTORADIOBUTTON | WS_GROUP,12,75,258,10 CONTROL "Use this latency:",IDC_MANUAL,"Button",BS_AUTORADIOBUTTON,12,93,69,10 - CONTROL "WASAPI Exclusive Mode",IDC_EXCLUSIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,39,93,10 END @@ -205,7 +201,7 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN - IDD_PORTAUDIO, DIALOG + IDD_CUBEB, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 309 diff --git a/pcsx2/SPU2/Windows/resource.h b/pcsx2/SPU2/Windows/resource.h index 8dfb7f66a6..32c75f3c5e 100644 --- a/pcsx2/SPU2/Windows/resource.h +++ b/pcsx2/SPU2/Windows/resource.h @@ -5,7 +5,7 @@ #define IDD_DEBUG 105 #define IDD_CONFIG_SOUNDTOUCH 117 #define IDD_CONFIG_DEBUG 118 -#define IDD_PORTAUDIO 119 +#define IDD_CUBEB 119 #define IDC_DUMPREGS 1003 #define IDC_DUMPMEM 1004 #define IDC_DUMPCORE 1005 @@ -27,7 +27,6 @@ #define IDC_OUTCONF 1028 #define IDC_DSP_ENABLE 1029 #define IDC_DS_DEVICE 1032 -#define IDC_PA_DEVICE 1033 #define IDC_DBG_OVERRUNS 1038 #define IDC_DBG_CACHE 1039 #define IDC_LATENCY_SLIDER 1040 @@ -50,9 +49,8 @@ #define IDC_VOLUME_SLIDER 1068 #define IDC_MINIMIZE 1069 #define IDC_MANUAL 1070 -#define IDC_PA_HOSTAPI 1071 +#define IDC_BACKEND 1071 #define IDC_LATENCY 1072 -#define IDC_EXCLUSIVE 1073 // Next default values for new objects // diff --git a/pcsx2/SPU2/wx/wxConfig.cpp b/pcsx2/SPU2/wx/wxConfig.cpp index cedae625ac..6b956ba6d4 100644 --- a/pcsx2/SPU2/wx/wxConfig.cpp +++ b/pcsx2/SPU2/wx/wxConfig.cpp @@ -17,10 +17,22 @@ #include "SPU2/Config.h" #if !defined(_WIN32) // BSD, Macos #include "SPU2/Linux/Config.h" +#include "SPU2/Linux/Dialogs.h" #endif #include "SPU2/Global.h" #include "wxConfig.h" +static const wchar_t* s_backend_names[][2] = { + {L"Automatic", L""}, +#ifdef __linux__ + {L"ALSA", L"alsa"}, + {L"JACK", L"jack"}, + {L"PulseAudio", L"pulseaudio"}, +#elif defined(__APPLE__) + {L"AudioUnit", L"audiounit"}, +#endif +}; + MixerTab::MixerTab(wxWindow* parent) : wxPanel(parent, wxID_ANY) { @@ -352,49 +364,27 @@ Dialog::Dialog() wxArrayString module_entries; module_entries.Add("No Sound (Emulate SPU2 only)"); -#ifdef SPU2X_PORTAUDIO - module_entries.Add("PortAudio (Cross-platform)"); +#ifdef SPU2X_CUBEB + module_entries.Add("Cubeb (Cross-platform)"); #endif - module_entries.Add("SDL Audio (Recommended for PulseAudio)"); m_module_select = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, module_entries); module_box->Add(m_module_select, wxSizerFlags().Centre()); -#ifdef SPU2X_PORTAUDIO +#ifdef SPU2X_CUBEB // Portaudio - m_portaudio_box = new wxBoxSizer(wxVERTICAL); - m_portaudio_text = new wxStaticText(this, wxID_ANY, "Portaudio API"); - m_portaudio_box->Add(m_portaudio_text, wxSizerFlags().Centre()); + m_cubeb_box = new wxBoxSizer(wxVERTICAL); + m_cubeb_text = new wxStaticText(this, wxID_ANY, "Backend"); + m_cubeb_box->Add(m_cubeb_text, wxSizerFlags().Centre()); - wxArrayString portaudio_entries; -#ifdef __linux__ - portaudio_entries.Add("ALSA (recommended)"); - portaudio_entries.Add("OSS (legacy)"); - portaudio_entries.Add("JACK"); -#elif defined(__APPLE__) - portaudio_entries.Add("CoreAudio"); -#else - portaudio_entries.Add("OSS"); -#endif - m_portaudio_select = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, portaudio_entries); - m_portaudio_box->Add(m_portaudio_select, wxSizerFlags().Centre()); + m_cubeb_select = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + for (size_t i = 0; i < std::size(s_backend_names); i++) + m_cubeb_select->Append(s_backend_names[i][0]); + m_cubeb_box->Add(m_cubeb_select, wxSizerFlags().Centre()); #endif - // SDL - m_sdl_box = new wxBoxSizer(wxVERTICAL); - m_sdl_text = new wxStaticText(this, wxID_ANY, "SDL API"); - m_sdl_box->Add(m_sdl_text, wxSizerFlags().Centre()); - - wxArrayString sdl_entries; - for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) - sdl_entries.Add(SDL_GetAudioDriver(i)); - - m_sdl_select = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sdl_entries); - m_sdl_box->Add(m_sdl_select, wxSizerFlags().Centre()); - -#ifdef SPU2X_PORTAUDIO - module_box->Add(m_portaudio_box, wxSizerFlags().Expand()); +#ifdef SPU2X_CUBEB + module_box->Add(m_cubeb_box, wxSizerFlags().Expand()); #endif - module_box->Add(m_sdl_box, wxSizerFlags().Expand()); m_top_box->Add(module_box, wxSizerFlags().Centre().Border(wxALL, 5)); @@ -423,34 +413,25 @@ Dialog::~Dialog() void Dialog::Reconfigure() { const int mod = m_module_select->GetCurrentSelection(); - bool show_portaudio = false, show_sdl = false; + bool show_cubeb = false; switch (mod) { case 0: - show_portaudio = false; - show_sdl = false; + show_cubeb = false; break; case 1: - show_portaudio = true; - show_sdl = false; - break; - - case 2: - show_portaudio = false; - show_sdl = true; + show_cubeb = true; break; default: - show_portaudio = false; - show_sdl = false; + show_cubeb = false; break; } -#ifdef SPU2X_PORTAUDIO - m_top_box->Show(m_portaudio_box, show_portaudio, true); +#ifdef SPU2X_CUBEB + m_top_box->Show(m_cubeb_box, show_cubeb, true); #endif - m_top_box->Show(m_sdl_box, show_sdl, true); // Recalculating both of these accounts for if neither was showing initially. m_top_box->Layout(); @@ -465,10 +446,18 @@ void Dialog::CallReconfigure(wxCommandEvent& event) void Dialog::Load() { m_module_select->SetSelection(OutputModule); -#ifdef SPU2X_PORTAUDIO - m_portaudio_select->SetSelection(OutputAPI); +#ifdef SPU2X_CUBEB + wxString backend; + CfgReadStr(L"Cubeb", L"BackendName", backend, L""); + for (size_t i = 0; i < std::size(s_backend_names); i++) + { + if (backend == s_backend_names[i][1]) + { + m_cubeb_select->SetSelection(static_cast(i)); + break; + } + } #endif - m_sdl_select->SetSelection(SdlOutputAPI); m_mixer_panel->Load(); m_sync_panel->Load(); @@ -481,19 +470,12 @@ void Dialog::Save() { OutputModule = m_module_select->GetSelection(); -#ifdef SPU2X_PORTAUDIO - OutputAPI = m_portaudio_select->GetSelection(); - wxString p_api(m_portaudio_select->GetStringSelection()); - if (p_api.Find("ALSA") != wxNOT_FOUND) - p_api = "ALSA"; - if (p_api.Find("OSS") != wxNOT_FOUND) - p_api = "OSS"; - PortaudioOut->SetApiSettings(p_api); +#ifdef SPU2X_CUBEB + const int backend_selection = m_cubeb_select->GetSelection(); + if (backend_selection >= 0) + CfgWriteStr(L"Cubeb", L"BackendName", s_backend_names[backend_selection][1]); #endif - SdlOutputAPI = m_sdl_select->GetSelection(); - SDLOut->SetApiSettings(m_sdl_select->GetStringSelection()); - m_mixer_panel->Save(); m_sync_panel->Save(); m_debug_panel->Save(); diff --git a/pcsx2/SPU2/wx/wxConfig.h b/pcsx2/SPU2/wx/wxConfig.h index 5ef3395854..8f25ee02f7 100644 --- a/pcsx2/SPU2/wx/wxConfig.h +++ b/pcsx2/SPU2/wx/wxConfig.h @@ -78,9 +78,9 @@ public: class Dialog : public wxDialog { - wxBoxSizer *m_top_box, *m_portaudio_box, *m_sdl_box; - wxChoice *m_module_select, *m_portaudio_select, *m_sdl_select; - wxStaticText *m_portaudio_text, *m_sdl_text; + wxBoxSizer *m_top_box, *m_cubeb_box; + wxChoice *m_module_select, *m_cubeb_select; + wxStaticText *m_cubeb_text; MixerTab* m_mixer_panel; SyncTab* m_sync_panel; diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index d23f26c5fe..15ac94b0bf 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -48,7 +48,7 @@ PrecompiledHeader.h;%(ForcedIncludeFiles) NoExtensions /Zc:externConstexpr %(AdditionalOptions) - WIN32_LEAN_AND_MEAN;LZMA_API_STATIC;BUILD_DX=1;SPU2X_CUBEB;SPU2X_PORTAUDIO;DIRECTINPUT_VERSION=0x0800;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;LZMA_API_STATIC;BUILD_DX=1;SPU2X_CUBEB;DIRECTINPUT_VERSION=0x0800;%(PreprocessorDefinitions) PCSX2_DEBUG;PCSX2_DEVBUILD;_SECURE_SCL_=1;%(PreprocessorDefinitions) PCSX2_DEVEL;PCSX2_DEVBUILD;NDEBUG;_SECURE_SCL_=1;%(PreprocessorDefinitions) NDEBUG;_SECURE_SCL_=0;%(PreprocessorDefinitions) @@ -359,7 +359,6 @@ - @@ -1120,9 +1119,6 @@ {47afdbef-f15f-4bc0-b436-5be443c3f80f} - - {0a18a071-125e-442f-aff7-a3f68abecf99} - {0fae817d-9a32-4830-857e-81da57246e16} false diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index 96f31e9a9c..b243c92bce 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -1133,9 +1133,6 @@ System\Ps2\SPU2 - - System\Ps2\SPU2 - System\Ps2\DEV9\ATA\Commands