Audio: Added crossfeed option for stereo filters

This commit is contained in:
Souryo 2016-12-09 14:47:34 -05:00
parent 7fe6ae6a0d
commit 2fac266303
17 changed files with 140 additions and 4 deletions

View file

@ -434,6 +434,7 @@
<ClInclude Include="Caltron41.h" />
<ClInclude Include="Cc21.h" />
<ClInclude Include="ColorDreams46.h" />
<ClInclude Include="CrossFeedFilter.h" />
<ClInclude Include="DaouInfosys.h" />
<ClInclude Include="DebugBreakHelper.h" />
<ClInclude Include="DebuggerTypes.h" />
@ -752,6 +753,7 @@
<ClCompile Include="CodeDataLogger.cpp" />
<ClCompile Include="Console.cpp" />
<ClCompile Include="ControlManager.cpp" />
<ClCompile Include="CrossFeedFilter.cpp" />
<ClCompile Include="Debugger.cpp" />
<ClCompile Include="LabelManager.cpp" />
<ClCompile Include="MemoryAccessCounter.cpp" />

View file

@ -1105,6 +1105,9 @@
<ClInclude Include="DebugBreakHelper.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="CrossFeedFilter.h">
<Filter>Nes\APU\Filters</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -1293,5 +1296,8 @@
<ClCompile Include="Profiler.cpp">
<Filter>Misc</Filter>
</ClCompile>
<ClCompile Include="CrossFeedFilter.cpp">
<Filter>Nes\APU\Filters</Filter>
</ClCompile>
</ItemGroup>
</Project>

15
Core/CrossFeedFilter.cpp Normal file
View file

@ -0,0 +1,15 @@
#include "stdafx.h"
#include "CrossFeedFilter.h"
void CrossFeedFilter::ApplyFilter(int16_t *stereoBuffer, size_t sampleCount, int ratio)
{
for(int i = 0; i < sampleCount; i++) {
int16_t leftSample = stereoBuffer[0];
int16_t rightSample = stereoBuffer[1];
stereoBuffer[0] += rightSample * ratio / 100;
stereoBuffer[1] += leftSample * ratio / 100;
stereoBuffer += 2;
}
}

7
Core/CrossFeedFilter.h Normal file
View file

@ -0,0 +1,7 @@
#include "stdafx.h"
class CrossFeedFilter
{
public:
void ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, int ratio);
};

View file

@ -20,6 +20,7 @@ int32_t EmulationSettings::_stereoDelay = 0;
double EmulationSettings::_stereoAngle = 0;
double EmulationSettings::_reverbStrength = 0;
double EmulationSettings::_reverbDelay = 0;
uint32_t EmulationSettings::_crossFeedRatio = 0;
NesModel EmulationSettings::_model = NesModel::Auto;
PpuModel EmulationSettings::_ppuModel = PpuModel::Ppu2C02;

View file

@ -308,6 +308,7 @@ private:
static double _stereoAngle;
static double _reverbStrength;
static double _reverbDelay;
static uint32_t _crossFeedRatio;
static NesModel _model;
static PpuModel _ppuModel;
@ -489,6 +490,16 @@ public:
return _reverbDelay;
}
static void SetCrossFeedRatio(uint32_t ratio)
{
_crossFeedRatio = ratio;
}
static uint32_t GetCrossFeedRatio()
{
return _crossFeedRatio;
}
//0: No limit, Number: % of default speed (50/60fps)
static void SetEmulationSpeed(uint32_t emulationSpeed, bool displaySpeed = false)
{

View file

@ -2,6 +2,7 @@
#include "SoundMixer.h"
#include "APU.h"
#include "CPU.h"
#include "CrossFeedFilter.h"
IAudioDevice* SoundMixer::AudioDevice = nullptr;
unique_ptr<WaveRecorder> SoundMixer::_waveRecorder;
@ -107,6 +108,11 @@ void SoundMixer::PlayAudioBuffer(uint32_t time)
break;
}
if(isStereo && EmulationSettings::GetCrossFeedRatio() > 0) {
CrossFeedFilter filter;
filter.ApplyFilter(soundBuffer, sampleCount, EmulationSettings::GetCrossFeedRatio());
}
SoundMixer::AudioDevice->PlayBuffer(soundBuffer, (uint32_t)sampleCount, _sampleRate, isStereo);
if(_waveRecorder) {
auto lock = _waveRecorderLock.AcquireSafe();

View file

@ -38,6 +38,8 @@ namespace Mesen.GUI.Config
public bool ReverbEnabled = false;
public UInt32 ReverbStrength = 5;
public UInt32 ReverbDelay = 10;
public bool CrossFeedEnabled = false;
public UInt32 CrossFeedRatio = 0;
public AudioInfo()
{
@ -87,6 +89,12 @@ namespace Mesen.GUI.Config
} else {
InteropEmu.SetReverbParameters(0, 0);
}
if(audioInfo.CrossFeedEnabled) {
InteropEmu.SetCrossFeedRatio(audioInfo.CrossFeedRatio);
} else {
InteropEmu.SetCrossFeedRatio(0);
}
}
}
}

