Merge pull request #792 from bladeoner/interpolation

Add Interpolation option and Add Gamemenu Audio
This commit is contained in:
dborth 2018-12-23 11:24:57 -07:00 committed by GitHub
commit 881fb1b6c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 194 additions and 21 deletions

View File

@ -130,6 +130,8 @@ extern const u8 icon_settings_network_png[];
extern const u32 icon_settings_network_png_size;
extern const u8 icon_settings_video_png[];
extern const u32 icon_settings_video_png_size;
extern const u8 icon_settings_audio_png[];
extern const u32 icon_settings_audio_png_size;
extern const u8 icon_settings_screenshot_png[];
extern const u32 icon_settings_screenshot_png_size;

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -41,6 +41,7 @@
#include "snes9x/snes9x.h"
#include "snes9x/fxemu.h"
#include "snes9x/memmap.h"
#include "snes9x/apu/apu.h"
#include "snes9x/cheats.h"
extern SCheatData Cheat;
@ -1886,6 +1887,7 @@ static int MenuGameSettings()
GuiImageData btnLargeOutlineOver(button_large_over_png);
GuiImageData iconMappings(icon_settings_mappings_png);
GuiImageData iconVideo(icon_settings_video_png);
GuiImageData iconAudio(icon_settings_audio_png);
GuiImageData iconController(icon_game_controllers_png);
GuiImageData iconCheats(icon_game_cheats_png);
GuiImageData iconScreenshot(icon_settings_screenshot_png);
@ -1902,7 +1904,7 @@ static int MenuGameSettings()
GuiImage mappingBtnIcon(&iconMappings);
GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight());
mappingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
mappingBtn.SetPosition(-125, 120);
mappingBtn.SetPosition(-200, 120);
mappingBtn.SetLabel(&mappingBtnTxt);
mappingBtn.SetImage(&mappingBtnImg);
mappingBtn.SetImageOver(&mappingBtnImgOver);
@ -1913,6 +1915,24 @@ static int MenuGameSettings()
mappingBtn.SetTrigger(trig2);
mappingBtn.SetEffectGrow();
GuiText audioBtnTxt("Audio", 22, (GXColor){0, 0, 0, 255});
audioBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20);
GuiImage audioBtnImg(&btnLargeOutline);
GuiImage audioBtnImgOver(&btnLargeOutlineOver);
GuiImage audioBtnIcon(&iconAudio);
GuiButton audioBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight());
audioBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
audioBtn.SetPosition(0, 120);
audioBtn.SetLabel(&audioBtnTxt);
audioBtn.SetImage(&audioBtnImg);
audioBtn.SetImageOver(&audioBtnImgOver);
audioBtn.SetIcon(&audioBtnIcon);
audioBtn.SetSoundOver(&btnSoundOver);
audioBtn.SetSoundClick(&btnSoundClick);
audioBtn.SetTrigger(trigA);
audioBtn.SetTrigger(trig2);
audioBtn.SetEffectGrow();
GuiText videoBtnTxt("Video", 22, (GXColor){0, 0, 0, 255});
videoBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20);
GuiImage videoBtnImg(&btnLargeOutline);
@ -1920,7 +1940,7 @@ static int MenuGameSettings()
GuiImage videoBtnIcon(&iconVideo);
GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight());
videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
videoBtn.SetPosition(125, 120);
videoBtn.SetPosition(200, 120);
videoBtn.SetLabel(&videoBtnTxt);
videoBtn.SetImage(&videoBtnImg);
videoBtn.SetImageOver(&videoBtnImgOver);
@ -2018,6 +2038,7 @@ static int MenuGameSettings()
w.Append(&titleTxt);
w.Append(&mappingBtn);
w.Append(&videoBtn);
w.Append(&audioBtn);
w.Append(&controllerBtn);
w.Append(&screenshotBtn);
w.Append(&cheatsBtn);
@ -2040,6 +2061,10 @@ static int MenuGameSettings()
{
menu = MENU_GAMESETTINGS_VIDEO;
}
else if(audioBtn.GetState() == STATE_CLICKED)
{
menu = MENU_GAMESETTINGS_AUDIO;
}
else if(controllerBtn.GetState() == STATE_CLICKED)
{
ControllerWindow();
@ -3333,6 +3358,102 @@ static int MenuSettingsVideo()
return menu;
}
/****************************************************************************
* MenuSettingsAudio
***************************************************************************/
static int MenuSettingsAudio()
{
int menu = MENU_NONE;
int ret;
int i = 0;
bool firstRun = true;
OptionList options;
sprintf(options.name[i++], "Interpolation");
options.length = i;
for(i=0; i < options.length; i++)
options.value[i][0] = 0;
GuiText titleTxt("Game Settings - Audio", 26, (GXColor){255, 255, 255, 255});
titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
titleTxt.SetPosition(50,50);
GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM);
GuiImageData btnOutline(button_png);
GuiImageData btnOutlineOver(button_over_png);
GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255});
GuiImage backBtnImg(&btnOutline);
GuiImage backBtnImgOver(&btnOutlineOver);
GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
backBtn.SetPosition(50, -35);
backBtn.SetLabel(&backBtnTxt);
backBtn.SetImage(&backBtnImg);
backBtn.SetImageOver(&backBtnImgOver);
backBtn.SetSoundOver(&btnSoundOver);
backBtn.SetSoundClick(&btnSoundClick);
backBtn.SetTrigger(trigA);
backBtn.SetTrigger(trig2);
backBtn.SetEffectGrow();
GuiOptionBrowser optionBrowser(552, 248, &options);
optionBrowser.SetPosition(0, 108);
optionBrowser.SetCol2Position(200);
optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
HaltGui();
GuiWindow w(screenwidth, screenheight);
w.Append(&backBtn);
mainWindow->Append(&optionBrowser);
mainWindow->Append(&w);
mainWindow->Append(&titleTxt);
ResumeGui();
while(menu == MENU_NONE)
{
usleep(THREAD_SLEEP);
ret = optionBrowser.GetClickedOption();
switch (ret)
{
case 0:
GCSettings.Interpolation++;
if (GCSettings.Interpolation > 2) {
GCSettings.Interpolation = 0;
}
switch(GCSettings.Interpolation)
{
case 0: Settings.InterpolationMethod = DSP_INTERPOLATION_GAUSSIAN; break;
case 1: Settings.InterpolationMethod = DSP_INTERPOLATION_LINEAR; break;
case 2: Settings.InterpolationMethod = DSP_INTERPOLATION_NONE; break;
}
break;
S9xReset();
}
if(ret >= 0 || firstRun)
{
firstRun = false;
switch(GCSettings.Interpolation)
{
case 0:
sprintf (options.value[0], "Gaussian (Accurate)"); break;
case 1:
sprintf (options.value[0], "Linear"); break;
case 2:
sprintf (options.value[0], "None"); break;
}
optionBrowser.TriggerUpdate();
}
if(backBtn.GetState() == STATE_CLICKED)
{
menu = MENU_GAMESETTINGS;
}
}
HaltGui();
mainWindow->Remove(&optionBrowser);
mainWindow->Remove(&w);
mainWindow->Remove(&titleTxt);
return menu;
}
/****************************************************************************
* MenuSettings
***************************************************************************/
@ -4158,6 +4279,9 @@ MainMenu (int menu)
case MENU_GAMESETTINGS_VIDEO:
currentMenu = MenuSettingsVideo();
break;
case MENU_GAMESETTINGS_AUDIO:
currentMenu = MenuSettingsAudio();
break;
case MENU_GAMESETTINGS_CHEATS:
currentMenu = MenuGameCheats();
break;

