From 91f0caa51666c49a9ffe6d2ecad7ba5d482dba6f Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 25 Nov 2017 00:10:44 +0100 Subject: [PATCH] win32: add volume control regular/turbo (closes #258) --- win32/CDirectSound.cpp | 11 +++++ win32/CDirectSound.h | 1 + win32/CXAudio2.cpp | 5 +++ win32/CXAudio2.h | 1 + win32/IS9xSoundOutput.h | 3 ++ win32/rsrc/resource.h | 11 ++++- win32/rsrc/snes9x.rc | 91 +++++++++++++++++++++++++++-------------- win32/wconfig.cpp | 2 + win32/win32_sound.cpp | 11 ++++- win32/wsnes9x.cpp | 53 +++++++++++++++++++++--- win32/wsnes9x.h | 2 + 11 files changed, 152 insertions(+), 39 deletions(-) diff --git a/win32/CDirectSound.cpp b/win32/CDirectSound.cpp index ca85290b..e30e06e2 100644 --- a/win32/CDirectSound.cpp +++ b/win32/CDirectSound.cpp @@ -441,6 +441,17 @@ bool CDirectSound::SetupSound() return (true); } +void CDirectSound::SetVolume(double volume) +{ + if (!initDone) + return; + + // convert percentage to hundredths of dB + LONG dbVolume = (LONG)(10 * log10(volume) * 2 * 100); + + lpDSB->SetVolume(dbVolume); +} + /* CDirectSound::ProcessSound Finishes core sample creation, syncronizes the buffer access. */ diff --git a/win32/CDirectSound.h b/win32/CDirectSound.h index 00c6b455..f48c71d2 100644 --- a/win32/CDirectSound.h +++ b/win32/CDirectSound.h @@ -242,6 +242,7 @@ public: bool InitSoundOutput(void) { return InitDirectSound(); } void DeInitSoundOutput(void) { DeInitDirectSound(); } bool SetupSound(void); + void SetVolume(double volume); }; diff --git a/win32/CXAudio2.cpp b/win32/CXAudio2.cpp index 39426c8a..99da6190 100644 --- a/win32/CXAudio2.cpp +++ b/win32/CXAudio2.cpp @@ -379,6 +379,11 @@ bool CXAudio2::SetupSound() return true; } +void CXAudio2::SetVolume(double volume) +{ + pSourceVoice->SetVolume(volume); +} + void CXAudio2::BeginPlayback() { pSourceVoice->Start(0); diff --git a/win32/CXAudio2.h b/win32/CXAudio2.h index e802fdd0..22fec44c 100644 --- a/win32/CXAudio2.h +++ b/win32/CXAudio2.h @@ -245,6 +245,7 @@ public: bool InitSoundOutput(void) { return InitXAudio2(); } void DeInitSoundOutput(void) { DeInitXAudio2(); } bool SetupSound(void); + void SetVolume(double volume); }; #endif \ No newline at end of file diff --git a/win32/IS9xSoundOutput.h b/win32/IS9xSoundOutput.h index 643580c9..281fcf0c 100644 --- a/win32/IS9xSoundOutput.h +++ b/win32/IS9xSoundOutput.h @@ -211,6 +211,9 @@ public: // (re)start playback virtual bool SetupSound()=0; + // SetVolume should set a new volume level (between 0.0 and 1.0) + virtual void SetVolume(double volume) = 0; + // ProcessSound should call S9xFinalizeSamples and queue new available samples into the // Host sound system. If the sound system is callback based, ProcessSound should do a syncronized // S9xFinalizeSamples and return. diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index b4398966..09d09853 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -2,6 +2,9 @@ // Microsoft Visual C++ generated include file. // Used by snes9x.rc // +#include "windows.h" +#define IDC_STATIC (-1) + #define IDR_RT_MANIFEST2 1 #define IDR_MENU_US 101 #define IDC_CURSOR_SCOPE 101 @@ -361,6 +364,10 @@ #define IDC_SHADER_HLSL_BROWSE 3016 #define IDC_SHADER_GROUP 3017 #define IDC_SHADER_GLSL_BROWSE 3018 +#define IDC_SLIDER_VOLUME_REGULAR 3018 +#define IDC_EDIT_VOLUME_REGULAR 3019 +#define IDC_SLIDER_VOLUME_TURBO 3020 +#define IDC_EDIT_VOLUME_TURBO 3021 #define ID_FILE_EXIT 40001 #define ID_WINDOW_HIDEMENUBAR 40004 #define ID_FILE_AVI_RECORDING 40005 @@ -504,9 +511,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 151 +#define _APS_NEXT_RESOURCE_VALUE 152 #define _APS_NEXT_COMMAND_VALUE 40178 -#define _APS_NEXT_CONTROL_VALUE 3018 +#define _APS_NEXT_CONTROL_VALUE 3022 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index cf0bf63b..db6d8c66 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -7,19 +7,17 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "windows.h" -#define IDC_STATIC (-1) + + ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources +// English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) -#endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // @@ -57,30 +55,39 @@ END // Dialog // -IDD_SOUND_OPTS DIALOGEX 0, 0, 300, 144 +IDD_SOUND_OPTS DIALOGEX 0, 0, 413, 144 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU CAPTION "Sound Settings" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - GROUPBOX "Sound Quality",IDC_STATIC,7,7,286,112,0,WS_EX_TRANSPARENT - DEFPUSHBUTTON "&OK",IDOK,178,120,56,16 - COMBOBOX IDC_DRIVER,65,24,106,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Sound Driver:",IDC_STATIC,13,25,49,11 - COMBOBOX IDC_BUFLEN,65,56,106,101,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Buffer Length:",IDC_STATIC,13,58,49,11 - COMBOBOX IDC_RATE,65,40,106,171,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Playback Rate:",IDC_STATIC,13,41,49,11 - CONTROL "&16 Bit playback",IDC_16BIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,24,96,10 - CONTROL "&Stereo",IDC_STEREO,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,183,38,93,10 - CONTROL "&Reverse Stereo",IDC_REV_STEREO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,53,94,10 + GROUPBOX "Sound Quality",IDC_STATIC,119,7,286,112,0,WS_EX_TRANSPARENT + DEFPUSHBUTTON "&OK",IDOK,288,122,56,16 + COMBOBOX IDC_DRIVER,177,24,106,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Sound Driver:",IDC_STATIC,125,25,49,11 + COMBOBOX IDC_BUFLEN,177,56,106,101,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + 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 "&16 Bit playback",IDC_16BIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,24,96,10 + CONTROL "&Stereo",IDC_STEREO,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,295,38,93,10 + CONTROL "&Reverse Stereo",IDC_REV_STEREO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,53,94,10 CONTROL "&Synchronize with sound core",IDC_SYNC_TO_SOUND_CPU, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,68,102,10 - PUSHBUTTON "&Cancel",IDCANCEL,237,120,56,16 - CONTROL "&Mute sound",IDC_MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,83,93,12 - CONTROL "Frame Advance mu&te",IDC_FAMT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,98,90,12 - CONTROL "",IDC_INRATE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | WS_TABSTOP,12,88,157,26 - EDITTEXT IDC_INRATEEDIT,65,74,105,12,ES_AUTOHSCROLL | ES_NUMBER - LTEXT "Input Rate:",IDC_INRATETEXT,14,74,46,11 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,68,102,10 + PUSHBUTTON "&Cancel",IDCANCEL,350,122,56,16 + CONTROL "&Mute sound",IDC_MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,83,93,12 + CONTROL "Frame Advance mu&te",IDC_FAMT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,295,98,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 + CONTROL "",IDC_SLIDER_VOLUME_REGULAR,"msctls_trackbar32",TBS_AUTOTICKS | TBS_VERT | TBS_BOTH | WS_TABSTOP | 0x400,22,25,23,73 + EDITTEXT IDC_EDIT_VOLUME_REGULAR,22,102,22,13,ES_AUTOHSCROLL + LTEXT "Regular",IDC_STATIC,22,17,49,10 + GROUPBOX "Volume",IDC_STATIC,7,7,105,112,0,WS_EX_TRANSPARENT + CONTROL "",IDC_SLIDER_VOLUME_TURBO,"msctls_trackbar32",TBS_AUTOTICKS | TBS_VERT | TBS_BOTH | WS_TABSTOP | 0x400,70,25,23,73 + EDITTEXT IDC_EDIT_VOLUME_TURBO,70,102,22,13,ES_AUTOHSCROLL + LTEXT "Fast-Forward",IDC_STATIC,62,17,49,10 + LTEXT "%",IDC_STATIC,47,104,8,8 + LTEXT "%",IDC_STATIC,95,104,8,8 END IDD_ROM_INFO DIALOGEX 0, 0, 233, 185 @@ -257,7 +264,7 @@ BEGIN RTEXT "New Value (dec or hex)",IDC_LABEL_CHEAT_BYTE,134,175,74,15,SS_CENTERIMAGE END -IDD_NETPLAYPROGRESS DIALOG 0, 0, 186, 61 +IDD_NETPLAYPROGRESS DIALOG 0, 0, 186, 61 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Dialog" FONT 8, "MS Sans Serif" @@ -354,7 +361,7 @@ BEGIN PUSHBUTTON "Sa&ve Watches",IDC_C_SAVEWATCH,215,142,52,16 END -IDD_CHEAT_FROM_SEARCH DIALOG 0, 0, 187, 143 +IDD_CHEAT_FROM_SEARCH DIALOG 0, 0, 187, 143 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU CAPTION "Cheat Details" FONT 8, "MS Sans Serif" @@ -559,14 +566,14 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN IDD_SOUND_OPTS, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 293 + RIGHTMARGIN, 406 TOPMARGIN, 7 - BOTTOMMARGIN, 136 + BOTTOMMARGIN, 138 END IDD_ROM_INFO, DIALOG @@ -697,17 +704,28 @@ END // IDB_OPENFOLDER BITMAP "openfold.bmp" + IDB_CLOSEDFOLDER BITMAP "closedfold.bmp" + IDB_CDDRIVE BITMAP "cdd.bmp" + IDB_NETDRIVE BITMAP "nd.bmp" + IDB_HARDDRIVE BITMAP "hd.bmp" + IDB_PAD BITMAP "pad.bmp" + IDB_REMOVABLE BITMAP "rd.bmp" + IDB_RAMDISK BITMAP "ram.bmp" + IDB_UNKNOWN BITMAP "ud.bmp" + IDB_LOCKEDFOLDER BITMAP "rodir.bmp" + IDB_HIDDENFOLDER BITMAP "hiddir.bmp" + ///////////////////////////////////////////////////////////////////////////// // // Icon @@ -782,7 +800,7 @@ END // Menu // -IDR_MENU_US MENU +IDR_MENU_US MENU BEGIN POPUP "&File" BEGIN @@ -959,7 +977,18 @@ BEGIN END END -#endif // English (U.S.) resources + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_SOUND_OPTS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +#endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index a4c29a68..e1418f98 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -981,6 +981,8 @@ void WinRegisterConfigItems() AddUIntC("SoundDriver", GUI.SoundDriver, 4, "0=Snes9xDirectSound, 4=XAudio2 (recommended)"); AddUIntC("BufferSize", GUI.SoundBufferSize, 64, "sound buffer size in ms - determines the internal and output sound buffer sizes. actual mixing is done every SoundBufferSize/4 samples"); AddBoolC("MuteFrameAdvance", GUI.FAMute, false, "true to prevent Snes9x from outputting sound when the Frame Advance command is in use"); + AddUIntC("VolumeRegular", GUI.VolumeRegular, 100, "volume during regular play (percentage between 0 and 100)"); + AddUIntC("VolumeTurbo", GUI.VolumeTurbo, 100, "volume during turbo mode (percentage between 0 and 100)"); #undef CATEGORY #define CATEGORY "Controls" AddBoolC("AllowLeftRight", Settings.UpAndDown, false, "true to allow left+right and up+down"); diff --git a/win32/win32_sound.cpp b/win32/win32_sound.cpp index 49e7ec90..efc673e4 100644 --- a/win32/win32_sound.cpp +++ b/win32/win32_sound.cpp @@ -266,6 +266,15 @@ bool8 S9xOpenSoundDevice () called by the sound core to process generated samples */ void S9xSoundCallback(void *data) -{ +{ + static double last_volume = 1.0; + + // only try to change volume if we actually need to switch it + double current_volume = (Settings.TurboMode ? GUI.VolumeTurbo : GUI.VolumeRegular) / 100.; + if (last_volume != current_volume) { + S9xSoundOutput->SetVolume(current_volume); + last_volume = current_volume; + } + S9xSoundOutput->ProcessSound(); } diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 11773341..e3202c36 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -4505,6 +4505,20 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETTICFREQ,1,0); _sntprintf(valTxt,10,TEXT("%d"),Settings.SoundInputRate); Edit_SetText(GetDlgItem(hDlg, IDC_INRATEEDIT),valTxt); + + // regular volume + SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME_REGULAR, TBM_SETRANGE, TRUE, MAKELONG(0, 100)); + SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME_REGULAR, TBM_SETPOS, TRUE, 100 - GUI.VolumeRegular); + SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME_REGULAR, TBM_SETTICFREQ, 10, 0); + _sntprintf(valTxt, 10, TEXT("%d"), GUI.VolumeRegular); + Edit_SetText(GetDlgItem(hDlg, IDC_EDIT_VOLUME_REGULAR), valTxt); + + // turbo volume + SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME_TURBO, TBM_SETRANGE, TRUE, MAKELONG(0, 100)); + SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME_TURBO, TBM_SETPOS, TRUE, 100 - GUI.VolumeTurbo); + SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME_TURBO, TBM_SETTICFREQ, 10, 0); + _sntprintf(valTxt, 10, TEXT("%d"), GUI.VolumeTurbo); + Edit_SetText(GetDlgItem(hDlg, IDC_EDIT_VOLUME_TURBO), valTxt); SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,0,(LPARAM)TEXT("8 KHz")); @@ -4577,13 +4591,32 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) } return true; case WM_HSCROLL: - hTrackbar = GetDlgItem(hDlg, IDC_INRATE); - if((HWND)lParam==hTrackbar) { - int trackValue = 31100 + 50 * SendDlgItemMessage(hDlg,IDC_INRATE,TBM_GETPOS,0,0); - _sntprintf(valTxt,10,TEXT("%d"),trackValue); - Edit_SetText(GetDlgItem(hDlg, IDC_INRATEEDIT),valTxt); + case WM_VSCROLL: + { + WORD loword_w = LOWORD(wParam); + if (loword_w == TB_THUMBPOSITION || loword_w == TB_THUMBTRACK || loword_w == TB_ENDTRACK) { + HWND trackHwnd = (HWND)lParam; + WORD scrollPos = SendMessage(trackHwnd, TBM_GETPOS, 0, 0); + int trackValue = 100 - scrollPos; + int editId = 0; + if (trackHwnd == GetDlgItem(hDlg, IDC_INRATE)) + { + trackValue = 31100 + 50 * scrollPos; + editId = IDC_INRATEEDIT; + } + else if (trackHwnd == GetDlgItem(hDlg, IDC_SLIDER_VOLUME_REGULAR)) + { + editId = IDC_EDIT_VOLUME_REGULAR; + } + else if (trackHwnd == GetDlgItem(hDlg, IDC_SLIDER_VOLUME_TURBO)) + { + editId = IDC_EDIT_VOLUME_TURBO; + } + _sntprintf(valTxt, 10, TEXT("%d"), trackValue); + Edit_SetText(GetDlgItem(hDlg, editId), valTxt); return true; } + } break; case WM_COMMAND: switch(LOWORD(wParam)) @@ -4619,6 +4652,16 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) int sliderVal=_tstoi(valTxt); Settings.SoundInputRate = sliderVal>0?sliderVal:32000; + // regular volume + Edit_GetText(GetDlgItem(hDlg, IDC_EDIT_VOLUME_REGULAR), valTxt, 10); + sliderVal = _tstoi(valTxt); + GUI.VolumeRegular = (sliderVal >= 0 && sliderVal <= 100) ? sliderVal : 100; + + // turbo volume + Edit_GetText(GetDlgItem(hDlg, IDC_EDIT_VOLUME_TURBO), valTxt, 10); + sliderVal = _tstoi(valTxt); + GUI.VolumeTurbo = (sliderVal >= 0 && sliderVal <= 100) ? sliderVal : 100; + WinSaveConfigFile(); // already done in WinProc on return diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 28da506a..3178193d 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -384,6 +384,8 @@ struct sGUI { int SoundDriver; int SoundBufferSize; bool Mute; + unsigned int VolumeRegular; + unsigned int VolumeTurbo; // used for sync sound synchronization CRITICAL_SECTION SoundCritSect; HANDLE SoundSyncEvent;