Add automatic input rate adjustment to win32.

This commit is contained in:
Brandon Wright 2018-05-24 18:52:43 -05:00
parent 8200a7bb5f
commit 98d3d276d5
8 changed files with 123 additions and 6 deletions

View File

@ -45,6 +45,7 @@
#define IDC_RATE 1003
#define IDC_MIX 1004
#define IDC_DYNRATECONTROL 1005
#define IDC_AUTOMATICINPUTRATE 1021
#define IDC_STEREO 1006
#define IDC_REV_STEREO 1007
#define IDC_LINEAR_INTER 1008

View File

@ -98,14 +98,15 @@ BEGIN
LTEXT "Buffer Length:",IDC_STATIC,125,58,49,11
COMBOBOX IDC_RATE,177,40,106,171,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Playback Rate:",IDC_STATIC,125,41,49,11
CONTROL "&Dynamic Rate Control",IDC_DYNRATECONTROL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,99,96,10
CONTROL "&Stereo",IDC_STEREO,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,295,20,93,10
CONTROL "&Reverse Stereo",IDC_REV_STEREO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,35,94,10
CONTROL "&Dynamic Rate Control",IDC_DYNRATECONTROL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,90,96,10
CONTROL "&Automatic Input Rate",IDC_AUTOMATICINPUTRATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,105,96,10
CONTROL "&Stereo",IDC_STEREO,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,295,15,93,10
CONTROL "&Reverse Stereo",IDC_REV_STEREO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,30,94,10
CONTROL "&Synchronize with sound core",IDC_SYNC_TO_SOUND_CPU,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,84,102,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,75,102,10
PUSHBUTTON "&Cancel",IDCANCEL,350,122,56,16
CONTROL "&Mute sound",IDC_MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,50,93,12
CONTROL "Frame Advance mu&te",IDC_FAMT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,67,90,12
CONTROL "&Mute sound",IDC_MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,45,93,12
CONTROL "Frame Advance mu&te",IDC_FAMT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,60,90,12
CONTROL "",IDC_INRATE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | WS_TABSTOP,124,88,157,26
EDITTEXT IDC_INRATEEDIT,177,74,105,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "Input Rate:",IDC_INRATETEXT,126,74,46,11

View File

@ -987,6 +987,7 @@ void WinRegisterConfigItems()
AddBoolC("ReverseStereo", Settings.ReverseStereo, false, "true to swap speaker outputs");
AddBoolC("Mute", GUI.Mute, false, "true to mute sound output (does not disable the sound CPU)");
AddBool("DynamicRateControl", Settings.DynamicRateControl, false);
AddBool("AutomaticInputRate", GUI.AutomaticInputRate, true);
#undef CATEGORY
#define CATEGORY "Sound\\Win"
AddUIntC("SoundDriver", GUI.SoundDriver, 4, "0=Snes9xDirectSound, 4=XAudio2 (recommended)");

View File

@ -208,6 +208,7 @@
#include "../filter/hq2x.h"
#include "../filter/2xsai.h"
#include "../apu/apu.h"
// available display output methods
CDirect3D Direct3D;
@ -655,6 +656,15 @@ void ToggleFullScreen ()
SetWindowPos (GUI.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_DRAWFRAME|SWP_FRAMECHANGED);
RestoreMainWinPos();
}
if (GUI.AutomaticInputRate)
{
int rate = WinGetAutomaticInputRate();
if (rate)
{
Settings.SoundInputRate = rate;
S9xUpdateDynamicRate(1, 2);
}
}
S9xGraphicsDeinit();
S9xSetWinPixelFormat ();
S9xInitUpdate();
@ -673,6 +683,60 @@ void WinEnumDisplayModes(std::vector<dMode> *modeVector)
S9xDisplayOutput->EnumModes(modeVector);
}
double WinGetRefreshRate(void)
{
double refreshRate = 0.0;
OSVERSIONINFO ovi;
DISPLAYCONFIG_TOPOLOGY_ID topologyID;
unsigned int numPathArrayElements = 0;
unsigned int numModeInfoArrayElements = 0;
DISPLAYCONFIG_PATH_INFO * pathInfoArray = NULL;
DISPLAYCONFIG_MODE_INFO * modeInfoArray = NULL;
int result = 0;
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&ovi))
return refreshRate;
if (ovi.dwMajorVersion < 6 || (ovi.dwMajorVersion == 6 && ovi.dwMinorVersion < 1))
return refreshRate;
result = GetDisplayConfigBufferSizes(QDC_DATABASE_CURRENT,
&numPathArrayElements,
&numModeInfoArrayElements);
if (result != ERROR_SUCCESS)
return refreshRate;
pathInfoArray = (DISPLAYCONFIG_PATH_INFO *)
malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * numPathArrayElements);
modeInfoArray = (DISPLAYCONFIG_MODE_INFO *)
malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * numModeInfoArrayElements);
result = QueryDisplayConfig(QDC_DATABASE_CURRENT,
&numPathArrayElements,
pathInfoArray,
&numModeInfoArrayElements,
modeInfoArray,
&topologyID);
if (result == ERROR_SUCCESS && numPathArrayElements >= 1)
{
refreshRate = (float)pathInfoArray[0].targetInfo.refreshRate.Numerator /
pathInfoArray[0].targetInfo.refreshRate.Denominator;
}
free(modeInfoArray);
free(pathInfoArray);
return refreshRate;
}
int WinGetAutomaticInputRate(void)
{
return (int)(WinGetRefreshRate() * 32040.0 / 60.09881389744051 + 0.5);
}
/* Depth conversion functions begin */
void Convert16To24 (SSurface *src, SSurface *dst, RECT *srect)

