diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 0db3a1ed..6e58dec4 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -561,6 +561,7 @@ + @@ -1050,6 +1051,7 @@ Create Create + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 62177a8b..6f402fce 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -1471,6 +1471,9 @@ Rewinder + + Nes\APU\Filters + @@ -1761,5 +1764,8 @@ Rewinder + + Nes\APU\Filters + \ No newline at end of file diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 24655093..30bf4737 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -542,6 +542,20 @@ enum class StereoFilter None = 0, Delay = 1, Panning = 2, + CombFilter = 3, +}; + +struct AudioFilterSettings +{ + StereoFilter StereoFilter = StereoFilter::None; + double Angle = 0; + int32_t Delay = 0; + int32_t Strength = 0; + + double ReverbDelay = 0; + double ReverbStrength = 0; + + int32_t CrossFadeRatio = 0; }; enum class InputDisplayPosition @@ -618,12 +632,7 @@ private: double _masterVolume = 1.0; double _volumeReduction = 0.75; uint32_t _sampleRate = 48000; - StereoFilter _stereoFilter = StereoFilter::None; - int32_t _stereoDelay = 0; - double _stereoAngle = 0; - double _reverbStrength = 0; - double _reverbDelay = 0; - uint32_t _crossFeedRatio = 0; + AudioFilterSettings _audioFilterSettings; NesModel _model = NesModel::Auto; PpuModel _ppuModel = PpuModel::Ppu2C02; @@ -870,60 +879,15 @@ public: _audioSettingsChanged = true; } - void SetStereoFilter(StereoFilter stereoFilter) + void SetAudioFilterSettings(AudioFilterSettings settings) { - _stereoFilter = stereoFilter; + _audioFilterSettings = settings; _audioSettingsChanged = true; } - void SetStereoDelay(int32_t delay) + AudioFilterSettings GetAudioFilterSettings() { - _stereoDelay = delay; - _audioSettingsChanged = true; - } - - void SetStereoPanningAngle(double angle) - { - _stereoAngle = angle; - _audioSettingsChanged = true; - } - - void SetReverbParameters(double strength, double delay) - { - _reverbStrength = strength; - _reverbDelay = delay; - _audioSettingsChanged = true; - } - - StereoFilter GetStereoFilter() - { - return _stereoFilter; - } - - int32_t GetStereoDelay() - { - return _stereoDelay; - } - - double GetStereoPanningAngle() - { - return _stereoAngle; - } - - double GetReverbStrength() - { - return _reverbStrength; - } - - double GetReverbDelay() - { - return _reverbDelay; - } - - void SetCrossFeedRatio(uint32_t ratio) - { - _crossFeedRatio = ratio; - _audioSettingsChanged = true; + return _audioFilterSettings; } bool NeedAudioSettingsUpdate() @@ -934,12 +898,7 @@ public: } return value; } - - uint32_t GetCrossFeedRatio() - { - return _crossFeedRatio; - } - + //0: No limit, Number: % of default speed (50/60fps) void SetEmulationSpeed(uint32_t emulationSpeed, bool displaySpeed = false) { diff --git a/Core/SoundMixer.cpp b/Core/SoundMixer.cpp index 1f4d346d..492a4f22 100644 --- a/Core/SoundMixer.cpp +++ b/Core/SoundMixer.cpp @@ -142,20 +142,23 @@ void SoundMixer::PlayAudioBuffer(uint32_t time) } } - if(_settings->GetReverbStrength() > 0) { - _reverbFilter.ApplyFilter(_outputBuffer, sampleCount, _sampleRate, _settings->GetReverbStrength(), _settings->GetReverbDelay()); + AudioFilterSettings filterSettings = _settings->GetAudioFilterSettings(); + + if(filterSettings.ReverbStrength > 0) { + _reverbFilter.ApplyFilter(_outputBuffer, sampleCount, _sampleRate, filterSettings.ReverbStrength, filterSettings.ReverbDelay); } else { _reverbFilter.ResetFilter(); } - switch(_settings->GetStereoFilter()) { + switch(filterSettings.StereoFilter) { case StereoFilter::None: break; - case StereoFilter::Delay: _stereoDelay.ApplyFilter(_outputBuffer, sampleCount, _sampleRate, _settings->GetStereoDelay()); break; - case StereoFilter::Panning: _stereoPanning.ApplyFilter(_outputBuffer, sampleCount, _settings->GetStereoPanningAngle()); break; + case StereoFilter::Delay: _stereoDelay.ApplyFilter(_outputBuffer, sampleCount, _sampleRate, filterSettings.Delay); break; + case StereoFilter::Panning: _stereoPanning.ApplyFilter(_outputBuffer, sampleCount, filterSettings.Angle); break; + case StereoFilter::CombFilter: _stereoCombFilter.ApplyFilter(_outputBuffer, sampleCount, _sampleRate, filterSettings.Delay, filterSettings.Strength); break; } - if(_settings->GetCrossFeedRatio() > 0) { - _crossFeedFilter.ApplyFilter(_outputBuffer, sampleCount, _settings->GetCrossFeedRatio()); + if(filterSettings.CrossFadeRatio > 0) { + _crossFeedFilter.ApplyFilter(_outputBuffer, sampleCount, filterSettings.CrossFadeRatio); } if(rewindManager && rewindManager->SendAudio(_outputBuffer, (uint32_t)sampleCount, _sampleRate)) { diff --git a/Core/SoundMixer.h b/Core/SoundMixer.h index e82183d2..2bf2135a 100644 --- a/Core/SoundMixer.h +++ b/Core/SoundMixer.h @@ -8,6 +8,7 @@ #include "Snapshotable.h" #include "StereoPanningFilter.h" #include "StereoDelayFilter.h" +#include "StereoCombFilter.h" #include "ReverbFilter.h" #include "CrossFeedFilter.h" @@ -47,6 +48,7 @@ private: LowPassFilter _lowPassFilter; StereoPanningFilter _stereoPanning; StereoDelayFilter _stereoDelay; + StereoCombFilter _stereoCombFilter; ReverbFilter _reverbFilter; int16_t _previousOutputLeft = 0; diff --git a/Core/StereoCombFilter.cpp b/Core/StereoCombFilter.cpp new file mode 100644 index 00000000..f9af7570 --- /dev/null +++ b/Core/StereoCombFilter.cpp @@ -0,0 +1,29 @@ +#include "stdafx.h" +#include "StereoCombFilter.h" + +void StereoCombFilter::ApplyFilter(int16_t * stereoBuffer, size_t sampleCount, uint32_t sampleRate, int32_t delay, uint32_t strength) +{ + size_t delaySampleCount = (int32_t)((double)delay / 1000 * sampleRate); + if(delaySampleCount != _lastDelay) { + _delayedSamplesLeft.clear(); + _delayedSamplesRight.clear(); + for(size_t i = 0; i < delaySampleCount; i++) { + _delayedSamplesLeft.push_back(0); + _delayedSamplesRight.push_back(0); + } + } + _lastDelay = delaySampleCount; + + double ratio = strength == 0 ? 0 : strength / 100.0; + for(size_t i = 0; i < sampleCount * 2; i += 2) { + _delayedSamplesLeft.push_back(stereoBuffer[i]); + _delayedSamplesRight.push_back(stereoBuffer[i + 1]); + + int16_t delayedSample = (_delayedSamplesRight.front() + _delayedSamplesLeft.front()) / 2; + int16_t monoSample = (stereoBuffer[i] + stereoBuffer[i + 1]) / 2; + stereoBuffer[i] = monoSample + (int16_t)(delayedSample * ratio); + stereoBuffer[i + 1] = monoSample - (int16_t)(delayedSample * ratio); + _delayedSamplesLeft.pop_front(); + _delayedSamplesRight.pop_front(); + } +} diff --git a/Core/StereoCombFilter.h b/Core/StereoCombFilter.h new file mode 100644 index 00000000..869cfcdf --- /dev/null +++ b/Core/StereoCombFilter.h @@ -0,0 +1,13 @@ +#pragma once +#include "stdafx.h" +#include + +class StereoCombFilter +{ + std::deque _delayedSamplesLeft; + std::deque _delayedSamplesRight; + size_t _lastDelay = 0; + +public: + void ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, uint32_t sampleRate, int32_t delay, uint32_t strength); +}; \ No newline at end of file diff --git a/Core/StereoDelayFilter.cpp b/Core/StereoDelayFilter.cpp index 9e3e3b85..3f1536d2 100644 --- a/Core/StereoDelayFilter.cpp +++ b/Core/StereoDelayFilter.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include #include "StereoDelayFilter.h" void StereoDelayFilter::ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, uint32_t sampleRate, int32_t stereoDelay) diff --git a/Core/StereoDelayFilter.h b/Core/StereoDelayFilter.h index 28d83c55..838b96ef 100644 --- a/Core/StereoDelayFilter.h +++ b/Core/StereoDelayFilter.h @@ -1,8 +1,6 @@ #pragma once #include "stdafx.h" #include -#include -#include "EmulationSettings.h" class StereoDelayFilter { diff --git a/GUI.NET/Config/AudioInfo.cs b/GUI.NET/Config/AudioInfo.cs index 460445d7..bcef692d 100644 --- a/GUI.NET/Config/AudioInfo.cs +++ b/GUI.NET/Config/AudioInfo.cs @@ -49,9 +49,13 @@ namespace Mesen.GUI.Config public InteropEmu.StereoFilter StereoFilter; [MinMax(0, 100)] public Int32 StereoDelay = 15; [MinMax(-180, 180)] public Int32 StereoPanningAngle = 15; + [MinMax(1, 100)] public Int32 StereoCombFilterDelay = 5; + [MinMax(1, 200)] public Int32 StereoCombFilterStrength = 100; + public bool ReverbEnabled = false; [MinMax(1, 10)] public UInt32 ReverbStrength = 5; [MinMax(1, 30)] public UInt32 ReverbDelay = 10; + public bool CrossFeedEnabled = false; [MinMax(0, 100)] public UInt32 CrossFeedRatio = 0; @@ -183,21 +187,15 @@ namespace Mesen.GUI.Config InteropEmu.SetFlag(EmulationFlags.ReduceDmcPopping, audioInfo.ReduceDmcPopping); InteropEmu.SetFlag(EmulationFlags.DisableNoiseModeFlag, audioInfo.DisableNoiseModeFlag); - InteropEmu.SetStereoFilter(audioInfo.StereoFilter); - InteropEmu.SetStereoPanningAngle((double)audioInfo.StereoPanningAngle/180*Math.PI); - InteropEmu.SetStereoDelay(audioInfo.StereoDelay); - - if(audioInfo.ReverbEnabled) { - InteropEmu.SetReverbParameters(audioInfo.ReverbStrength/10.0, audioInfo.ReverbDelay/10.0); - } else { - InteropEmu.SetReverbParameters(0, 0); - } - - if(audioInfo.CrossFeedEnabled) { - InteropEmu.SetCrossFeedRatio(audioInfo.CrossFeedRatio); - } else { - InteropEmu.SetCrossFeedRatio(0); - } + InteropEmu.SetAudioFilterSettings(new InteropEmu.AudioFilterSettings() { + StereoFilter = audioInfo.StereoFilter, + Angle = (double)audioInfo.StereoPanningAngle / 180 * Math.PI, + Delay = audioInfo.StereoFilter == InteropEmu.StereoFilter.Delay ? audioInfo.StereoDelay : audioInfo.StereoCombFilterDelay, + Strength = audioInfo.StereoCombFilterStrength, + ReverbDelay = audioInfo.ReverbEnabled ? audioInfo.ReverbDelay / 10.0 : 0, + ReverbStrength = audioInfo.ReverbEnabled ? audioInfo.ReverbStrength / 10.0 : 0, + CrossFeedRatio = audioInfo.CrossFeedEnabled ? (int)audioInfo.CrossFeedRatio : 0 + }); } } diff --git a/GUI.NET/Dependencies/resources.ca.xml b/GUI.NET/Dependencies/resources.ca.xml index 06bf06b0..76c33132 100644 --- a/GUI.NET/Dependencies/resources.ca.xml +++ b/GUI.NET/Dependencies/resources.ca.xml @@ -135,6 +135,10 @@ Panoràmic ms (angle en graus) + Comb Filter + ms + Retard: + Força: Activa la mescla de canals: Reverberació Activa la reverberació diff --git a/GUI.NET/Dependencies/resources.en.xml b/GUI.NET/Dependencies/resources.en.xml index 78903b30..19587535 100644 --- a/GUI.NET/Dependencies/resources.en.xml +++ b/GUI.NET/Dependencies/resources.en.xml @@ -135,6 +135,10 @@ Panning ms (Angle in degrees) + Comb Filter + ms + Delay: + Strength: Enable Crossfeed: Reverb Enable Reverb diff --git a/GUI.NET/Dependencies/resources.es.xml b/GUI.NET/Dependencies/resources.es.xml index 251c5c37..8a13afe5 100644 --- a/GUI.NET/Dependencies/resources.es.xml +++ b/GUI.NET/Dependencies/resources.es.xml @@ -134,6 +134,10 @@ Panorámico ms (Ángulo en grados) + Comb Filter + ms + Retraso: + Fuerza: Activar mezcla de canales: Reverberación Activar la reverberación diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index f4814b79..7309df6e 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -135,6 +135,10 @@ Panoramique ms (angle en degrés) + Filtre en peigne + ms + Délai : + Force : Activer le crossfeed : Réverbération Activer la réverbération diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index 48d552ff..b6f42c16 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -136,6 +136,10 @@ パニング ミリ秒 (角度) + コムフィルタ + ミリ秒 + ディレイ: + 強度: クロスフィード: 残響 残響を有効にする diff --git a/GUI.NET/Dependencies/resources.pt.xml b/GUI.NET/Dependencies/resources.pt.xml index 8095a8f1..a9a4e125 100644 --- a/GUI.NET/Dependencies/resources.pt.xml +++ b/GUI.NET/Dependencies/resources.pt.xml @@ -134,6 +134,10 @@ Panorâmico ms (Ângulo em graus) + Comb Filter + ms + Atraso: + Força: Ativar mistura de canais Ressonância Ativar a ressonância diff --git a/GUI.NET/Dependencies/resources.ru.xml b/GUI.NET/Dependencies/resources.ru.xml index 1aeb8960..415bbbba 100644 --- a/GUI.NET/Dependencies/resources.ru.xml +++ b/GUI.NET/Dependencies/resources.ru.xml @@ -134,6 +134,10 @@ Панорамирование мс угол в градусах + Comb Filter + мс + Задержка : + Сила : Enable Crossfeed: Реверберация Включена diff --git a/GUI.NET/Dependencies/resources.uk.xml b/GUI.NET/Dependencies/resources.uk.xml index 991089ee..273bddf7 100644 --- a/GUI.NET/Dependencies/resources.uk.xml +++ b/GUI.NET/Dependencies/resources.uk.xml @@ -134,6 +134,10 @@ Панорамування мс кут в градусах + Comb Filter + мс + Затримка : + Сила : Включити кільцювання: Відлуння Включена diff --git a/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs b/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs index 06f54653..64bb96bc 100644 --- a/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs @@ -112,6 +112,7 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); this.grpStereo = new System.Windows.Forms.GroupBox(); this.tlpStereoFilter = new System.Windows.Forms.TableLayoutPanel(); + this.radStereoCombFilter = new System.Windows.Forms.RadioButton(); this.lblStereoDelayMs = new System.Windows.Forms.Label(); this.lblStereoPanningAngle = new System.Windows.Forms.Label(); this.radStereoDisabled = new System.Windows.Forms.RadioButton(); @@ -119,6 +120,13 @@ namespace Mesen.GUI.Forms.Config this.radStereoPanning = new System.Windows.Forms.RadioButton(); this.nudStereoDelay = new Mesen.GUI.Controls.MesenNumericUpDown(); this.nudStereoPanning = new Mesen.GUI.Controls.MesenNumericUpDown(); + this.tableLayoutPanel9 = new System.Windows.Forms.TableLayoutPanel(); + this.nudStereoCombFilterStrength = new Mesen.GUI.Controls.MesenNumericUpDown(); + this.lblStereoCombFilterMs = new System.Windows.Forms.Label(); + this.nudStereoCombFilterDelay = new Mesen.GUI.Controls.MesenNumericUpDown(); + this.lblStereoCombFilterDelay = new System.Windows.Forms.Label(); + this.lblStereoCombFilterStrength = new System.Windows.Forms.Label(); + this.lblCombFilterPercent = 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(); @@ -132,11 +140,11 @@ namespace Mesen.GUI.Forms.Config this.lblCrossFeedRatio = new System.Windows.Forms.Label(); this.tpgAdvanced = new System.Windows.Forms.TabPage(); this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.chkDisableDynamicSampleRate = new Mesen.GUI.Controls.ctrlRiskyOption(); this.chkDisableNoiseModeFlag = new Mesen.GUI.Controls.ctrlRiskyOption(); this.chkSilenceTriangleHighFreq = new System.Windows.Forms.CheckBox(); this.chkSwapDutyCycles = new Mesen.GUI.Controls.ctrlRiskyOption(); this.chkReduceDmcPopping = new System.Windows.Forms.CheckBox(); - this.chkDisableDynamicSampleRate = new Mesen.GUI.Controls.ctrlRiskyOption(); this.baseConfigPanel.SuspendLayout(); this.grpVolume.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); @@ -158,6 +166,7 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel4.SuspendLayout(); this.grpStereo.SuspendLayout(); this.tlpStereoFilter.SuspendLayout(); + this.tableLayoutPanel9.SuspendLayout(); this.grpReverb.SuspendLayout(); this.tableLayoutPanel5.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.trkReverbDelay)).BeginInit(); @@ -1425,7 +1434,7 @@ namespace Mesen.GUI.Forms.Config 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, 115); this.grpStereo.TabIndex = 0; this.grpStereo.TabStop = false; this.grpStereo.Text = "Stereo"; @@ -1436,6 +1445,7 @@ namespace Mesen.GUI.Forms.Config this.tlpStereoFilter.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tlpStereoFilter.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tlpStereoFilter.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpStereoFilter.Controls.Add(this.radStereoCombFilter, 0, 3); this.tlpStereoFilter.Controls.Add(this.lblStereoDelayMs, 2, 1); this.tlpStereoFilter.Controls.Add(this.lblStereoPanningAngle, 2, 2); this.tlpStereoFilter.Controls.Add(this.radStereoDisabled, 0, 0); @@ -1443,22 +1453,36 @@ namespace Mesen.GUI.Forms.Config this.tlpStereoFilter.Controls.Add(this.radStereoPanning, 0, 2); this.tlpStereoFilter.Controls.Add(this.nudStereoDelay, 1, 1); this.tlpStereoFilter.Controls.Add(this.nudStereoPanning, 1, 2); + this.tlpStereoFilter.Controls.Add(this.tableLayoutPanel9, 1, 3); 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 = 5; + 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()); 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, 96); this.tlpStereoFilter.TabIndex = 0; // + // radStereoCombFilter + // + this.radStereoCombFilter.AutoSize = true; + this.radStereoCombFilter.Location = new System.Drawing.Point(3, 72); + this.radStereoCombFilter.Name = "radStereoCombFilter"; + this.radStereoCombFilter.Size = new System.Drawing.Size(77, 17); + this.radStereoCombFilter.TabIndex = 4; + this.radStereoCombFilter.TabStop = true; + this.radStereoCombFilter.Tag = "Panning"; + this.radStereoCombFilter.Text = "Comb Filter"; + this.radStereoCombFilter.UseVisualStyleBackColor = true; + // // lblStereoDelayMs // this.lblStereoDelayMs.Anchor = System.Windows.Forms.AnchorStyles.Left; this.lblStereoDelayMs.AutoSize = true; - this.lblStereoDelayMs.Location = new System.Drawing.Point(120, 28); + this.lblStereoDelayMs.Location = new System.Drawing.Point(131, 28); this.lblStereoDelayMs.Name = "lblStereoDelayMs"; this.lblStereoDelayMs.Size = new System.Drawing.Size(20, 13); this.lblStereoDelayMs.TabIndex = 1; @@ -1468,7 +1492,7 @@ namespace Mesen.GUI.Forms.Config // this.lblStereoPanningAngle.Anchor = System.Windows.Forms.AnchorStyles.Left; this.lblStereoPanningAngle.AutoSize = true; - this.lblStereoPanningAngle.Location = new System.Drawing.Point(120, 51); + this.lblStereoPanningAngle.Location = new System.Drawing.Point(131, 51); this.lblStereoPanningAngle.Name = "lblStereoPanningAngle"; this.lblStereoPanningAngle.Size = new System.Drawing.Size(92, 13); this.lblStereoPanningAngle.TabIndex = 1; @@ -1520,7 +1544,7 @@ namespace Mesen.GUI.Forms.Config 0, 0, 0}); - this.nudStereoDelay.Location = new System.Drawing.Point(72, 24); + this.nudStereoDelay.Location = new System.Drawing.Point(83, 24); this.nudStereoDelay.Margin = new System.Windows.Forms.Padding(0); this.nudStereoDelay.Maximum = new decimal(new int[] { 100, @@ -1552,7 +1576,7 @@ namespace Mesen.GUI.Forms.Config 0, 0, 0}); - this.nudStereoPanning.Location = new System.Drawing.Point(72, 47); + this.nudStereoPanning.Location = new System.Drawing.Point(83, 47); this.nudStereoPanning.Margin = new System.Windows.Forms.Padding(0); this.nudStereoPanning.Maximum = new decimal(new int[] { 180, @@ -1574,12 +1598,143 @@ namespace Mesen.GUI.Forms.Config 0, 0, 0}); + // + // tableLayoutPanel9 + // + this.tableLayoutPanel9.ColumnCount = 7; + this.tlpStereoFilter.SetColumnSpan(this.tableLayoutPanel9, 2); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel9.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel9.Controls.Add(this.nudStereoCombFilterStrength, 4, 0); + this.tableLayoutPanel9.Controls.Add(this.lblStereoCombFilterMs, 2, 0); + this.tableLayoutPanel9.Controls.Add(this.nudStereoCombFilterDelay, 1, 0); + this.tableLayoutPanel9.Controls.Add(this.lblStereoCombFilterDelay, 0, 0); + this.tableLayoutPanel9.Controls.Add(this.lblStereoCombFilterStrength, 3, 0); + this.tableLayoutPanel9.Controls.Add(this.lblCombFilterPercent, 5, 0); + this.tableLayoutPanel9.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel9.Location = new System.Drawing.Point(83, 69); + this.tableLayoutPanel9.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel9.Name = "tableLayoutPanel9"; + this.tableLayoutPanel9.RowCount = 1; + this.tableLayoutPanel9.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel9.Size = new System.Drawing.Size(368, 23); + this.tableLayoutPanel9.TabIndex = 5; + // + // nudStereoCombFilterStrength + // + this.nudStereoCombFilterStrength.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.nudStereoCombFilterStrength.DecimalPlaces = 0; + this.nudStereoCombFilterStrength.Increment = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudStereoCombFilterStrength.Location = new System.Drawing.Point(187, 1); + this.nudStereoCombFilterStrength.Margin = new System.Windows.Forms.Padding(0); + this.nudStereoCombFilterStrength.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nudStereoCombFilterStrength.MaximumSize = new System.Drawing.Size(10000, 20); + this.nudStereoCombFilterStrength.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudStereoCombFilterStrength.MinimumSize = new System.Drawing.Size(0, 21); + this.nudStereoCombFilterStrength.Name = "nudStereoCombFilterStrength"; + this.nudStereoCombFilterStrength.Size = new System.Drawing.Size(45, 21); + this.nudStereoCombFilterStrength.TabIndex = 5; + this.nudStereoCombFilterStrength.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // lblStereoCombFilterMs + // + this.lblStereoCombFilterMs.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblStereoCombFilterMs.AutoSize = true; + this.lblStereoCombFilterMs.Location = new System.Drawing.Point(91, 5); + this.lblStereoCombFilterMs.Name = "lblStereoCombFilterMs"; + this.lblStereoCombFilterMs.Size = new System.Drawing.Size(20, 13); + this.lblStereoCombFilterMs.TabIndex = 3; + this.lblStereoCombFilterMs.Text = "ms"; + // + // nudStereoCombFilterDelay + // + this.nudStereoCombFilterDelay.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.nudStereoCombFilterDelay.DecimalPlaces = 0; + this.nudStereoCombFilterDelay.Increment = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudStereoCombFilterDelay.Location = new System.Drawing.Point(43, 1); + this.nudStereoCombFilterDelay.Margin = new System.Windows.Forms.Padding(0); + this.nudStereoCombFilterDelay.Maximum = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.nudStereoCombFilterDelay.MaximumSize = new System.Drawing.Size(10000, 20); + this.nudStereoCombFilterDelay.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudStereoCombFilterDelay.MinimumSize = new System.Drawing.Size(0, 21); + this.nudStereoCombFilterDelay.Name = "nudStereoCombFilterDelay"; + this.nudStereoCombFilterDelay.Size = new System.Drawing.Size(45, 21); + this.nudStereoCombFilterDelay.TabIndex = 2; + this.nudStereoCombFilterDelay.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // lblStereoCombFilterDelay + // + this.lblStereoCombFilterDelay.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblStereoCombFilterDelay.AutoSize = true; + this.lblStereoCombFilterDelay.Location = new System.Drawing.Point(3, 5); + this.lblStereoCombFilterDelay.Name = "lblStereoCombFilterDelay"; + this.lblStereoCombFilterDelay.Size = new System.Drawing.Size(37, 13); + this.lblStereoCombFilterDelay.TabIndex = 0; + this.lblStereoCombFilterDelay.Text = "Delay:"; + // + // lblStereoCombFilterStrength + // + this.lblStereoCombFilterStrength.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblStereoCombFilterStrength.AutoSize = true; + this.lblStereoCombFilterStrength.Location = new System.Drawing.Point(134, 5); + this.lblStereoCombFilterStrength.Margin = new System.Windows.Forms.Padding(20, 0, 3, 0); + this.lblStereoCombFilterStrength.Name = "lblStereoCombFilterStrength"; + this.lblStereoCombFilterStrength.Size = new System.Drawing.Size(50, 13); + this.lblStereoCombFilterStrength.TabIndex = 4; + this.lblStereoCombFilterStrength.Text = "Strength:"; + // + // lblCombFilterPercent + // + this.lblCombFilterPercent.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblCombFilterPercent.AutoSize = true; + this.lblCombFilterPercent.Location = new System.Drawing.Point(235, 5); + this.lblCombFilterPercent.Name = "lblCombFilterPercent"; + this.lblCombFilterPercent.Size = new System.Drawing.Size(15, 13); + this.lblCombFilterPercent.TabIndex = 6; + this.lblCombFilterPercent.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, 124); this.grpReverb.Name = "grpReverb"; this.grpReverb.Size = new System.Drawing.Size(457, 106); this.grpReverb.TabIndex = 1; @@ -1665,7 +1820,7 @@ namespace Mesen.GUI.Forms.Config 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(6, 213); + this.flowLayoutPanel5.Location = new System.Drawing.Point(6, 233); this.flowLayoutPanel5.Margin = new System.Windows.Forms.Padding(6, 0, 0, 0); this.flowLayoutPanel5.Name = "flowLayoutPanel5"; this.flowLayoutPanel5.Size = new System.Drawing.Size(457, 25); @@ -1758,6 +1913,16 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel3.Size = new System.Drawing.Size(463, 341); this.tableLayoutPanel3.TabIndex = 1; // + // chkDisableDynamicSampleRate + // + this.chkDisableDynamicSampleRate.Checked = false; + this.chkDisableDynamicSampleRate.Dock = System.Windows.Forms.DockStyle.Fill; + this.chkDisableDynamicSampleRate.Location = new System.Drawing.Point(0, 48); + this.chkDisableDynamicSampleRate.Name = "chkDisableDynamicSampleRate"; + this.chkDisableDynamicSampleRate.Size = new System.Drawing.Size(463, 24); + this.chkDisableDynamicSampleRate.TabIndex = 4; + this.chkDisableDynamicSampleRate.Text = "Disable dynamic sample rate"; + // // chkDisableNoiseModeFlag // this.chkDisableNoiseModeFlag.Checked = false; @@ -1799,16 +1964,6 @@ namespace Mesen.GUI.Forms.Config this.chkReduceDmcPopping.TextAlign = System.Drawing.ContentAlignment.TopLeft; this.chkReduceDmcPopping.UseVisualStyleBackColor = true; // - // chkDisableDynamicSampleRate - // - this.chkDisableDynamicSampleRate.Checked = false; - this.chkDisableDynamicSampleRate.Dock = System.Windows.Forms.DockStyle.Fill; - this.chkDisableDynamicSampleRate.Location = new System.Drawing.Point(0, 48); - this.chkDisableDynamicSampleRate.Name = "chkDisableDynamicSampleRate"; - this.chkDisableDynamicSampleRate.Size = new System.Drawing.Size(463, 24); - this.chkDisableDynamicSampleRate.TabIndex = 4; - this.chkDisableDynamicSampleRate.Text = "Disable dynamic sample rate"; - // // frmAudioConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1854,6 +2009,8 @@ namespace Mesen.GUI.Forms.Config this.grpStereo.ResumeLayout(false); this.tlpStereoFilter.ResumeLayout(false); this.tlpStereoFilter.PerformLayout(); + this.tableLayoutPanel9.ResumeLayout(false); + this.tableLayoutPanel9.PerformLayout(); this.grpReverb.ResumeLayout(false); this.tableLayoutPanel5.ResumeLayout(false); this.tableLayoutPanel5.PerformLayout(); @@ -1978,5 +2135,13 @@ namespace Mesen.GUI.Forms.Config private ctrlHorizontalTrackbar trkVolumeReduction; private System.Windows.Forms.CheckBox chkMuteSoundInBackground; private ctrlRiskyOption chkDisableDynamicSampleRate; + private System.Windows.Forms.RadioButton radStereoCombFilter; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel9; + private MesenNumericUpDown nudStereoCombFilterStrength; + private System.Windows.Forms.Label lblStereoCombFilterMs; + private MesenNumericUpDown nudStereoCombFilterDelay; + private System.Windows.Forms.Label lblStereoCombFilterDelay; + private System.Windows.Forms.Label lblStereoCombFilterStrength; + private System.Windows.Forms.Label lblCombFilterPercent; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmAudioConfig.cs b/GUI.NET/Forms/Config/frmAudioConfig.cs index 2d51b7c4..7045cc97 100644 --- a/GUI.NET/Forms/Config/frmAudioConfig.cs +++ b/GUI.NET/Forms/Config/frmAudioConfig.cs @@ -101,10 +101,13 @@ namespace Mesen.GUI.Forms.Config radStereoDisabled.Tag = InteropEmu.StereoFilter.None; radStereoDelay.Tag = InteropEmu.StereoFilter.Delay; radStereoPanning.Tag = InteropEmu.StereoFilter.Panning; + radStereoCombFilter.Tag = InteropEmu.StereoFilter.CombFilter; AddBinding("StereoFilter", tlpStereoFilter); AddBinding("StereoDelay", nudStereoDelay); AddBinding("StereoPanningAngle", nudStereoPanning); + AddBinding("StereoCombFilterDelay", nudStereoCombFilterDelay); + AddBinding("StereoCombFilterStrength", nudStereoCombFilterStrength); AddBinding("ReverbEnabled", chkReverbEnabled); AddBinding("ReverbDelay", trkReverbDelay); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 6b9c1ecf..f17d23bc 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -184,11 +184,7 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void SetBandGain(int band, double gain); [DllImport(DLLPath)] public static extern void SetSampleRate(UInt32 sampleRate); [DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency); - [DllImport(DLLPath)] public static extern void SetStereoFilter(StereoFilter stereoFilter); - [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 SetAudioFilterSettings(AudioFilterSettings settings); [DllImport(DLLPath)] public static extern NesModel GetNesModel(); [DllImport(DLLPath)] public static extern void SetNesModel(NesModel model); @@ -1051,6 +1047,20 @@ namespace Mesen.GUI None = 0, Delay = 1, Panning = 2, + CombFilter = 3, + } + + public struct AudioFilterSettings + { + public StereoFilter StereoFilter; + public double Angle; + public Int32 Delay; + public Int32 Strength; + + public double ReverbDelay; + public double ReverbStrength; + + public Int32 CrossFeedRatio; } public struct ScreenSize diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 13203c33..3d72c00f 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -607,11 +607,7 @@ namespace InteropEmu { DllExport void __stdcall SetMasterVolume(double volume, double volumeReduction, ConsoleId consoleId) { GetConsoleById(consoleId)->GetSettings()->SetMasterVolume(volume, volumeReduction); } DllExport void __stdcall SetSampleRate(uint32_t sampleRate) { _settings->SetSampleRate(sampleRate); } DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { _settings->SetAudioLatency(msLatency); } - DllExport void __stdcall SetStereoFilter(StereoFilter stereoFilter) { _settings->SetStereoFilter(stereoFilter); } - DllExport void __stdcall SetStereoDelay(int32_t delay) { _settings->SetStereoDelay(delay); } - DllExport void __stdcall SetStereoPanningAngle(double angle) { _settings->SetStereoPanningAngle(angle); } - DllExport void __stdcall SetReverbParameters(double strength, double delay) { _settings->SetReverbParameters(strength, delay); } - DllExport void __stdcall SetCrossFeedRatio(uint32_t ratio) { _settings->SetCrossFeedRatio(ratio); } + DllExport void __stdcall SetAudioFilterSettings(AudioFilterSettings settings) { _settings->SetAudioFilterSettings(settings); } DllExport NesModel __stdcall GetNesModel() { return _console->GetModel(); } DllExport void __stdcall SetNesModel(uint32_t model) { _settings->SetNesModel((NesModel)model); }