View file

@ -115,6 +115,7 @@
<Control ID="radStereoPanning">Panorámico</Control>
<Control ID="lblStereoDelayMs">ms</Control>
<Control ID="lblStereoPanningAngle">(Ángulo en grados)</Control>
<Control ID="chkCrossFeedEnabled">Enable Crossfeed:</Control>
<Control ID="grpReverb">Reverberación</Control>
<Control ID="chkReverbEnabled">Activar la reverberación</Control>
<Control ID="lblReverbDelay">Retraso:</Control>

View file

@ -115,6 +115,7 @@
<Control ID="radStereoPanning">Panoramique</Control>
<Control ID="lblStereoDelayMs">ms</Control>
<Control ID="lblStereoPanningAngle">(angle en degrés)</Control>
<Control ID="chkCrossFeedEnabled">Activer le crossfeed :</Control>
<Control ID="grpReverb">Réverbération</Control>
<Control ID="chkReverbEnabled">Activer la réverbération</Control>
<Control ID="lblReverbDelay">Délai :</Control>

View file

@ -115,6 +115,7 @@
<Control ID="radStereoPanning">パニング</Control>
<Control ID="lblStereoDelayMs">ミリ秒</Control>
<Control ID="lblStereoPanningAngle">(角度)</Control>
<Control ID="chkCrossFeedEnabled">クロスフィード:</Control>
<Control ID="grpReverb">残響</Control>
<Control ID="chkReverbEnabled">残響を有効にする</Control>
<Control ID="lblReverbDelay">ディレイ:</Control>

View file

@ -115,6 +115,7 @@
<Control ID="radStereoPanning">Панорамирование</Control>
<Control ID="lblStereoDelayMs">мс</Control>
<Control ID="lblStereoPanningAngle">угол в градусах</Control>
<Control ID="chkCrossFeedEnabled">Enable Crossfeed:</Control>
<Control ID="grpReverb">Реверберация</Control>
<Control ID="chkReverbEnabled">Включена</Control>
<Control ID="lblReverbDelay">Задержка :</Control>

View file

@ -115,6 +115,7 @@
<Control ID="radStereoPanning">Панорамування</Control>
<Control ID="lblStereoDelayMs">мс</Control>
<Control ID="lblStereoPanningAngle">кут в градусах</Control>
<Control ID="chkCrossFeedEnabled">Enable Crossfeed:</Control>
<Control ID="grpReverb">Відлуння</Control>
<Control ID="chkReverbEnabled">Включена</Control>
<Control ID="lblReverbDelay">Затримка :</Control>

View file