View File

@ -41,6 +41,7 @@ enum
MENU_GAMESETTINGS_MAPPINGS_CTRL,
MENU_GAMESETTINGS_MAPPINGS_MAP,
MENU_GAMESETTINGS_VIDEO,
MENU_GAMESETTINGS_AUDIO,
MENU_GAMESETTINGS_CHEATS
};

View File

@ -23,6 +23,8 @@
#include "input.h"
#include "button_mapping.h"
#include "snes9x/apu/apu.h"
struct SGCSettings GCSettings;
/****************************************************************************
@ -151,6 +153,7 @@ preparePrefsData ()
createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift));
createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift));
createXMLSetting("sfxOverclock", "SuperFX Overclock", toStr(GCSettings.sfxOverclock));
createXMLSetting("Interpolation", "Interpolation", toStr(GCSettings.Interpolation));
createXMLSection("Menu", "Menu Settings");
@ -335,6 +338,10 @@ decodePrefsData ()
loadXMLSetting(&GCSettings.xshift, "xshift");
loadXMLSetting(&GCSettings.yshift, "yshift");
// Audio Settings
loadXMLSetting(&GCSettings.Interpolation, "Interpolation");
// Emulation Settings
loadXMLSetting(&GCSettings.sfxOverclock, "sfxOverclock");
@ -489,6 +496,10 @@ DefaultSettings ()
Settings.SoundInputRate = 31950;
Settings.DynamicRateControl = true;
// Interpolation Method
GCSettings.Interpolation = 0;
Settings.InterpolationMethod = DSP_INTERPOLATION_GAUSSIAN;
// Graphics
Settings.Transparency = true;
Settings.SupportHiRes = true;

View File

@ -1,5 +1,7 @@
// snes_spc 0.9.0. http://www.slack.net/~ant/
#include "snes9x.h"
#include "SPC_DSP.h"
#include "blargg_endian.h"
@ -126,26 +128,45 @@ static short const gauss [512] =
};
inline int SPC_DSP::interpolate( voice_t const* v )
{
int out;
int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
switch (Settings.InterpolationMethod)
{
case 0: // raw
{
out = v->buf [(v->interp_pos >> 12) + v->buf_pos] & ~1;
break;
}
case 1: // linear interpolation
{
int fract = v->interp_pos & 0xFFF;
out = (0x1000 - fract) * in [0];
out += fract * in [1];
out >>= 12;
break;
}
default:
case 2: // Original gaussian filter
{
// Make pointers into gaussian based on fractional position between samples
int offset = v->interp_pos >> 4 & 0xFF;
short const* fwd = gauss + 255 - offset;
short const* rev = gauss + offset; // mirror left half of gaussian
int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
int out;
out = (fwd [ 0] * in [0]) >> 11;
out += (fwd [256] * in [1]) >> 11;
out += (rev [256] * in [2]) >> 11;
out = (int16_t) out;
out += (rev [ 0] * in [3]) >> 11;
CLAMP16( out );
out &= ~1;
break;
}
}
return out;
}
//// Counters
int const simple_counter_range = 2048 * 5 * 3; // 30720

View File

@ -47,4 +47,8 @@ void S9xUpdateDynamicRate (double rate);
extern SNES_SPC *spc_core;
#define DSP_INTERPOLATION_NONE 0
#define DSP_INTERPOLATION_LINEAR 1
#define DSP_INTERPOLATION_GAUSSIAN 2
#endif

View File

@ -242,6 +242,7 @@ struct SSettings
bool8 ReverseStereo;
bool8 Mute;
bool8 DynamicRateControl;
int32 InterpolationMethod;
bool8 SupportHiRes;
bool8 Transparency;

View File

@ -486,6 +486,13 @@ int main(int argc, char *argv[])
S9xResetSuperFX();
}
switch (GCSettings.Interpolation)
{
case 0: Settings.InterpolationMethod = DSP_INTERPOLATION_GAUSSIAN; break;
case 1: Settings.InterpolationMethod = DSP_INTERPOLATION_LINEAR; break;
case 2: Settings.InterpolationMethod = DSP_INTERPOLATION_NONE; break;
}
while (1) // main loop
{
if(!autoboot) {

View File

@ -119,6 +119,8 @@ struct SGCSettings{
int PreviewImage;
int sfxOverclock;
int Interpolation;
};
void ExitApp();