Add Interpolation option and Add Gamemenu Audio

This adds the following:
- A new gamemenu option called Audio
- Under the new gamemenu option an option Interpolation with three options:  Gaussian (Default), Linear, None
This commit is contained in:
bladeoner 2018-12-23 18:14:30 +01:00
parent 16c80360ce
commit 1479319bb5
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 u32 icon_settings_network_png_size;
extern const u8 icon_settings_video_png[]; extern const u8 icon_settings_video_png[];
extern const u32 icon_settings_video_png_size; 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 u8 icon_settings_screenshot_png[];
extern const u32 icon_settings_screenshot_png_size; 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/snes9x.h"
#include "snes9x/fxemu.h" #include "snes9x/fxemu.h"
#include "snes9x/memmap.h" #include "snes9x/memmap.h"
#include "snes9x/apu/apu.h"
#include "snes9x/cheats.h" #include "snes9x/cheats.h"
extern SCheatData Cheat; extern SCheatData Cheat;
@ -1886,6 +1887,7 @@ static int MenuGameSettings()
GuiImageData btnLargeOutlineOver(button_large_over_png); GuiImageData btnLargeOutlineOver(button_large_over_png);
GuiImageData iconMappings(icon_settings_mappings_png); GuiImageData iconMappings(icon_settings_mappings_png);
GuiImageData iconVideo(icon_settings_video_png); GuiImageData iconVideo(icon_settings_video_png);
GuiImageData iconAudio(icon_settings_audio_png);
GuiImageData iconController(icon_game_controllers_png); GuiImageData iconController(icon_game_controllers_png);
GuiImageData iconCheats(icon_game_cheats_png); GuiImageData iconCheats(icon_game_cheats_png);
GuiImageData iconScreenshot(icon_settings_screenshot_png); GuiImageData iconScreenshot(icon_settings_screenshot_png);
@ -1902,7 +1904,7 @@ static int MenuGameSettings()
GuiImage mappingBtnIcon(&iconMappings); GuiImage mappingBtnIcon(&iconMappings);
GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight());
mappingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); mappingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
mappingBtn.SetPosition(-125, 120); mappingBtn.SetPosition(-200, 120);
mappingBtn.SetLabel(&mappingBtnTxt); mappingBtn.SetLabel(&mappingBtnTxt);
mappingBtn.SetImage(&mappingBtnImg); mappingBtn.SetImage(&mappingBtnImg);
mappingBtn.SetImageOver(&mappingBtnImgOver); mappingBtn.SetImageOver(&mappingBtnImgOver);
@ -1913,6 +1915,24 @@ static int MenuGameSettings()
mappingBtn.SetTrigger(trig2); mappingBtn.SetTrigger(trig2);
mappingBtn.SetEffectGrow(); 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}); GuiText videoBtnTxt("Video", 22, (GXColor){0, 0, 0, 255});
videoBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); videoBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20);
GuiImage videoBtnImg(&btnLargeOutline); GuiImage videoBtnImg(&btnLargeOutline);
@ -1920,7 +1940,7 @@ static int MenuGameSettings()
GuiImage videoBtnIcon(&iconVideo); GuiImage videoBtnIcon(&iconVideo);
GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight());
videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
videoBtn.SetPosition(125, 120); videoBtn.SetPosition(200, 120);
videoBtn.SetLabel(&videoBtnTxt); videoBtn.SetLabel(&videoBtnTxt);
videoBtn.SetImage(&videoBtnImg); videoBtn.SetImage(&videoBtnImg);
videoBtn.SetImageOver(&videoBtnImgOver); videoBtn.SetImageOver(&videoBtnImgOver);
@ -2018,6 +2038,7 @@ static int MenuGameSettings()
w.Append(&titleTxt); w.Append(&titleTxt);
w.Append(&mappingBtn); w.Append(&mappingBtn);
w.Append(&videoBtn); w.Append(&videoBtn);
w.Append(&audioBtn);
w.Append(&controllerBtn); w.Append(&controllerBtn);
w.Append(&screenshotBtn); w.Append(&screenshotBtn);
w.Append(&cheatsBtn); w.Append(&cheatsBtn);
@ -2040,6 +2061,10 @@ static int MenuGameSettings()
{ {
menu = MENU_GAMESETTINGS_VIDEO; menu = MENU_GAMESETTINGS_VIDEO;
} }
else if(audioBtn.GetState() == STATE_CLICKED)
{
menu = MENU_GAMESETTINGS_AUDIO;
}
else if(controllerBtn.GetState() == STATE_CLICKED) else if(controllerBtn.GetState() == STATE_CLICKED)
{ {
ControllerWindow(); ControllerWindow();
@ -3333,6 +3358,102 @@ static int MenuSettingsVideo()
return menu; 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 * MenuSettings
***************************************************************************/ ***************************************************************************/
@ -4158,6 +4279,9 @@ MainMenu (int menu)
case MENU_GAMESETTINGS_VIDEO: case MENU_GAMESETTINGS_VIDEO:
currentMenu = MenuSettingsVideo(); currentMenu = MenuSettingsVideo();
break; break;
case MENU_GAMESETTINGS_AUDIO:
currentMenu = MenuSettingsAudio();
break;
case MENU_GAMESETTINGS_CHEATS: case MENU_GAMESETTINGS_CHEATS:
currentMenu = MenuGameCheats(); currentMenu = MenuGameCheats();
break; break;

View File

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

View File

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

View File

@ -1,5 +1,7 @@
// snes_spc 0.9.0. http://www.slack.net/~ant/ // snes_spc 0.9.0. http://www.slack.net/~ant/
#include "snes9x.h"
#include "SPC_DSP.h" #include "SPC_DSP.h"
#include "blargg_endian.h" #include "blargg_endian.h"
@ -127,25 +129,44 @@ static short const gauss [512] =
inline int SPC_DSP::interpolate( voice_t const* v ) 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 // Make pointers into gaussian based on fractional position between samples
int offset = v->interp_pos >> 4 & 0xFF; int offset = v->interp_pos >> 4 & 0xFF;
short const* fwd = gauss + 255 - offset; short const* fwd = gauss + 255 - offset;
short const* rev = gauss + offset; // mirror left half of gaussian short const* rev = gauss + offset; // mirror left half of gaussian
int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
int out;
out = (fwd [ 0] * in [0]) >> 11; out = (fwd [ 0] * in [0]) >> 11;
out += (fwd [256] * in [1]) >> 11; out += (fwd [256] * in [1]) >> 11;
out += (rev [256] * in [2]) >> 11; out += (rev [256] * in [2]) >> 11;
out = (int16_t) out; out = (int16_t) out;
out += (rev [ 0] * in [3]) >> 11; out += (rev [ 0] * in [3]) >> 11;
CLAMP16( out ); CLAMP16( out );
out &= ~1; out &= ~1;
break;
}
}
return out; return out;
} }
//// Counters //// Counters
int const simple_counter_range = 2048 * 5 * 3; // 30720 int const simple_counter_range = 2048 * 5 * 3; // 30720

View File

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

View File

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

View File

@ -486,6 +486,13 @@ int main(int argc, char *argv[])
S9xResetSuperFX(); 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 while (1) // main loop
{ {
if(!autoboot) { if(!autoboot) {

View File

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