SPU2: purge DSound & log + config fix

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2020-09-29 07:53:50 +02:00 committed by refractionpcsx2
parent c8abed371b
commit 7d917afcbb
12 changed files with 4 additions and 549 deletions

View File

@ -84,7 +84,6 @@ SndOutModule* mods[] =
&NullOut,
#ifdef _MSC_VER
XAudio2Out,
DSoundOut,
WaveOut,
#endif
#if defined(SPU2X_PORTAUDIO)

View File

@ -667,7 +667,6 @@ public:
#ifdef _MSC_VER
//internal
extern SndOutModule* WaveOut;
extern SndOutModule* DSoundOut;
extern SndOutModule* XAudio2Out;
#endif
#if defined(SPU2X_PORTAUDIO)

View File

@ -66,7 +66,6 @@ void initIni()
void CfgSetSettingsDir(const char* dir)
{
initIni();
CfgFile = Path::Combine((dir == nullptr) ? wxString(L"inis") : wxString::FromUTF8(dir), L"SPU2.ini");
}

View File

@ -136,11 +136,10 @@ void ReadSettings()
dspPluginModule = CfgReadInt(L"DSP PLUGIN", L"ModuleNum", 0);
dspPluginEnabled = CfgReadBool(L"DSP PLUGIN", L"Enabled", false);
// Read DSOUNDOUT and WAVEOUT configs:
// Read WAVEOUT configs:
CfgReadStr(L"WAVEOUT", L"Device", Config_WaveOut.Device, L"default");
Config_WaveOut.NumBuffers = CfgReadInt(L"WAVEOUT", L"Buffer_Count", 4);
DSoundOut->ReadSettings();
PortaudioOut->ReadSettings();
SoundtouchCfg::ReadSettings();
@ -155,8 +154,6 @@ void ReadSettings()
{
// Unsupported or legacy module.
fwprintf(stderr, L"* SPU2: Unknown output module '%s' specified in configuration file.\n", omodid);
fprintf(stderr, "* SPU2: Defaulting to DirectSound (%S).\n", DSoundOut->GetIdent());
OutputModule = FindOutputModuleById(DSoundOut->GetIdent());
}
}
@ -197,7 +194,6 @@ void WriteSettings()
CfgWriteBool(L"DSP PLUGIN", L"Enabled", dspPluginEnabled);
PortaudioOut->WriteSettings();
DSoundOut->WriteSettings();
SoundtouchCfg::WriteSettings();
DebugConfig::WriteSettings();
}
@ -207,8 +203,7 @@ void CheckOutputModule(HWND window)
OutputModule = SendMessage(GetDlgItem(window, IDC_OUTPUT), CB_GETCURSEL, 0, 0);
const bool IsConfigurable =
mods[OutputModule] == PortaudioOut ||
mods[OutputModule] == WaveOut ||
mods[OutputModule] == DSoundOut;
mods[OutputModule] == WaveOut;
const bool AudioExpansion =
mods[OutputModule] == XAudio2Out ||

View File