@ -72,6 +72,10 @@
this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();
this.nudStereoPanning = new System.Windows.Forms.NumericUpDown();
this.lblStereoPanningAngle = new System.Windows.Forms.Label();
this.flowLayoutPanel5 = new System.Windows.Forms.FlowLayoutPanel();
this.chkCrossFeedEnabled = new System.Windows.Forms.CheckBox();
this.nudCrossFeedRatio = new System.Windows.Forms.NumericUpDown();
this.lblCrossFeedRatio = new System.Windows.Forms.Label();
this.grpReverb = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
this.chkReverbEnabled = new System.Windows.Forms.CheckBox();
@ -102,6 +106,8 @@
((System.ComponentModel.ISupportInitialize)(this.nudStereoDelay)).BeginInit();
this.flowLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudStereoPanning)).BeginInit();
this.flowLayoutPanel5.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudCrossFeedRatio)).BeginInit();
this.grpReverb.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trkReverbDelay)).BeginInit();
@ -590,7 +596,7 @@
this.grpStereo.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpStereo.Location = new System.Drawing.Point(3, 3);
this.grpStereo.Name = "grpStereo";
this.grpStereo.Size = new System.Drawing.Size(457, 95);
this.grpStereo.Size = new System.Drawing.Size(457, 130);
this.grpStereo.TabIndex = 0;
this.grpStereo.TabStop = false;
this.grpStereo.Text = "Stereo";
@ -605,15 +611,18 @@
this.tlpStereoFilter.Controls.Add(this.radStereoDelay, 0, 1);
this.tlpStereoFilter.Controls.Add(this.radStereoPanning, 0, 2);
this.tlpStereoFilter.Controls.Add(this.flowLayoutPanel4, 1, 2);
this.tlpStereoFilter.Controls.Add(this.flowLayoutPanel5, 0, 4);
this.tlpStereoFilter.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpStereoFilter.Location = new System.Drawing.Point(3, 16);
this.tlpStereoFilter.Name = "tlpStereoFilter";
this.tlpStereoFilter.RowCount = 4;
this.tlpStereoFilter.RowCount = 6;
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpStereoFilter.Size = new System.Drawing.Size(451, 76);
this.tlpStereoFilter.Size = new System.Drawing.Size(451, 111);
this.tlpStereoFilter.TabIndex = 0;
//
// flowLayoutPanel3
@ -647,6 +656,7 @@
// radStereoDisabled
//
this.radStereoDisabled.AutoSize = true;
this.radStereoDisabled.Checked = true;
this.radStereoDisabled.Location = new System.Drawing.Point(3, 3);
this.radStereoDisabled.Name = "radStereoDisabled";
this.radStereoDisabled.Size = new System.Drawing.Size(66, 17);
@ -655,6 +665,7 @@
this.radStereoDisabled.Tag = "None";
this.radStereoDisabled.Text = "Disabled";
this.radStereoDisabled.UseVisualStyleBackColor = true;
this.radStereoDisabled.CheckedChanged += new System.EventHandler(this.radStereoDisabled_CheckedChanged);
//
// radStereoDelay
//
@ -718,11 +729,56 @@
this.lblStereoPanningAngle.TabIndex = 1;
this.lblStereoPanningAngle.Text = "(Angle in degrees)";
//
// flowLayoutPanel5
//
this.tlpStereoFilter.SetColumnSpan(this.flowLayoutPanel5, 2);
this.flowLayoutPanel5.Controls.Add(this.chkCrossFeedEnabled);
this.flowLayoutPanel5.Controls.Add(this.nudCrossFeedRatio);
this.flowLayoutPanel5.Controls.Add(this.lblCrossFeedRatio);
this.flowLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutPanel5.Location = new System.Drawing.Point(20, 85);
this.flowLayoutPanel5.Margin = new System.Windows.Forms.Padding(20, 0, 0, 0);
this.flowLayoutPanel5.Name = "flowLayoutPanel5";
this.flowLayoutPanel5.Size = new System.Drawing.Size(431, 25);
this.flowLayoutPanel5.TabIndex = 5;
//
// chkCrossFeedEnabled
//
this.chkCrossFeedEnabled.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.chkCrossFeedEnabled.AutoSize = true;
this.chkCrossFeedEnabled.Enabled = false;
this.chkCrossFeedEnabled.Location = new System.Drawing.Point(3, 5);
this.chkCrossFeedEnabled.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.chkCrossFeedEnabled.Name = "chkCrossFeedEnabled";
this.chkCrossFeedEnabled.Size = new System.Drawing.Size(112, 17);
this.chkCrossFeedEnabled.TabIndex = 1;
this.chkCrossFeedEnabled.Text = "Enable Crossfeed:";
this.chkCrossFeedEnabled.UseVisualStyleBackColor = true;
//
// nudCrossFeedRatio
//
this.nudCrossFeedRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.nudCrossFeedRatio.Enabled = false;
this.nudCrossFeedRatio.Location = new System.Drawing.Point(121, 3);
this.nudCrossFeedRatio.Name = "nudCrossFeedRatio";
this.nudCrossFeedRatio.Size = new System.Drawing.Size(42, 20);
this.nudCrossFeedRatio.TabIndex = 2;
//
// lblCrossFeedRatio
//
this.lblCrossFeedRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblCrossFeedRatio.AutoSize = true;
this.lblCrossFeedRatio.Location = new System.Drawing.Point(169, 6);
this.lblCrossFeedRatio.Name = "lblCrossFeedRatio";
this.lblCrossFeedRatio.Size = new System.Drawing.Size(15, 13);
this.lblCrossFeedRatio.TabIndex = 3;
this.lblCrossFeedRatio.Text = "%";
//
// grpReverb
//
this.grpReverb.Controls.Add(this.tableLayoutPanel5);
this.grpReverb.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpReverb.Location = new System.Drawing.Point(3, 104);
this.grpReverb.Location = new System.Drawing.Point(3, 139);
this.grpReverb.Name = "grpReverb";
this.grpReverb.Size = new System.Drawing.Size(457, 109);
this.grpReverb.TabIndex = 1;
@ -904,6 +960,9 @@
this.flowLayoutPanel4.ResumeLayout(false);
this.flowLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudStereoPanning)).EndInit();
this.flowLayoutPanel5.ResumeLayout(false);
this.flowLayoutPanel5.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudCrossFeedRatio)).EndInit();
this.grpReverb.ResumeLayout(false);
this.tableLayoutPanel5.ResumeLayout(false);
this.tableLayoutPanel5.PerformLayout();
@ -975,5 +1034,9 @@
private System.Windows.Forms.CheckBox chkReduceDmcPopping;
private System.Windows.Forms.PictureBox picLatencyWarning;
private System.Windows.Forms.Label lblLatencyWarning;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel5;
private System.Windows.Forms.CheckBox chkCrossFeedEnabled;
private System.Windows.Forms.NumericUpDown nudCrossFeedRatio;
private System.Windows.Forms.Label lblCrossFeedRatio;
}
}