View File

@ -223,5 +223,7 @@ template<typename screenPtrType>
void WinDisplayStringInBuffer (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap);
char *ReadShaderFileContents(const TCHAR *filename);
void ReduceToPath(TCHAR *filename);
double WinGetRefreshRate();
int WinGetAutomaticInputRate();
#endif

View File

@ -196,6 +196,7 @@
#include "CDirectSound.h"
#include "CXAudio2.h"
#include "win32_sound.h"
#include "win32_display.h"
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
@ -217,6 +218,14 @@ bool ReInitSound()
{
if (GUI.AVIOut)
return false;
if (GUI.AutomaticInputRate)
{
int rate = WinGetAutomaticInputRate();
if (rate)
Settings.SoundInputRate = rate;
else
GUI.AutomaticInputRate = false;
}
Settings.SoundInputRate = CLAMP(Settings.SoundInputRate,8000, 48000);
Settings.SoundPlaybackRate = CLAMP(Settings.SoundPlaybackRate,8000, 48000);
S9xSetSoundMute(GUI.Mute);

View File

@ -4512,7 +4512,16 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
break;
}
}
if (WinGetAutomaticInputRate() < 1)
{
EnableWindow(GetDlgItem(hDlg, IDC_AUTOMATICINPUTRATE), 0);
GUI.AutomaticInputRate = false;
}
EnableWindow(GetDlgItem(hDlg, IDC_DYNRATECONTROL), GUI.SoundDriver == WIN_XAUDIO2_SOUND_DRIVER);
EnableWindow(GetDlgItem(hDlg, IDC_INRATEEDIT), !GUI.AutomaticInputRate);
EnableWindow(GetDlgItem(hDlg, IDC_INRATE), !GUI.AutomaticInputRate);
SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETRANGE,TRUE,MAKELONG(0,20));
SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETPOS,TRUE,(Settings.SoundInputRate - 31100)/50);
@ -4595,6 +4604,9 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
if(Settings.SoundSync)
SendDlgItemMessage(hDlg,IDC_SYNC_TO_SOUND_CPU,BM_SETCHECK,BST_CHECKED,0);
if (GUI.AutomaticInputRate)
SendDlgItemMessage(hDlg, IDC_AUTOMATICINPUTRATE, BM_SETCHECK, BST_CHECKED, 0);
return true;
case WM_PAINT:
{
@ -4666,6 +4678,8 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
int sliderVal=_tstoi(valTxt);
Settings.SoundInputRate = sliderVal>0?sliderVal:32000;
GUI.AutomaticInputRate = IsDlgButtonChecked(hDlg, IDC_AUTOMATICINPUTRATE);
// regular volume
Edit_GetText(GetDlgItem(hDlg, IDC_EDIT_VOLUME_REGULAR), valTxt, 10);
sliderVal = _tstoi(valTxt);
@ -4687,6 +4701,30 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
EndDialog(hDlg, 1);
return true;
case IDC_AUTOMATICINPUTRATE:
GUI.AutomaticInputRate = IsDlgButtonChecked(hDlg, IDC_AUTOMATICINPUTRATE);
EnableWindow(GetDlgItem(hDlg, IDC_INRATEEDIT), !GUI.AutomaticInputRate);
EnableWindow(GetDlgItem(hDlg, IDC_INRATE), !GUI.AutomaticInputRate);
if (GUI.AutomaticInputRate)
{
int newrate = WinGetAutomaticInputRate();
if (newrate)
{
Settings.SoundInputRate = newrate;
SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETPOS, TRUE, (Settings.SoundInputRate - 31100) / 50);
_sntprintf(valTxt, 10, TEXT("%d"), Settings.SoundInputRate);
Edit_SetText(GetDlgItem(hDlg, IDC_INRATEEDIT), valTxt);
}
else
{
GUI.AutomaticInputRate = false;
SendDlgItemMessage(hDlg, IDC_AUTOMATICINPUTRATE, BM_SETCHECK, BST_UNCHECKED, 0);
}
}
return true;
case IDC_DRIVER:
if(CBN_SELCHANGE==HIWORD(wParam))
{

View File

@ -388,6 +388,7 @@ struct sGUI {
bool Mute;
unsigned int VolumeRegular;
unsigned int VolumeTurbo;
bool AutomaticInputRate;
// used for sync sound synchronization
CRITICAL_SECTION SoundCritSect;
HANDLE SoundSyncEvent;