@ -61,11 +61,6 @@ extern int CfgReadInt(const TCHAR* Section, const TCHAR* Name, int Default);
extern float CfgReadFloat(const TCHAR* Section, const TCHAR* Name, float Default);
// Items Specific to DirectSound
#define STRFY(x) #x
#define verifyc(x) Verifyc(x, STRFY(x))
extern void Verifyc(HRESULT hr, const char* fn);
struct ds_device_data
{
wxString name;

View File

@ -67,25 +67,6 @@ BEGIN
DEFPUSHBUTTON "Close",IDOK,246,451,50,14
END
IDD_DSOUND DIALOGEX 0, 0, 196, 218
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "DirectSound Output Module Settings"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,45,196,50,14
PUSHBUTTON "Cancel",IDCANCEL,102,196,50,14
COMBOBOX IDC_DS_DEVICE,8,13,180,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "DirectSound Device:",IDC_STATIC,6,3,65,8
CONTROL "",IDC_BUFFERS_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,40,137,108,10
LTEXT "Increase the buffer count if you are experiencing loopy or stuttery audio even when games run at high FPS.",IDC_STATIC,13,157,169,27
CTEXT "8 (80 ms latency)",IDC_LATENCY_LABEL,46,123,95,11
LTEXT "The options above are useful for compatibility with older and/or buggy sound drivers ONLY, and should not be checked unless you experience sound problems (such as crackly audio or silence).",IDC_STATIC,18,68,172,38
CONTROL "Disable Global Focus",IDC_GLOBALFOCUS_DISABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,6,38,140,10
CONTROL "Use a crappy alternate buffering mode",IDC_USE_HARDWARE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,53,140,10
GROUPBOX "Output Buffers",IDC_STATIC,6,111,183,77
END
IDD_WAVEOUT DIALOGEX 0, 0, 170, 122
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "WaveOut Output Module Settings"
@ -179,14 +160,6 @@ BEGIN
BOTTOMMARGIN, 465
END
IDD_DSOUND, DIALOG
BEGIN
LEFTMARGIN, 4
RIGHTMARGIN, 191
TOPMARGIN, 3
BOTTOMMARGIN, 214
END
IDD_WAVEOUT, DIALOG
BEGIN
LEFTMARGIN, 4

View File

@ -1,488 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 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 "../Global.h"
#define _WIN32_DCOM
#include "Dialogs.h"
#define DIRECTSOUND_VERSION 0x1000
#include <dsound.h>
class DSound : public SndOutModule
{
private:
static const uint MAX_BUFFER_COUNT = 8;
static const int PacketsPerBuffer = 8;
static const int BufferSize = SndOutPacketSize * PacketsPerBuffer;
//////////////////////////////////////////////////////////////////////////////////////////
// Configuration Vars
wxString m_Device;
u8 m_NumBuffers;
bool m_DisableGlobalFocus;
bool m_UseHardware;
ds_device_data m_devices[32];
int ndevs;
GUID DevGuid; // currently employed GUID.
bool haveGuid;
//////////////////////////////////////////////////////////////////////////////////////////
// Instance vars
int channel;
int myLastWrite; // last write position, in bytes
bool dsound_running;
HANDLE thread;
DWORD tid;
IDirectSound8* dsound;
IDirectSoundBuffer8* buffer;
IDirectSoundNotify8* buffer_notify;
HANDLE buffer_events[MAX_BUFFER_COUNT];
WAVEFORMATEX wfx;
HANDLE waitEvent;
template <typename T>
static DWORD CALLBACK RThread(DSound* obj)
{
return obj->Thread<T>();
}
template <typename T>
DWORD CALLBACK Thread()
{
static const int BufferSizeBytes = BufferSize * sizeof(T);
while (dsound_running)
{
u32 rv = WaitForMultipleObjects(m_NumBuffers, buffer_events, FALSE, 200);
T *p1, *oldp1;
LPVOID p2;
DWORD s1, s2;
u32 poffset = BufferSizeBytes * rv;
if (FAILED(buffer->Lock(poffset, BufferSizeBytes, (LPVOID*)&p1, &s1, &p2, &s2, 0)))
{
assert(0);
fputs("* SPU2: Directsound Warning > Buffer lock failure. You may need to increase\n\tyour configured DSound buffer count.\n", stderr);
continue;
}
oldp1 = p1;
for (int p = 0; p < PacketsPerBuffer; p++, p1 += SndOutPacketSize)
SndBuffer::ReadSamples(p1);
buffer->Unlock(oldp1, s1, p2, s2);
// Set the write pointer to the beginning of the next block.
myLastWrite = (poffset + BufferSizeBytes) & ~BufferSizeBytes;
}
return 0;
}
public:
s32 Init()
{
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
//
// Initialize DSound
//
GUID cGuid;
try
{
if (m_Device.empty())
throw std::runtime_error("screw it");
if ((FAILED(IIDFromString(m_Device, &cGuid))) ||
FAILED(DirectSoundCreate8(&cGuid, &dsound, nullptr)))
throw std::runtime_error("try again?");
}
catch (std::runtime_error&)
{
// if the GUID failed, just open up the default dsound driver:
if (FAILED(DirectSoundCreate8(nullptr, &dsound, nullptr)))
throw std::runtime_error("DirectSound failed to initialize!");
}
if (FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY)))
throw std::runtime_error("DirectSound Error: Cooperative level could not be set.");
// Determine the user's speaker configuration, and select an expansion option as needed.
// FAIL : Directsound doesn't appear to support audio expansion >_<
DWORD speakerConfig = 2;
//dsound->GetSpeakerConfig( &speakerConfig );
IDirectSoundBuffer* buffer_;
DSBUFFERDESC desc;
// Set up WAV format structure.
memset(&wfx, 0, sizeof(WAVEFORMATEX));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nSamplesPerSec = SampleRate;
wfx.nChannels = (WORD)speakerConfig;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = 2 * (WORD)speakerConfig;
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
wfx.cbSize = 0;
uint BufferSizeBytes = BufferSize * wfx.nBlockAlign;
// Set up DSBUFFERDESC structure.
memset(&desc, 0, sizeof(DSBUFFERDESC));
desc.dwSize = sizeof(DSBUFFERDESC);
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
desc.dwBufferBytes = BufferSizeBytes * m_NumBuffers;
desc.lpwfxFormat = &wfx;
// Try a hardware buffer first, and then fall back on a software buffer if
// that one fails.
desc.dwFlags |= m_UseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE;
desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS;
if (FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0)))
{
if (m_UseHardware)
{
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS;
if (FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0)))
throw std::runtime_error("DirectSound Error: Buffer could not be created.");
}
throw std::runtime_error("DirectSound Error: Buffer could not be created.");
}
if (FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8, (void**)&buffer)) || buffer == nullptr)
throw std::runtime_error("DirectSound Error: Interface could not be queried.");
buffer_->Release();
verifyc(buffer->QueryInterface(IID_IDirectSoundNotify8, (void**)&buffer_notify));
DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT];
for (uint i = 0; i < m_NumBuffers; i++)
{
buffer_events[i] = CreateEvent(nullptr, FALSE, FALSE, nullptr);
not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes * (i + 1)) % desc.dwBufferBytes;
not[i].hEventNotify = buffer_events[i];
}
buffer_notify->SetNotificationPositions(m_NumBuffers, not);
LPVOID p1 = 0, p2 = 0;
DWORD s1 = 0, s2 = 0;
verifyc(buffer->Lock(0, desc.dwBufferBytes, &p1, &s1, &p2, &s2, 0));
assert(p2 == 0);
memset(p1, 0, s1);
verifyc(buffer->Unlock(p1, s1, p2, s2));
//Play the buffer !
verifyc(buffer->Play(0, 0, DSBPLAY_LOOPING));
// Start Thread
myLastWrite = 0;
dsound_running = true;
thread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)RThread<StereoOut16>, this, 0, &tid);
SetThreadPriority(thread, THREAD_PRIORITY_ABOVE_NORMAL);
return 0;
}
void Close()
{
// Stop Thread
fprintf(stderr, "* SPU2: Waiting for DSound thread to finish...");
dsound_running = false;
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
fprintf(stderr, " Done.\n");
//
// Clean up
//
if (buffer != nullptr)
{
buffer->Stop();
for (u32 i = 0; i < m_NumBuffers; i++)
{
if (buffer_events[i] != nullptr)
CloseHandle(buffer_events[i]);
buffer_events[i] = nullptr;
}
safe_release(buffer_notify);
safe_release(buffer);
}
safe_release(dsound);
CoUninitialize();
}
private:
bool _DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext)
{
m_devices[ndevs].name = lpcstrDescription;
if (lpGuid)
{
m_devices[ndevs].guid = *lpGuid;
m_devices[ndevs].hasGuid = true;
}
else
{
m_devices[ndevs].hasGuid = false;
}
ndevs++;
if (ndevs < 32)
return TRUE;
return FALSE;
}
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];
haveGuid = !FAILED(IIDFromString(m_Device, &DevGuid));
SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_RESETCONTENT, 0, 0);
ndevs = 0;
DirectSoundEnumerate(DSEnumCallback, nullptr);
tSel = -1;
for (int i = 0; i < ndevs; i++)
{
SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_ADDSTRING, 0, (LPARAM)m_devices[i].name.wc_str());
if (haveGuid && IsEqualGUID(m_devices[i].guid, DevGuid) || tSel < 0 && !m_devices[i].hasGuid)
tSel = i;
}
if (tSel >= 0)
SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_SETCURSEL, tSel, 0);
INIT_SLIDER(IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1);
SendMessage(GetDlgItem(hWnd, IDC_BUFFERS_SLIDER), TBM_SETPOS, TRUE, m_NumBuffers);
swprintf_s(temp, L"%d (%d ms latency)", m_NumBuffers, 1000 / (96000 / (m_NumBuffers * BufferSize)));
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
SET_CHECK(IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus);
SET_CHECK(IDC_USE_HARDWARE, m_UseHardware);
}
break;
case WM_COMMAND:
{
wchar_t temp[128];
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDOK:
{
int i = (int)SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_GETCURSEL, 0, 0);
if (!m_devices[i].hasGuid)
{
m_Device[0] = 0; // clear device name to ""
}
else
{
swprintf_s(temp, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
m_devices[i].guid.Data1,
m_devices[i].guid.Data2,
m_devices[i].guid.Data3,
m_devices[i].guid.Data4[0],
m_devices[i].guid.Data4[1],
m_devices[i].guid.Data4[2],
m_devices[i].guid.Data4[3],
m_devices[i].guid.Data4[4],
m_devices[i].guid.Data4[5],
m_devices[i].guid.Data4[6],
m_devices[i].guid.Data4[7]);
m_Device = temp;
}
m_NumBuffers = (int)SendMessage(GetDlgItem(hWnd, IDC_BUFFERS_SLIDER), TBM_GETPOS, 0, 0);
if (m_NumBuffers < 2)
m_NumBuffers = 2;
if (m_NumBuffers > MAX_BUFFER_COUNT)
m_NumBuffers = MAX_BUFFER_COUNT;
EndDialog(hWnd, 0);
}
break;
case IDCANCEL:
EndDialog(hWnd, 0);
break;
HANDLE_CHECK(IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus);
HANDLE_CHECK(IDC_USE_HARDWARE, m_UseHardware);
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 < 2)
wmEvent = 2;
if (wmEvent > MAX_BUFFER_COUNT)
wmEvent = MAX_BUFFER_COUNT;
SendMessage((HWND)lParam, TBM_SETPOS, TRUE, wmEvent);
swprintf_s(temp, L"%d (%d ms latency)", wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
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)
{
INT_PTR ret;
ret = DialogBoxParam(nullptr, MAKEINTRESOURCE(IDD_DSOUND), (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;
}
}
s32 Test() const
{
return 0;
}
int GetEmptySampleCount()
{
DWORD play, write;
if (buffer == nullptr)
return 0;
buffer->GetCurrentPosition(&play, &write);
// Note: Dsound's write cursor is bogus. Use our own instead:
int empty = play - myLastWrite;
if (empty < 0)
empty = -empty;
return empty / 2;
}
const wchar_t* GetIdent() const
{
return L"dsound";
}
const wchar_t* GetLongName() const
{
return L"DirectSound (Nice)";
}
void ReadSettings()
{
CfgReadStr(L"DSOUNDOUT", L"Device", m_Device, L"default");
m_NumBuffers = CfgReadInt(L"DSOUNDOUT", L"Buffer_Count", 5);
m_DisableGlobalFocus = CfgReadBool(L"DSOUNDOUT", L"Disable_Global_Focus", false);
m_UseHardware = CfgReadBool(L"DSOUNDOUT", L"Use_Hardware", false);
Clampify(m_NumBuffers, (u8)3, (u8)8);
}
void SetApiSettings(wxString api)
{
}
void WriteSettings() const
{
CfgWriteStr(L"DSOUNDOUT", L"Device", m_Device.empty() ? L"default" : m_Device);
CfgWriteInt(L"DSOUNDOUT", L"Buffer_Count", m_NumBuffers);
CfgWriteBool(L"DSOUNDOUT", L"Disable_Global_Focus", m_DisableGlobalFocus);
CfgWriteBool(L"DSOUNDOUT", L"Use_Hardware", m_UseHardware);
}
} static DS;
BOOL CALLBACK DSound::ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DS._ConfigProc(hWnd, uMsg, wParam, lParam);
}
BOOL CALLBACK DSound::DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext)
{
pxAssume(DSoundOut != nullptr);
return DS._DSEnumCallback(lpGuid, lpcstrDescription, lpcstrModule, lpContext);
}
SndOutModule* DSoundOut = &DS;

