Audio: Added cubic interpolation option

This commit is contained in:
Sour 2020-04-28 17:56:57 -04:00
parent 45602ed530
commit 5ff456bc09
9 changed files with 64 additions and 28 deletions

View file

@ -20,6 +20,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
#include "Spc.h"
#include "EmuSettings.h"
#ifdef BLARGG_ENABLE_OPTIMIZER
#include BLARGG_ENABLE_OPTIMIZER
@ -131,6 +132,25 @@ static short const gauss [512] =
1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
};
inline int SPC_DSP::interpolate_cubic(voice_t const* v)
{
int const* in = &v->buf[(v->interp_pos >> 12) + v->buf_pos];
float v0 = in[0] / 32768.0;
float v1 = in[1] / 32768.0;
float v2 = in[2] / 32768.0;
float v3 = in[3] / 32768.0;
float a = (v3 - v2) - (v0 - v1);
float b = (v0 - v1) - a;
float c = v2 - v0;
float d = v1;
float ratio = (double)(v->interp_pos & 0xFFF) / 0x1000;
return (int)((d + ratio * (c + ratio * (b + ratio * a))) * 32768);
}
inline int SPC_DSP::interpolate( voice_t const* v )
{
// Make pointers into gaussian based on fractional position between samples
@ -451,7 +471,7 @@ VOICE_CLOCK( V3c )
// Gaussian interpolation
{
int output = interpolate( v );
int output = _settings->GetAudioConfig().EnableCubicInterpolation ? interpolate_cubic(v) : interpolate( v );
// Noise
if ( m.t_non & v->vbit )
@ -812,9 +832,10 @@ inline void SPC_DSP::writeRam(uint16_t addr, uint8_t value) { _spc->DspWriteRam(
//// Setup
void SPC_DSP::init( Spc *spc, void* ram_64k )
void SPC_DSP::init( Spc *spc, EmuSettings *settings, void* ram_64k )
{
_spc = spc;
_settings = settings;
m.ram = (uint8_t*) ram_64k;
mute_voices( 0 );
disable_surround( false );

View file

@ -8,6 +8,7 @@
extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); }
class Spc;
class EmuSettings;
class SPC_DSP {
public:
typedef BOOST::uint8_t uint8_t;
@ -15,7 +16,7 @@ public:
// Setup
// Initializes DSP and has it use the 64K RAM provided
void init( Spc* spc, void* ram_64k );
void init( Spc* spc, EmuSettings* settings, void* ram_64k );
// Sets destination for output samples. If out is NULL or out_size is 0,
// doesn't generate any.
@ -191,11 +192,13 @@ private:
};
state_t m;
Spc* _spc;
EmuSettings* _settings;
void init_counter();
void run_counters();
unsigned read_counter( int rate );
int interpolate_cubic(voice_t const* v);
int interpolate( voice_t const* v );
void run_envelope( voice_t* const v );
void decode_brr( voice_t* v );

View file

@ -119,6 +119,8 @@ struct AudioConfig
uint32_t SampleRate = 48000;
uint32_t AudioLatency = 60;
bool EnableCubicInterpolation = true;
bool MuteSoundInBackground = false;
bool ReduceSoundInBackground = true;
bool ReduceSoundInFastForward = false;

View file

@ -25,7 +25,7 @@ Spc::Spc(Console* console)
_dsp.reset(new SPC_DSP());
#ifndef DUMMYSPC
_dsp->init(this, _ram);
_dsp->init(this, _console->GetSettings().get(), _ram);
#endif
_dsp->reset();
_dsp->set_output(_soundBuffer, Spc::SampleBufferSize >> 1);

View file

@ -42,6 +42,7 @@ static constexpr const char* MesenNtscFilter = "mesen-s_ntsc_filter";
static constexpr const char* MesenRegion = "mesen-s_region";
static constexpr const char* MesenAspectRatio = "mesen-s_aspect_ratio";
static constexpr const char* MesenBlendHighRes = "mesen-s_blend_high_res";
static constexpr const char* MesenCubicInterpolation = "mesen-s_cubic_interpolation";
static constexpr const char* MesenOverscanVertical = "mesen-s_overscan_vertical";
static constexpr const char* MesenOverscanHorizontal = "mesen-s_overscan_horizontal";
static constexpr const char* MesenRamState = "mesen-s_ramstate";
@ -114,6 +115,7 @@ extern "C" {
{ MesenOverscanHorizontal, "Horizontal Overscan; None|8px|16px" },
{ MesenAspectRatio, "Aspect Ratio; Auto|No Stretching|NTSC|PAL|4:3|16:9" },
{ MesenBlendHighRes, "Blend Hi-Res Modes; disabled|enabled" },
{ MesenCubicInterpolation, "Cubic Interpolation (Audio); disabled|enabled" },
{ MesenOverclock, "Overclock; None|Low|Medium|High|Very High" },
{ MesenOverclockType, "Overclock Type; Before NMI|After NMI" },
{ MesenSuperFxOverclock, "Super FX Clock Speed; 100%|200%|300%|400%|500%|1000%" },
@ -208,6 +210,7 @@ extern "C" {
{
struct retro_variable var = { };
VideoConfig video = _console->GetSettings()->GetVideoConfig();
AudioConfig audio = _console->GetSettings()->GetAudioConfig();
EmulationConfig emulation = _console->GetSettings()->GetEmulationConfig();
InputConfig input = _console->GetSettings()->GetInputConfig();
video.Brightness = 0;
@ -378,6 +381,11 @@ extern "C" {
string value = string(var.value);
video.BlendHighResolutionModes = (value == "enabled");
}
if(readVariable(MesenCubicInterpolation, var)) {
string value = string(var.value);
audio.EnableCubicInterpolation = (value == "enabled");
}
auto getKeyCode = [=](int port, int retroKey) {
return (port << 8) | (retroKey + 1);
@ -412,6 +420,7 @@ extern "C" {
_console->GetSettings()->SetVideoConfig(video);
_console->GetSettings()->SetEmulationConfig(emulation);
_console->GetSettings()->SetInputConfig(input);
_console->GetSettings()->SetAudioConfig(audio);
retro_system_av_info avInfo = {};
_renderer->GetSystemAudioVideoInfo(avInfo);

View file

@ -18,6 +18,8 @@ namespace Mesen.GUI.Config
[ValidValues(11025, 22050, 32000, 44100, 48000, 96000)] public UInt32 SampleRate = 48000;
[MinMax(15, 300)] public UInt32 AudioLatency = 60;
[MarshalAs(UnmanagedType.I1)] public bool EnableCubicInterpolation = true;
[MarshalAs(UnmanagedType.I1)] public bool MuteSoundInBackground = false;
[MarshalAs(UnmanagedType.I1)] public bool ReduceSoundInBackground = true;
[MarshalAs(UnmanagedType.I1)] public bool ReduceSoundInFastForward = false;

View file

@ -119,32 +119,13 @@
<Control ID="tpgGeneral">General</Control>
<Control ID="tpgAdvanced">Advanced</Control>
<Control ID="chkDisableDynamicSampleRate">Disable dynamic sample rate</Control>
<Control ID="chkSwapDutyCycles">Swap square channels duty cycles (Mimics old clones)</Control>
<Control ID="chkSilenceTriangleHighFreq">Mute ultrasonic frequencies on triangle channel (reduces popping)</Control>
<Control ID="chkReduceDmcPopping">Reduce popping sounds on the DMC channel</Control>
<Control ID="chkDisableNoiseModeFlag">Disable noise channel mode flag</Control>
<Control ID="tpgEffects">Effects</Control>
<Control ID="grpStereo">Stereo</Control>
<Control ID="radStereoDisabled">Disabled</Control>
<Control ID="radStereoDelay">Delay</Control>
<Control ID="radStereoPanning">Panning</Control>
<Control ID="lblStereoDelayMs">ms</Control>
<Control ID="lblStereoPanningAngle">(Angle in degrees)</Control>
<Control ID="radStereoCombFilter">Comb Filter</Control>
<Control ID="lblStereoCombFilterMs">ms</Control>
<Control ID="lblStereoCombFilterDelay">Delay:</Control>
<Control ID="lblStereoCombFilterStrength">Strength:</Control>
<Control ID="chkCrossFeedEnabled">Enable Crossfeed:</Control>
<Control ID="grpReverb">Reverb</Control>
<Control ID="chkReverbEnabled">Enable Reverb</Control>
<Control ID="lblReverbDelay">Delay:</Control>
<Control ID="lblReverbStrength">Strength:</Control>
<Control ID="chkMuteSoundInBackground">Mute sound when in background</Control>
<Control ID="chkReduceSoundInBackground">Reduce volume when in background</Control>
<Control ID="chkReduceSoundInFastForward">Reduce volume during fast forward/rewind</Control>
<Control ID="trkVolumeReduction">Volume Reduction (%)</Control>
<Control ID="lblVolumeReductionSettings">Volume Reduction Settings</Control>
<Control ID="chkEnableAudio">Enable Audio</Control>
<Control ID="chkEnableCubicInterpolation">Enable cubic interpolation</Control>
<Control ID="lblSampleRate">Sample Rate:</Control>
<Control ID="lblLatencyMs">ms</Control>
<Control ID="lblLatencyWarning">Low values may cause sound problems</Control>

View file

@ -76,6 +76,7 @@
this.tpgAdvanced = new System.Windows.Forms.TabPage();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.chkDisableDynamicSampleRate = new Mesen.GUI.Controls.ctrlRiskyOption();
this.chkEnableCubicInterpolation = new System.Windows.Forms.CheckBox();
this.tabControl1.SuspendLayout();
this.tpgGeneral.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
@ -298,6 +299,7 @@
0,
0,
0});
this.nudLatency.IsHex = false;
this.nudLatency.Location = new System.Drawing.Point(3, 3);
this.nudLatency.Maximum = new decimal(new int[] {
300,
@ -890,11 +892,13 @@
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.chkDisableDynamicSampleRate, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.chkDisableDynamicSampleRate, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.chkEnableCubicInterpolation, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowCount = 3;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(478, 346);
@ -903,12 +907,22 @@
// chkDisableDynamicSampleRate
//
this.chkDisableDynamicSampleRate.Checked = false;
this.chkDisableDynamicSampleRate.Location = new System.Drawing.Point(0, 0);
this.chkDisableDynamicSampleRate.Location = new System.Drawing.Point(0, 23);
this.chkDisableDynamicSampleRate.Name = "chkDisableDynamicSampleRate";
this.chkDisableDynamicSampleRate.Size = new System.Drawing.Size(463, 24);
this.chkDisableDynamicSampleRate.TabIndex = 5;
this.chkDisableDynamicSampleRate.Text = "Disable dynamic sample rate";
//
// chkEnableCubicInterpolation
//
this.chkEnableCubicInterpolation.AutoSize = true;
this.chkEnableCubicInterpolation.Location = new System.Drawing.Point(3, 3);
this.chkEnableCubicInterpolation.Name = "chkEnableCubicInterpolation";
this.chkEnableCubicInterpolation.Size = new System.Drawing.Size(148, 17);
this.chkEnableCubicInterpolation.TabIndex = 6;
this.chkEnableCubicInterpolation.Text = "Enable cubic interpolation";
this.chkEnableCubicInterpolation.UseVisualStyleBackColor = true;
//
// frmAudioConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -938,6 +952,7 @@
this.tlpEqualizer.ResumeLayout(false);
this.tpgAdvanced.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -994,5 +1009,6 @@
private System.Windows.Forms.TabPage tpgAdvanced;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private Controls.ctrlRiskyOption chkDisableDynamicSampleRate;
}
private System.Windows.Forms.CheckBox chkEnableCubicInterpolation;
}
}

View file

@ -30,6 +30,8 @@ namespace Mesen.GUI.Forms.Config
AddBinding(nameof(AudioConfig.SampleRate), cboSampleRate);
AddBinding(nameof(AudioConfig.AudioDevice), cboAudioDevice);
AddBinding(nameof(AudioConfig.DisableDynamicSampleRate), chkDisableDynamicSampleRate);
AddBinding(nameof(AudioConfig.EnableCubicInterpolation), chkEnableCubicInterpolation);
AddBinding(nameof(AudioConfig.EnableEqualizer), chkEnableEqualizer);
AddBinding(nameof(AudioConfig.Band1Gain), trkBand1Gain);