View file

@ -58,6 +58,9 @@ namespace Mesen.GUI.Forms.Config
AddBinding("ReverbEnabled", chkReverbEnabled);
AddBinding("ReverbDelay", trkReverbDelay);
AddBinding("ReverbStrength", trkReverbStrength);
AddBinding("CrossFeedEnabled", chkCrossFeedEnabled);
AddBinding("CrossFeedRatio", nudCrossFeedRatio);
}
protected override void OnFormClosed(FormClosedEventArgs e)
@ -92,5 +95,11 @@ namespace Mesen.GUI.Forms.Config
picLatencyWarning.Visible = nudLatency.Value <= 30;
lblLatencyWarning.Visible = nudLatency.Value <= 30;
}
private void radStereoDisabled_CheckedChanged(object sender, EventArgs e)
{
chkCrossFeedEnabled.Enabled = !radStereoDisabled.Checked;
nudCrossFeedRatio.Enabled = !radStereoDisabled.Checked;
}
}
}

View file

@ -134,6 +134,8 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void SetStereoDelay(Int32 delay);
[DllImport(DLLPath)] public static extern void SetStereoPanningAngle(double angle);
[DllImport(DLLPath)] public static extern void SetReverbParameters(double strength, double delay);
[DllImport(DLLPath)] public static extern void SetCrossFeedRatio(UInt32 ratio);
[DllImport(DLLPath)] public static extern void SetNesModel(NesModel model);
[DllImport(DLLPath)] public static extern void SetEmulationSpeed(UInt32 emulationSpeed);
[DllImport(DLLPath)] public static extern void IncreaseEmulationSpeed();

View file

@ -330,6 +330,7 @@ namespace InteropEmu {
DllExport void __stdcall SetStereoDelay(int32_t delay) { EmulationSettings::SetStereoDelay(delay); }
DllExport void __stdcall SetStereoPanningAngle(double angle) { EmulationSettings::SetStereoPanningAngle(angle); }
DllExport void __stdcall SetReverbParameters(double strength, double delay) { EmulationSettings::SetReverbParameters(strength, delay); }
DllExport void __stdcall SetCrossFeedRatio(uint32_t ratio) { EmulationSettings::SetCrossFeedRatio(ratio); }
DllExport void __stdcall SetNesModel(uint32_t model) { EmulationSettings::SetNesModel((NesModel)model); }
DllExport void __stdcall SetOverscanDimensions(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) { EmulationSettings::SetOverscanDimensions(left, right, top, bottom); }