View File

@ -22,15 +22,6 @@ int SendDialogMsg(HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam)
return SendMessage(GetDlgItem(hwnd, dlgId), code, wParam, lParam);
}
__forceinline void Verifyc(HRESULT hr, const char* fn)
{
if (FAILED(hr))
{
assert(0);
throw std::runtime_error("DirectSound returned an error from %s");
}
}
void AssignSliderValue(HWND idcwnd, HWND hwndDisplay, int value)
{
value = std::min(std::max(value, 0), 512);

View File

@ -3,7 +3,6 @@
// Used by SPU2.rc
#define IDD_CONFIG 9
#define IDD_DEBUG 105
#define IDD_DSOUND 106
#define IDD_WAVEOUT 109
#define IDD_CONFIG_SOUNDTOUCH 117
#define IDD_CONFIG_DEBUG 118

View File

@ -225,10 +225,7 @@ s32 SPU2init()
assert(regtable[0x400] == nullptr);
if (IsInitialized)
{
printf(" * SPU2: Already initialized - Ignoring SPU2init signal.");
return 0;
}
IsInitialized = true;
SPU2_dummy_callback = false;

View File

@ -288,7 +288,6 @@
<ClCompile Include="..\..\SPU2\Lowpass.cpp" />
<ClCompile Include="..\..\SPU2\SndOut.cpp" />
<ClCompile Include="..\..\SPU2\Timestretcher.cpp" />
<ClCompile Include="..\..\SPU2\Windows\SndOut_DSound.cpp" />
<ClCompile Include="..\..\SPU2\Windows\SndOut_waveOut.cpp" />
<ClCompile Include="..\..\SPU2\Windows\SndOut_XAudio2.cpp" />
<ClCompile Include="..\..\SPU2\Linux\Alsa.cpp">
@ -781,4 +780,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>

View File

@ -985,9 +985,6 @@
<ClCompile Include="..\..\SPU2\Windows\SndOut_waveOut.cpp">
<Filter>System\Ps2\SPU2</Filter>
</ClCompile>
<ClCompile Include="..\..\SPU2\Windows\SndOut_DSound.cpp">
<Filter>System\Ps2\SPU2</Filter>
</ClCompile>
<ClCompile Include="..\..\SPU2\Windows\UIHelpers.cpp">
<Filter>System\Ps2\SPU2</Filter>
</ClCompile>
@ -1605,4 +1602,4 @@
<Filter>AppHost\Resources</Filter>
</Manifest>
</ItemGroup>
</Project>
</Project>