mirror of https://github.com/PCSX2/pcsx2.git
SPU2: Remove Portaudio and SDL2 output modules
This commit is contained in:
parent
88ce192610
commit
f3d51a242d
|
@ -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-
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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[];
|
||||
|
||||
// =====================================================================================================
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
//#include "Mixer.h"
|
||||
#include "Global.h"
|
||||
#include "SndOut.h"
|
||||
|
||||
#define _WIN32_DCOM
|
||||
#ifdef _WIN32
|
||||
#include <portaudio/include/portaudio.h>
|
||||
#include "Windows/Dialogs.h"
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
#include "portaudio.h"
|
||||
#include "Linux/Dialogs.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "wchar.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <portaudio/include/pa_win_wasapi.h>
|
||||
#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 T>
|
||||
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<Stereo20Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ConLog("* SPU2 > 2.1 speaker expansion enabled.\n");
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo21Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ConLog("* SPU2 > 4 speaker expansion enabled [quadraphenia]\n");
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo40Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ConLog("* SPU2 > 4.1 speaker expansion enabled.\n");
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo41Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
switch (dplLevel)
|
||||
{
|
||||
case 0:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion enabled.\n");
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo51Out32>(&writtenSoFar); //"normal" stereo upmix
|
||||
break;
|
||||
case 1:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n");
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo51Out32Dpl>(&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<Stereo51Out32DplII>(&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<Stereo71Out32>(&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;
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#ifdef SDL_BUILD
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include "Global.h"
|
||||
#include "SndOut.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "Windows/Dialogs.h"
|
||||
#else // BSD, Macos
|
||||
#include "Linux/Dialogs.h"
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
/* 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 <SDL.h>
|
||||
#include <SDL_audio.h>
|
||||
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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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<int>(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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<ForcedIncludeFiles>PrecompiledHeader.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<AdditionalOptions>/Zc:externConstexpr %(AdditionalOptions)</AdditionalOptions>
|
||||
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;LZMA_API_STATIC;BUILD_DX=1;SPU2X_CUBEB;SPU2X_PORTAUDIO;DIRECTINPUT_VERSION=0x0800;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;LZMA_API_STATIC;BUILD_DX=1;SPU2X_CUBEB;DIRECTINPUT_VERSION=0x0800;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="$(Configuration.Contains(Debug))">PCSX2_DEBUG;PCSX2_DEVBUILD;_SECURE_SCL_=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="$(Configuration.Contains(Devel))">PCSX2_DEVEL;PCSX2_DEVBUILD;NDEBUG;_SECURE_SCL_=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="$(Configuration.Contains(Release))">NDEBUG;_SECURE_SCL_=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
@ -359,7 +359,6 @@
|
|||
<ClCompile Include="SPU2\debug.cpp" />
|
||||
<ClCompile Include="SPU2\RegLog.cpp" />
|
||||
<ClCompile Include="SPU2\SndOut_Cubeb.cpp" />
|
||||
<ClCompile Include="SPU2\SndOut_Portaudio.cpp" />
|
||||
<ClCompile Include="SPU2\wavedump_wav.cpp" />
|
||||
<ClCompile Include="SPU2\SndOut.cpp" />
|
||||
<ClCompile Include="SPU2\Timestretcher.cpp" />
|
||||
|
@ -1120,9 +1119,6 @@
|
|||
<ProjectReference Include="$(SolutionDir)3rdparty\libsamplerate\libsamplerate.vcxproj">
|
||||
<Project>{47afdbef-f15f-4bc0-b436-5be443c3f80f}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)3rdparty\portaudio\build\msvc\portaudio.vcxproj">
|
||||
<Project>{0a18a071-125e-442f-aff7-a3f68abecf99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)3rdparty\pthreads4w\build\pthreads4w.vcxproj">
|
||||
<Project>{0fae817d-9a32-4830-857e-81da57246e16}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
|
|
|
@ -1133,9 +1133,6 @@
|
|||
<ClCompile Include="SPU2\Wavedump_wav.cpp">
|
||||
<Filter>System\Ps2\SPU2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SPU2\SndOut_Portaudio.cpp">
|
||||
<Filter>System\Ps2\SPU2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DEV9\ATA\Commands\ATA_Command.cpp">
|
||||
<Filter>System\Ps2\DEV9\ATA\Commands</Filter>
|
||||
</ClCompile>
|
||||
|
|
Loading…
Reference in New Issue