diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 2f340363..67954d82 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -355,7 +355,7 @@ true WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true - AnySuitable + Disabled true Speed diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp index ff1d083b..0a78ead6 100644 --- a/Core/EmulationSettings.cpp +++ b/Core/EmulationSettings.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "EmulationSettings.h" +#include "Console.h" #include "VsControlManager.h" //Version 0.8.0 @@ -11,9 +12,13 @@ Language EmulationSettings::_displayLanguage = Language::English; uint64_t EmulationSettings::_flags = 0; +bool EmulationSettings::_audioSettingsChanged = true; uint32_t EmulationSettings::_audioLatency = 20000; double EmulationSettings::_channelVolume[11] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; double EmulationSettings::_channelPanning[11] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; +EqualizerFilterType EmulationSettings::_equalizerFilterType = EqualizerFilterType::None; +vector EmulationSettings::_bandGains = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; +vector EmulationSettings::_bands = { { 40,56,80,113,160,225,320,450,600,750,1000,2000,3000,4000,5000,6000,7000,10000,12500,15000 } }; double EmulationSettings::_masterVolume = 1.0; uint32_t EmulationSettings::_sampleRate = 44100; StereoFilter EmulationSettings::_stereoFilter = StereoFilter::None; @@ -83,4 +88,16 @@ uint32_t EmulationSettings::_ppuPaletteArgb[11][64] = { /* 2C05-03 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, /* 2C05-04 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, /* 2C05-05 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 } -}; \ No newline at end of file +}; + +void EmulationSettings::SetEqualizerBands(double *bands, uint32_t bandCount) +{ + Console::Pause(); + _bands.clear(); + _bandGains.clear(); + for(uint32_t i = 0; i < bandCount; i++) { + _bands.push_back(bands[i]); + _bandGains.push_back(0); + } + Console::Resume(); +} diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 0e21caf9..53e65401 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -67,6 +67,14 @@ enum class AudioChannel Sunsoft5B = 10 }; +enum class EqualizerFilterType +{ + None = 0, + Butterworth = 1, + Chebyshev1 = 2, + Chebyshev2 = 3 +}; + enum class NesModel { Auto = 0, @@ -322,9 +330,13 @@ private: static Language _displayLanguage; + static bool _audioSettingsChanged; static uint32_t _audioLatency; static double _channelVolume[11]; static double _channelPanning[11]; + static EqualizerFilterType _equalizerFilterType; + static vector _bandGains; + static vector _bands; static double _masterVolume; static uint32_t _sampleRate; static StereoFilter _stereoFilter; @@ -470,11 +482,48 @@ public: static void SetChannelPanning(AudioChannel channel, double panning) { _channelPanning[(int)channel] = panning; + _audioSettingsChanged = true; + } + + static double GetBandGain(int band) + { + if(band < (int)_bandGains.size()) { + return _bandGains[band]; + } else { + return 0; + } + } + + static void SetBandGain(int band, double gain) + { + if(band < (int)_bandGains.size()) { + _bandGains[band] = gain; + } + _audioSettingsChanged = true; + } + + static vector GetEqualizerBands() + { + return _bands; + } + + static void SetEqualizerBands(double *bands, uint32_t bandCount); + + static EqualizerFilterType GetEqualizerFilterType() + { + return _equalizerFilterType; + } + + static void SetEqualizerFilterType(EqualizerFilterType filter) + { + _equalizerFilterType = filter; + _audioSettingsChanged = true; } static void SetSampleRate(uint32_t sampleRate) { _sampleRate = sampleRate; + _audioSettingsChanged = true; } static uint32_t GetSampleRate() @@ -485,27 +534,32 @@ public: static void SetAudioLatency(uint32_t msLatency) { _audioLatency = msLatency; + _audioSettingsChanged = true; } static void SetStereoFilter(StereoFilter stereoFilter) { _stereoFilter = stereoFilter; + _audioSettingsChanged = true; } static void SetStereoDelay(int32_t delay) { _stereoDelay = delay; + _audioSettingsChanged = true; } static void SetStereoPanningAngle(double angle) { _stereoAngle = angle; + _audioSettingsChanged = true; } static void SetReverbParameters(double strength, double delay) { _reverbStrength = strength; _reverbDelay = delay; + _audioSettingsChanged = true; } static StereoFilter GetStereoFilter() @@ -536,6 +590,16 @@ public: static void SetCrossFeedRatio(uint32_t ratio) { _crossFeedRatio = ratio; + _audioSettingsChanged = true; + } + + static bool NeedAudioSettingsUpdate() + { + bool value = _audioSettingsChanged; + if(value) { + _audioSettingsChanged = false; + } + return value; } static uint32_t GetCrossFeedRatio() diff --git a/Core/SoundMixer.cpp b/Core/SoundMixer.cpp index 32c0c5bb..c9426c1b 100644 --- a/Core/SoundMixer.cpp +++ b/Core/SoundMixer.cpp @@ -3,6 +3,7 @@ #include "APU.h" #include "CPU.h" #include "VideoDecoder.h" +#include "../Utilities/orfanidis_eq.h" IAudioDevice* SoundMixer::AudioDevice = nullptr; unique_ptr SoundMixer::_waveRecorder; @@ -12,6 +13,7 @@ uint32_t SoundMixer::_muteFrameCount; SoundMixer::SoundMixer() { + _eqFrequencyGrid.reset(new orfanidis_eq::freq_grid()); _outputBuffer = new int16_t[SoundMixer::MaxSamplesPerFrame]; _blipBufLeft = blip_new(SoundMixer::MaxSamplesPerFrame); _blipBufRight = blip_new(SoundMixer::MaxSamplesPerFrame); @@ -77,6 +79,9 @@ void SoundMixer::Reset() } memset(_channelOutput, 0, sizeof(_channelOutput)); memset(_currentOutput, 0, sizeof(_currentOutput)); + + UpdateRates(true); + UpdateEqualizers(true); } void SoundMixer::PlayAudioBuffer(uint32_t time) @@ -84,10 +89,14 @@ void SoundMixer::PlayAudioBuffer(uint32_t time) EndFrame(time); size_t sampleCount = blip_read_samples(_blipBufLeft, _outputBuffer, SoundMixer::MaxSamplesPerFrame, 1); + ApplyEqualizer(_equalizerLeft.get(), sampleCount); + if(_hasPanning) { blip_read_samples(_blipBufRight, _outputBuffer + 1, SoundMixer::MaxSamplesPerFrame, 1); + ApplyEqualizer(_equalizerRight.get(), sampleCount); } else { - for(size_t i = 0; i < sampleCount * 2; i+=2) { + //Copy left channel to right channel (optimization - when no panning is used) + for(size_t i = 0; i < sampleCount * 2; i += 2) { _outputBuffer[i + 1] = _outputBuffer[i]; } } @@ -128,15 +137,19 @@ void SoundMixer::PlayAudioBuffer(uint32_t time) } } } - + VideoDecoder::GetInstance()->AddRecordingSound(_outputBuffer, (uint32_t)sampleCount, _sampleRate); - if(EmulationSettings::GetSampleRate() != _sampleRate) { - //Update sample rate for next frame if setting changed - _sampleRate = EmulationSettings::GetSampleRate(); - UpdateRates(true); - } else { - UpdateRates(false); + if(EmulationSettings::NeedAudioSettingsUpdate()) { + if(EmulationSettings::GetSampleRate() != _sampleRate) { + //Update sample rate for next frame if setting changed + _sampleRate = EmulationSettings::GetSampleRate(); + UpdateRates(true); + UpdateEqualizers(true); + } else { + UpdateEqualizers(false); + UpdateRates(false); + } } } @@ -164,11 +177,11 @@ void SoundMixer::UpdateRates(bool forceUpdate) _volumes[i] = EmulationSettings::GetChannelVolume((AudioChannel)i); _panning[i] = EmulationSettings::GetChannelPanning((AudioChannel)i); if(_panning[i] != 1.0) { - if(_hasPanning) { + if(!_hasPanning) { blip_clear(_blipBufLeft); blip_clear(_blipBufRight); } - _hasPanning = true; + hasPanning = true; } } _hasPanning = hasPanning; @@ -253,6 +266,54 @@ void SoundMixer::EndFrame(uint32_t time) memset(_channelOutput, 0, sizeof(_channelOutput)); } +void SoundMixer::ApplyEqualizer(orfanidis_eq::eq1* equalizer, size_t sampleCount) +{ + if(equalizer) { + int offset = equalizer == _equalizerRight.get() ? 1 : 0; + for(size_t i = 0; i < sampleCount; i++) { + double in = _outputBuffer[i * 2 + offset]; + double out; + equalizer->sbs_process(&in, &out); + _outputBuffer[i * 2 + offset] = (int16_t)out; + } + } +} + +void SoundMixer::UpdateEqualizers(bool forceUpdate) +{ + EqualizerFilterType type = EmulationSettings::GetEqualizerFilterType(); + if(type != EqualizerFilterType::None) { + vector bands = EmulationSettings::GetEqualizerBands(); + + if(bands.size() != _eqFrequencyGrid->get_number_of_bands()) { + _equalizerLeft.reset(); + _equalizerRight.reset(); + } + + if((_equalizerLeft && (int)_equalizerLeft->get_eq_type() != (int)type) || !_equalizerLeft || forceUpdate) { + bands.insert(bands.begin(), bands[0] - (bands[1] - bands[0])); + bands.insert(bands.end(), bands[bands.size() - 1] + (bands[bands.size() - 1] - bands[bands.size() - 2])); + _eqFrequencyGrid.reset(new orfanidis_eq::freq_grid()); + for(size_t i = 1; i < bands.size() - 1; i++) { + _eqFrequencyGrid->add_band((bands[i] + bands[i - 1]) / 2, bands[i], (bands[i + 1] + bands[i]) / 2); + } + + _equalizerLeft.reset(new orfanidis_eq::eq1(_eqFrequencyGrid.get(), (orfanidis_eq::filter_type)EmulationSettings::GetEqualizerFilterType())); + _equalizerRight.reset(new orfanidis_eq::eq1(_eqFrequencyGrid.get(), (orfanidis_eq::filter_type)EmulationSettings::GetEqualizerFilterType())); + _equalizerLeft->set_sample_rate(_sampleRate); + _equalizerRight->set_sample_rate(_sampleRate); + } + + for(unsigned int i = 0; i < _eqFrequencyGrid->get_number_of_bands(); i++) { + _equalizerLeft->change_band_gain_db(i, EmulationSettings::GetBandGain(i)); + _equalizerRight->change_band_gain_db(i, EmulationSettings::GetBandGain(i)); + } + } else { + _equalizerLeft.reset(); + _equalizerRight.reset(); + } +} + void SoundMixer::StartRecording(string filepath) { auto lock = _waveRecorderLock.AcquireSafe(); diff --git a/Core/SoundMixer.h b/Core/SoundMixer.h index 623e3a1b..9321f1ff 100644 --- a/Core/SoundMixer.h +++ b/Core/SoundMixer.h @@ -12,6 +12,11 @@ #include "CrossFeedFilter.h" #include "WaveRecorder.h" +namespace orfanidis_eq { + class freq_grid; + class eq1; +} + class SoundMixer : public Snapshotable { public: @@ -29,6 +34,10 @@ private: static const uint32_t MaxSamplesPerFrame = MaxSampleRate / 60 * 4 * 2; //x4 to allow CPU overclocking up to 10x, x2 for panning stereo static const uint32_t MaxChannelCount = 11; + unique_ptr _eqFrequencyGrid; + unique_ptr _equalizerLeft; + unique_ptr _equalizerRight; + CrossFeedFilter _crossFeedFilter; LowPassFilter _lowPassFilter; StereoPanningFilter _stereoPanning; @@ -59,6 +68,9 @@ private: void EndFrame(uint32_t time); void UpdateRates(bool forceUpdate); + + void UpdateEqualizers(bool forceUpdate); + void ApplyEqualizer(orfanidis_eq::eq1* equalizer, size_t sampleCount); protected: virtual void StreamState(bool saving) override; diff --git a/GUI.NET/Config/AudioInfo.cs b/GUI.NET/Config/AudioInfo.cs index 4aaa20af..c94f5cd6 100644 --- a/GUI.NET/Config/AudioInfo.cs +++ b/GUI.NET/Config/AudioInfo.cs @@ -57,6 +57,30 @@ namespace Mesen.GUI.Config public bool CrossFeedEnabled = false; [MinMax(0, 100)] public UInt32 CrossFeedRatio = 0; + public bool EnableEqualizer = false; + public EqualizerFilterType EqualizerFilterType = EqualizerFilterType.Butterworth; + public EqualizerPreset EqualizerPreset = EqualizerPreset.Custom; + [MinMax(-200, 200)] public Int32 Band1Gain = 0; + [MinMax(-200, 200)] public Int32 Band2Gain = 0; + [MinMax(-200, 200)] public Int32 Band3Gain = 0; + [MinMax(-200, 200)] public Int32 Band4Gain = 0; + [MinMax(-200, 200)] public Int32 Band5Gain = 0; + [MinMax(-200, 200)] public Int32 Band6Gain = 0; + [MinMax(-200, 200)] public Int32 Band7Gain = 0; + [MinMax(-200, 200)] public Int32 Band8Gain = 0; + [MinMax(-200, 200)] public Int32 Band9Gain = 0; + [MinMax(-200, 200)] public Int32 Band10Gain = 0; + [MinMax(-200, 200)] public Int32 Band11Gain = 0; + [MinMax(-200, 200)] public Int32 Band12Gain = 0; + [MinMax(-200, 200)] public Int32 Band13Gain = 0; + [MinMax(-200, 200)] public Int32 Band14Gain = 0; + [MinMax(-200, 200)] public Int32 Band15Gain = 0; + [MinMax(-200, 200)] public Int32 Band16Gain = 0; + [MinMax(-200, 200)] public Int32 Band17Gain = 0; + [MinMax(-200, 200)] public Int32 Band18Gain = 0; + [MinMax(-200, 200)] public Int32 Band19Gain = 0; + [MinMax(-200, 200)] public Int32 Band20Gain = 0; + public AudioInfo() { } @@ -105,6 +129,50 @@ namespace Mesen.GUI.Config InteropEmu.SetChannelPanning(AudioChannel.Namco163, ConvertPanning(audioInfo.Namco163Panning)); InteropEmu.SetChannelPanning(AudioChannel.Sunsoft5B, ConvertPanning(audioInfo.Sunsoft5bPanning)); + InteropEmu.SetEqualizerFilterType(audioInfo.EnableEqualizer ? audioInfo.EqualizerFilterType : EqualizerFilterType.None); + + if(audioInfo.EqualizerPreset < EqualizerPreset.TwinFamicom60) { + double[] defaultBands = new double[20] { 40, 56, 80, 113, 160, 225, 320, 450, 600, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 10000, 12500, 15000 }; + InteropEmu.SetEqualizerBands(defaultBands, (UInt32)defaultBands.Length); + + InteropEmu.SetBandGain(0, (double)audioInfo.Band1Gain / 10); + InteropEmu.SetBandGain(1, (double)audioInfo.Band2Gain / 10); + InteropEmu.SetBandGain(2, (double)audioInfo.Band3Gain / 10); + InteropEmu.SetBandGain(3, (double)audioInfo.Band4Gain / 10); + InteropEmu.SetBandGain(4, (double)audioInfo.Band5Gain / 10); + InteropEmu.SetBandGain(5, (double)audioInfo.Band6Gain / 10); + InteropEmu.SetBandGain(6, (double)audioInfo.Band7Gain / 10); + InteropEmu.SetBandGain(7, (double)audioInfo.Band8Gain / 10); + InteropEmu.SetBandGain(8, (double)audioInfo.Band9Gain / 10); + InteropEmu.SetBandGain(9, (double)audioInfo.Band10Gain / 10); + InteropEmu.SetBandGain(10, (double)audioInfo.Band11Gain / 10); + InteropEmu.SetBandGain(11, (double)audioInfo.Band12Gain / 10); + InteropEmu.SetBandGain(12, (double)audioInfo.Band13Gain / 10); + InteropEmu.SetBandGain(13, (double)audioInfo.Band14Gain / 10); + InteropEmu.SetBandGain(14, (double)audioInfo.Band15Gain / 10); + InteropEmu.SetBandGain(15, (double)audioInfo.Band16Gain / 10); + InteropEmu.SetBandGain(16, (double)audioInfo.Band17Gain / 10); + InteropEmu.SetBandGain(17, (double)audioInfo.Band18Gain / 10); + InteropEmu.SetBandGain(18, (double)audioInfo.Band19Gain / 10); + InteropEmu.SetBandGain(19, (double)audioInfo.Band20Gain / 10); + } else { + switch(audioInfo.EqualizerPreset) { + case EqualizerPreset.TwinFamicom60: + double[] bands = new double[60] { + 20, 22.5, 25.3, 28.4, 31.9, 35.9, 40.4, 45.4, 51.0, 57.4, 64.5, 72.5, 81.5, 91.6, 103, 116, 130, 146, 165, 185, 208, 234, + 263, 295, 332, 373, 420, 472, 531, 596, 671, 754, 848, 953, 1070, 1200, 1350, 1520, 1710, 1920, 2160, 2430, 2730, + 3070, 3450, 3880, 4370, 4910, 5520, 6200, 6970, 7840, 8810, 9910, 11100, 12500, 14100, 15800, 17300, 20000 + }; + InteropEmu.SetEqualizerBands(bands, (UInt32)bands.Length); + + double[] gains = new double[60] { -4.4, -4.1, -3.8, -3.5, -3.1, -2.8, -2.3, -1.9, -1.6, -1.3, -1.1, -0.9, -0.7, -0.7, -0.6, -0.6, -0.4, -0.1, 0.0, -0.2, -0.3, -0.4, -0.3, -0.5, -0.3, -0.4, -0.2, -0.2, -0.2, -0.3, -0.3, -0.4, -0.4, -0.3, -0.2, -0.6, -0.5, -0.7, -0.7, -1.1, -1.4, -1.6, -1.9, -2.3, -2.7, -3.1, -3.6, -4.3, -4.7, -5.4, -6.2, -7.0, -7.8, -8.2, -8.8, -9.4, -10.0, -10.6, -10.9, -9.5 }; + for(int i = 0; i < 60; i++) { + InteropEmu.SetBandGain(i, gains[i]); + } + break; + } + } + InteropEmu.SetSampleRate(audioInfo.SampleRate); InteropEmu.SetFlag(EmulationFlags.MuteSoundInBackground, audioInfo.MuteSoundInBackground); @@ -132,4 +200,11 @@ namespace Mesen.GUI.Config } } } + + public enum EqualizerPreset + { + Custom = 0, + TwinFamicom, + TwinFamicom60 + } } diff --git a/GUI.NET/Controls/ctrlTrackbar.Designer.cs b/GUI.NET/Controls/ctrlTrackbar.Designer.cs index 58282a85..d9949cb9 100644 --- a/GUI.NET/Controls/ctrlTrackbar.Designer.cs +++ b/GUI.NET/Controls/ctrlTrackbar.Designer.cs @@ -42,6 +42,7 @@ this.tableLayoutPanel1.Controls.Add(this.lblText, 0, 2); this.tableLayoutPanel1.Controls.Add(this.trackBar, 0, 0); this.tableLayoutPanel1.Controls.Add(this.txtValue, 0, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; @@ -49,16 +50,18 @@ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(62, 160); + this.tableLayoutPanel1.Size = new System.Drawing.Size(34, 160); this.tableLayoutPanel1.TabIndex = 0; // // lblText // this.lblText.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.lblText.AutoSize = true; - this.lblText.Location = new System.Drawing.Point(3, 147); + this.lblText.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblText.Location = new System.Drawing.Point(0, 148); + this.lblText.Margin = new System.Windows.Forms.Padding(0); this.lblText.Name = "lblText"; - this.lblText.Size = new System.Drawing.Size(56, 13); + this.lblText.Size = new System.Drawing.Size(34, 12); this.lblText.TabIndex = 14; this.lblText.Text = "Text"; this.lblText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -67,12 +70,12 @@ // this.trackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Right))); - this.trackBar.Location = new System.Drawing.Point(17, 0); + this.trackBar.Location = new System.Drawing.Point(0, 0); this.trackBar.Margin = new System.Windows.Forms.Padding(0); this.trackBar.Maximum = 100; this.trackBar.Name = "trackBar"; this.trackBar.Orientation = System.Windows.Forms.Orientation.Vertical; - this.trackBar.Size = new System.Drawing.Size(45, 124); + this.trackBar.Size = new System.Drawing.Size(34, 125); this.trackBar.TabIndex = 13; this.trackBar.TickFrequency = 10; this.trackBar.Value = 50; @@ -80,14 +83,14 @@ // // txtValue // - this.txtValue.Anchor = System.Windows.Forms.AnchorStyles.None; + this.txtValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.txtValue.BackColor = System.Drawing.Color.White; this.txtValue.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.txtValue.Location = new System.Drawing.Point(15, 127); + this.txtValue.Location = new System.Drawing.Point(3, 128); this.txtValue.Multiline = true; this.txtValue.Name = "txtValue"; this.txtValue.ReadOnly = true; - this.txtValue.Size = new System.Drawing.Size(31, 17); + this.txtValue.Size = new System.Drawing.Size(28, 17); this.txtValue.TabIndex = 15; this.txtValue.TabStop = false; this.txtValue.Text = "100"; @@ -100,9 +103,9 @@ this.Controls.Add(this.tableLayoutPanel1); this.Margin = new System.Windows.Forms.Padding(0); this.MaximumSize = new System.Drawing.Size(63, 160); - this.MinimumSize = new System.Drawing.Size(63, 160); + this.MinimumSize = new System.Drawing.Size(34, 160); this.Name = "ctrlTrackbar"; - this.Size = new System.Drawing.Size(63, 160); + this.Size = new System.Drawing.Size(34, 160); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBar)).EndInit(); diff --git a/GUI.NET/Controls/ctrlTrackbar.cs b/GUI.NET/Controls/ctrlTrackbar.cs index 414af770..51e66fce 100644 --- a/GUI.NET/Controls/ctrlTrackbar.cs +++ b/GUI.NET/Controls/ctrlTrackbar.cs @@ -27,13 +27,18 @@ namespace Mesen.GUI.Controls } } + public int Minimum + { + get { return trackBar.Minimum; } + set { trackBar.Minimum = value; } + } + public int Maximum { get { return trackBar.Maximum; } set { trackBar.Maximum = value; } } - - + [Bindable(true)] [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] @@ -50,13 +55,23 @@ namespace Mesen.GUI.Controls set { trackBar.Value = value; + UpdateText(); + } + } + + private void UpdateText() + { + if(this.Minimum == 0) { txtValue.Text = trackBar.Value.ToString() + "%"; + } else { + txtValue.Text = (trackBar.Value / 10.0).ToString() + "dB"; + txtValue.Font = new Font("Microsoft Sans Serif", 6.75F); } } private void trackBar_ValueChanged(object sender, EventArgs e) { - txtValue.Text = trackBar.Value.ToString() + "%"; + UpdateText(); } } } diff --git a/GUI.NET/Dependencies/resources.es.xml b/GUI.NET/Dependencies/resources.es.xml index 974f17e5..c715be9b 100644 --- a/GUI.NET/Dependencies/resources.es.xml +++ b/GUI.NET/Dependencies/resources.es.xml @@ -163,6 +163,9 @@ VRC7 Namco Sunsoft + + Equalizer + Enable equalizer
OK diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index d5bb113b..42734ca6 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -163,6 +163,9 @@ VRC7 Namco Sunsoft + + Égaliseur + Activer l'égaliseur
OK diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index d46687ac..3cf1c454 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -163,6 +163,9 @@ VRC7 Namco Sunsoft + + イコライザー + イコライザーを有効にする
OK diff --git a/GUI.NET/Dependencies/resources.pt.xml b/GUI.NET/Dependencies/resources.pt.xml index ece8fcc6..4cff83ae 100644 --- a/GUI.NET/Dependencies/resources.pt.xml +++ b/GUI.NET/Dependencies/resources.pt.xml @@ -162,7 +162,10 @@ VRC6 VRC7 Namco - Sunsoft + Sunsoft + + Equalizer + Enable equalizer
OK diff --git a/GUI.NET/Dependencies/resources.ru.xml b/GUI.NET/Dependencies/resources.ru.xml index 132910ca..0d2765e6 100644 --- a/GUI.NET/Dependencies/resources.ru.xml +++ b/GUI.NET/Dependencies/resources.ru.xml @@ -163,6 +163,9 @@ VRC7 Namco Sunsoft + + Equalizer + Enable equalizer
OK diff --git a/GUI.NET/Dependencies/resources.uk.xml b/GUI.NET/Dependencies/resources.uk.xml index 69d8da6a..550c60a9 100644 --- a/GUI.NET/Dependencies/resources.uk.xml +++ b/GUI.NET/Dependencies/resources.uk.xml @@ -163,6 +163,9 @@ VRC7 Namco Sunsoft + + Equalizer + Enable equalizer
OK diff --git a/GUI.NET/Forms/BaseConfigForm.cs b/GUI.NET/Forms/BaseConfigForm.cs index 2589705f..070da2c8 100644 --- a/GUI.NET/Forms/BaseConfigForm.cs +++ b/GUI.NET/Forms/BaseConfigForm.cs @@ -170,5 +170,15 @@ namespace Mesen.GUI.Forms return default(T); } + + public static void SetEnumValue(this ComboBox cbo, T value) + { + for(int i = 0; i < cbo.Items.Count; i++) { + if(ResourceHelper.GetEnumText((Enum)(object)value) == cbo.Items[i].ToString()) { + cbo.SelectedIndex = i; + break; + } + } + } } } diff --git a/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs b/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs index f4ddfa79..64c472a6 100644 --- a/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs @@ -74,6 +74,36 @@ namespace Mesen.GUI.Forms.Config this.trkVrc7Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); this.trkNamcoPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); this.trkSunsoftPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.tpgEqualizer = new System.Windows.Forms.TabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.chkEnableEqualizer = new System.Windows.Forms.CheckBox(); + this.tlpEqualizer = new System.Windows.Forms.TableLayoutPanel(); + this.trkBand6Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand5Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand4Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand3Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand2Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand1Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand11Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand12Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand13Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand14Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand15Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand16Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand7Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand8Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand9Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand10Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand17Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand18Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand19Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.trkBand20Gain = new Mesen.GUI.Controls.ctrlTrackbar(); + this.flowLayoutPanel6 = new System.Windows.Forms.FlowLayoutPanel(); + this.lblEqualizerPreset = new System.Windows.Forms.Label(); + this.cboEqualizerPreset = new System.Windows.Forms.ComboBox(); + this.flowLayoutPanel7 = new System.Windows.Forms.FlowLayoutPanel(); + this.lblEqualizerFilterType = new System.Windows.Forms.Label(); + this.cboEqualizerFilterType = new System.Windows.Forms.ComboBox(); this.tpgEffects = new System.Windows.Forms.TabPage(); this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); this.grpStereo = new System.Windows.Forms.GroupBox(); @@ -116,6 +146,11 @@ namespace Mesen.GUI.Forms.Config this.tpgVolume.SuspendLayout(); this.tpgPanning.SuspendLayout(); this.tableLayoutPanel6.SuspendLayout(); + this.tpgEqualizer.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.tlpEqualizer.SuspendLayout(); + this.flowLayoutPanel6.SuspendLayout(); + this.flowLayoutPanel7.SuspendLayout(); this.tpgEffects.SuspendLayout(); this.tableLayoutPanel4.SuspendLayout(); this.grpStereo.SuspendLayout(); @@ -137,16 +172,17 @@ namespace Mesen.GUI.Forms.Config // baseConfigPanel // this.baseConfigPanel.Controls.Add(this.btnReset); - this.baseConfigPanel.Location = new System.Drawing.Point(0, 375); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 373); this.baseConfigPanel.Size = new System.Drawing.Size(477, 29); this.baseConfigPanel.Controls.SetChildIndex(this.btnReset, 0); // // grpVolume // this.grpVolume.Controls.Add(this.tableLayoutPanel1); - this.grpVolume.Location = new System.Drawing.Point(3, 6); + this.grpVolume.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpVolume.Location = new System.Drawing.Point(3, 3); this.grpVolume.Name = "grpVolume"; - this.grpVolume.Size = new System.Drawing.Size(462, 341); + this.grpVolume.Size = new System.Drawing.Size(463, 341); this.grpVolume.TabIndex = 2; this.grpVolume.TabStop = false; this.grpVolume.Text = "Volume"; @@ -179,16 +215,17 @@ namespace Mesen.GUI.Forms.Config 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.Absolute, 20F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(456, 322); + this.tableLayoutPanel1.Size = new System.Drawing.Size(457, 322); this.tableLayoutPanel1.TabIndex = 2; // // trkDmcVol // this.trkDmcVol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkDmcVol.Location = new System.Drawing.Point(384, 0); + this.trkDmcVol.Location = new System.Drawing.Point(387, 0); this.trkDmcVol.Margin = new System.Windows.Forms.Padding(0); this.trkDmcVol.Maximum = 100; this.trkDmcVol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkDmcVol.Minimum = 0; this.trkDmcVol.MinimumSize = new System.Drawing.Size(63, 160); this.trkDmcVol.Name = "trkDmcVol"; this.trkDmcVol.Size = new System.Drawing.Size(63, 160); @@ -199,10 +236,11 @@ namespace Mesen.GUI.Forms.Config // trkNoiseVol // this.trkNoiseVol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkNoiseVol.Location = new System.Drawing.Point(306, 0); + this.trkNoiseVol.Location = new System.Drawing.Point(310, 0); this.trkNoiseVol.Margin = new System.Windows.Forms.Padding(0); this.trkNoiseVol.Maximum = 100; this.trkNoiseVol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkNoiseVol.Minimum = 0; this.trkNoiseVol.MinimumSize = new System.Drawing.Size(63, 160); this.trkNoiseVol.Name = "trkNoiseVol"; this.trkNoiseVol.Size = new System.Drawing.Size(63, 160); @@ -213,10 +251,11 @@ namespace Mesen.GUI.Forms.Config // trkTriangleVol // this.trkTriangleVol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkTriangleVol.Location = new System.Drawing.Point(231, 0); + this.trkTriangleVol.Location = new System.Drawing.Point(234, 0); this.trkTriangleVol.Margin = new System.Windows.Forms.Padding(0); this.trkTriangleVol.Maximum = 100; this.trkTriangleVol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkTriangleVol.Minimum = 0; this.trkTriangleVol.MinimumSize = new System.Drawing.Size(63, 160); this.trkTriangleVol.Name = "trkTriangleVol"; this.trkTriangleVol.Size = new System.Drawing.Size(63, 160); @@ -227,10 +266,11 @@ namespace Mesen.GUI.Forms.Config // trkSquare2Vol // this.trkSquare2Vol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkSquare2Vol.Location = new System.Drawing.Point(156, 0); + this.trkSquare2Vol.Location = new System.Drawing.Point(158, 0); this.trkSquare2Vol.Margin = new System.Windows.Forms.Padding(0); this.trkSquare2Vol.Maximum = 100; this.trkSquare2Vol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkSquare2Vol.Minimum = 0; this.trkSquare2Vol.MinimumSize = new System.Drawing.Size(63, 160); this.trkSquare2Vol.Name = "trkSquare2Vol"; this.trkSquare2Vol.Size = new System.Drawing.Size(63, 160); @@ -241,10 +281,11 @@ namespace Mesen.GUI.Forms.Config // trkSquare1Vol // this.trkSquare1Vol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkSquare1Vol.Location = new System.Drawing.Point(81, 0); + this.trkSquare1Vol.Location = new System.Drawing.Point(82, 0); this.trkSquare1Vol.Margin = new System.Windows.Forms.Padding(0); this.trkSquare1Vol.Maximum = 100; this.trkSquare1Vol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkSquare1Vol.Minimum = 0; this.trkSquare1Vol.MinimumSize = new System.Drawing.Size(63, 160); this.trkSquare1Vol.Name = "trkSquare1Vol"; this.trkSquare1Vol.Size = new System.Drawing.Size(63, 160); @@ -259,6 +300,7 @@ namespace Mesen.GUI.Forms.Config this.trkMaster.Margin = new System.Windows.Forms.Padding(0); this.trkMaster.Maximum = 100; this.trkMaster.MaximumSize = new System.Drawing.Size(63, 160); + this.trkMaster.Minimum = 0; this.trkMaster.MinimumSize = new System.Drawing.Size(63, 160); this.trkMaster.Name = "trkMaster"; this.trkMaster.Size = new System.Drawing.Size(63, 160); @@ -273,6 +315,7 @@ namespace Mesen.GUI.Forms.Config this.trkFdsVol.Margin = new System.Windows.Forms.Padding(0); this.trkFdsVol.Maximum = 100; this.trkFdsVol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkFdsVol.Minimum = 0; this.trkFdsVol.MinimumSize = new System.Drawing.Size(63, 160); this.trkFdsVol.Name = "trkFdsVol"; this.trkFdsVol.Size = new System.Drawing.Size(63, 160); @@ -283,10 +326,11 @@ namespace Mesen.GUI.Forms.Config // trkMmc5Vol // this.trkMmc5Vol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkMmc5Vol.Location = new System.Drawing.Point(81, 160); + this.trkMmc5Vol.Location = new System.Drawing.Point(82, 160); this.trkMmc5Vol.Margin = new System.Windows.Forms.Padding(0); this.trkMmc5Vol.Maximum = 100; this.trkMmc5Vol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkMmc5Vol.Minimum = 0; this.trkMmc5Vol.MinimumSize = new System.Drawing.Size(63, 160); this.trkMmc5Vol.Name = "trkMmc5Vol"; this.trkMmc5Vol.Size = new System.Drawing.Size(63, 160); @@ -297,10 +341,11 @@ namespace Mesen.GUI.Forms.Config // trkVrc6Vol // this.trkVrc6Vol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkVrc6Vol.Location = new System.Drawing.Point(156, 160); + this.trkVrc6Vol.Location = new System.Drawing.Point(158, 160); this.trkVrc6Vol.Margin = new System.Windows.Forms.Padding(0); this.trkVrc6Vol.Maximum = 100; this.trkVrc6Vol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkVrc6Vol.Minimum = 0; this.trkVrc6Vol.MinimumSize = new System.Drawing.Size(63, 160); this.trkVrc6Vol.Name = "trkVrc6Vol"; this.trkVrc6Vol.Size = new System.Drawing.Size(63, 160); @@ -311,10 +356,11 @@ namespace Mesen.GUI.Forms.Config // trkVrc7Vol // this.trkVrc7Vol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkVrc7Vol.Location = new System.Drawing.Point(231, 160); + this.trkVrc7Vol.Location = new System.Drawing.Point(234, 160); this.trkVrc7Vol.Margin = new System.Windows.Forms.Padding(0); this.trkVrc7Vol.Maximum = 100; this.trkVrc7Vol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkVrc7Vol.Minimum = 0; this.trkVrc7Vol.MinimumSize = new System.Drawing.Size(63, 160); this.trkVrc7Vol.Name = "trkVrc7Vol"; this.trkVrc7Vol.Size = new System.Drawing.Size(63, 160); @@ -325,10 +371,11 @@ namespace Mesen.GUI.Forms.Config // trkNamco163Vol // this.trkNamco163Vol.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkNamco163Vol.Location = new System.Drawing.Point(306, 160); + this.trkNamco163Vol.Location = new System.Drawing.Point(310, 160); this.trkNamco163Vol.Margin = new System.Windows.Forms.Padding(0); this.trkNamco163Vol.Maximum = 100; this.trkNamco163Vol.MaximumSize = new System.Drawing.Size(63, 160); + this.trkNamco163Vol.Minimum = 0; this.trkNamco163Vol.MinimumSize = new System.Drawing.Size(63, 160); this.trkNamco163Vol.Name = "trkNamco163Vol"; this.trkNamco163Vol.Size = new System.Drawing.Size(63, 160); @@ -339,10 +386,11 @@ namespace Mesen.GUI.Forms.Config // trkSunsoft5b // this.trkSunsoft5b.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.trkSunsoft5b.Location = new System.Drawing.Point(384, 160); + this.trkSunsoft5b.Location = new System.Drawing.Point(387, 160); this.trkSunsoft5b.Margin = new System.Windows.Forms.Padding(0); this.trkSunsoft5b.Maximum = 100; this.trkSunsoft5b.MaximumSize = new System.Drawing.Size(63, 160); + this.trkSunsoft5b.Minimum = 0; this.trkSunsoft5b.MinimumSize = new System.Drawing.Size(63, 160); this.trkSunsoft5b.Name = "trkSunsoft5b"; this.trkSunsoft5b.Size = new System.Drawing.Size(63, 160); @@ -376,7 +424,7 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(463, 343); + this.tableLayoutPanel2.Size = new System.Drawing.Size(463, 364); this.tableLayoutPanel2.TabIndex = 3; // // chkMuteSoundInBackground @@ -551,13 +599,14 @@ namespace Mesen.GUI.Forms.Config this.tabMain.Controls.Add(this.tpgGeneral); this.tabMain.Controls.Add(this.tpgVolume); this.tabMain.Controls.Add(this.tpgPanning); + this.tabMain.Controls.Add(this.tpgEqualizer); this.tabMain.Controls.Add(this.tpgEffects); this.tabMain.Controls.Add(this.tpgAdvanced); this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; this.tabMain.Location = new System.Drawing.Point(0, 0); this.tabMain.Name = "tabMain"; this.tabMain.SelectedIndex = 0; - this.tabMain.Size = new System.Drawing.Size(477, 375); + this.tabMain.Size = new System.Drawing.Size(477, 373); this.tabMain.TabIndex = 4; // // tpgGeneral @@ -566,7 +615,7 @@ namespace Mesen.GUI.Forms.Config this.tpgGeneral.Location = new System.Drawing.Point(4, 22); this.tpgGeneral.Name = "tpgGeneral"; this.tpgGeneral.Padding = new System.Windows.Forms.Padding(3); - this.tpgGeneral.Size = new System.Drawing.Size(469, 349); + this.tpgGeneral.Size = new System.Drawing.Size(469, 370); this.tpgGeneral.TabIndex = 0; this.tpgGeneral.Text = "General"; this.tpgGeneral.UseVisualStyleBackColor = true; @@ -577,7 +626,7 @@ namespace Mesen.GUI.Forms.Config this.tpgVolume.Location = new System.Drawing.Point(4, 22); this.tpgVolume.Name = "tpgVolume"; this.tpgVolume.Padding = new System.Windows.Forms.Padding(3); - this.tpgVolume.Size = new System.Drawing.Size(469, 349); + this.tpgVolume.Size = new System.Drawing.Size(469, 347); this.tpgVolume.TabIndex = 1; this.tpgVolume.Text = "Volume"; this.tpgVolume.UseVisualStyleBackColor = true; @@ -588,7 +637,7 @@ namespace Mesen.GUI.Forms.Config this.tpgPanning.Location = new System.Drawing.Point(4, 22); this.tpgPanning.Name = "tpgPanning"; this.tpgPanning.Padding = new System.Windows.Forms.Padding(3); - this.tpgPanning.Size = new System.Drawing.Size(469, 349); + this.tpgPanning.Size = new System.Drawing.Size(469, 370); this.tpgPanning.TabIndex = 4; this.tpgPanning.Text = "Panning"; this.tpgPanning.UseVisualStyleBackColor = true; @@ -621,7 +670,7 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel6.Size = new System.Drawing.Size(463, 343); + this.tableLayoutPanel6.Size = new System.Drawing.Size(463, 364); this.tableLayoutPanel6.TabIndex = 3; // // trkSquare1Pan @@ -789,13 +838,484 @@ namespace Mesen.GUI.Forms.Config this.trkSunsoftPan.Text = "Sunsoft"; this.trkSunsoftPan.Value = 0; // + // tpgEqualizer + // + this.tpgEqualizer.Controls.Add(this.groupBox1); + this.tpgEqualizer.Location = new System.Drawing.Point(4, 22); + this.tpgEqualizer.Name = "tpgEqualizer"; + this.tpgEqualizer.Padding = new System.Windows.Forms.Padding(3); + this.tpgEqualizer.Size = new System.Drawing.Size(469, 347); + this.tpgEqualizer.TabIndex = 5; + this.tpgEqualizer.Text = "Equalizer"; + this.tpgEqualizer.UseVisualStyleBackColor = true; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.chkEnableEqualizer); + this.groupBox1.Controls.Add(this.tlpEqualizer); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox1.Location = new System.Drawing.Point(3, 3); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(463, 341); + this.groupBox1.TabIndex = 4; + this.groupBox1.TabStop = false; + // + // chkEnableEqualizer + // + this.chkEnableEqualizer.AutoSize = true; + this.chkEnableEqualizer.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.chkEnableEqualizer.Location = new System.Drawing.Point(7, -1); + this.chkEnableEqualizer.Name = "chkEnableEqualizer"; + this.chkEnableEqualizer.Padding = new System.Windows.Forms.Padding(5, 0, 0, 0); + this.chkEnableEqualizer.Size = new System.Drawing.Size(110, 17); + this.chkEnableEqualizer.TabIndex = 5; + this.chkEnableEqualizer.Text = "Enable Equalizer"; + this.chkEnableEqualizer.UseVisualStyleBackColor = false; + this.chkEnableEqualizer.CheckedChanged += new System.EventHandler(this.chkEnableEqualizer_CheckedChanged); + // + // tlpEqualizer + // + this.tlpEqualizer.ColumnCount = 10; + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tlpEqualizer.Controls.Add(this.trkBand6Gain, 5, 1); + this.tlpEqualizer.Controls.Add(this.trkBand5Gain, 4, 1); + this.tlpEqualizer.Controls.Add(this.trkBand4Gain, 3, 1); + this.tlpEqualizer.Controls.Add(this.trkBand3Gain, 2, 1); + this.tlpEqualizer.Controls.Add(this.trkBand2Gain, 1, 1); + this.tlpEqualizer.Controls.Add(this.trkBand1Gain, 0, 1); + this.tlpEqualizer.Controls.Add(this.trkBand11Gain, 0, 2); + this.tlpEqualizer.Controls.Add(this.trkBand12Gain, 1, 2); + this.tlpEqualizer.Controls.Add(this.trkBand13Gain, 2, 2); + this.tlpEqualizer.Controls.Add(this.trkBand14Gain, 3, 2); + this.tlpEqualizer.Controls.Add(this.trkBand15Gain, 4, 2); + this.tlpEqualizer.Controls.Add(this.trkBand16Gain, 5, 2); + this.tlpEqualizer.Controls.Add(this.trkBand7Gain, 6, 1); + this.tlpEqualizer.Controls.Add(this.trkBand8Gain, 7, 1); + this.tlpEqualizer.Controls.Add(this.trkBand9Gain, 8, 1); + this.tlpEqualizer.Controls.Add(this.trkBand10Gain, 9, 1); + this.tlpEqualizer.Controls.Add(this.trkBand17Gain, 6, 2); + this.tlpEqualizer.Controls.Add(this.trkBand18Gain, 7, 2); + this.tlpEqualizer.Controls.Add(this.trkBand19Gain, 8, 2); + this.tlpEqualizer.Controls.Add(this.trkBand20Gain, 9, 2); + this.tlpEqualizer.Controls.Add(this.flowLayoutPanel6, 0, 0); + this.tlpEqualizer.Controls.Add(this.flowLayoutPanel7, 6, 0); + this.tlpEqualizer.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlpEqualizer.Location = new System.Drawing.Point(3, 16); + this.tlpEqualizer.Name = "tlpEqualizer"; + this.tlpEqualizer.RowCount = 4; + this.tlpEqualizer.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpEqualizer.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpEqualizer.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpEqualizer.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tlpEqualizer.Size = new System.Drawing.Size(457, 322); + this.tlpEqualizer.TabIndex = 3; + // + // trkBand6Gain + // + this.trkBand6Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand6Gain.Location = new System.Drawing.Point(225, 23); + this.trkBand6Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand6Gain.Maximum = 200; + this.trkBand6Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand6Gain.Minimum = -200; + this.trkBand6Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand6Gain.Name = "trkBand6Gain"; + this.trkBand6Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand6Gain.TabIndex = 16; + this.trkBand6Gain.Text = "225 Hz"; + this.trkBand6Gain.Value = 50; + this.trkBand6Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand5Gain + // + this.trkBand5Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand5Gain.Location = new System.Drawing.Point(180, 23); + this.trkBand5Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand5Gain.Maximum = 200; + this.trkBand5Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand5Gain.Minimum = -200; + this.trkBand5Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand5Gain.Name = "trkBand5Gain"; + this.trkBand5Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand5Gain.TabIndex = 15; + this.trkBand5Gain.Text = "160 Hz"; + this.trkBand5Gain.Value = 50; + this.trkBand5Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand4Gain + // + this.trkBand4Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand4Gain.Location = new System.Drawing.Point(135, 23); + this.trkBand4Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand4Gain.Maximum = 200; + this.trkBand4Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand4Gain.Minimum = -200; + this.trkBand4Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand4Gain.Name = "trkBand4Gain"; + this.trkBand4Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand4Gain.TabIndex = 14; + this.trkBand4Gain.Text = "113 Hz"; + this.trkBand4Gain.Value = 50; + this.trkBand4Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand3Gain + // + this.trkBand3Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand3Gain.Location = new System.Drawing.Point(90, 23); + this.trkBand3Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand3Gain.Maximum = 200; + this.trkBand3Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand3Gain.Minimum = -200; + this.trkBand3Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand3Gain.Name = "trkBand3Gain"; + this.trkBand3Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand3Gain.TabIndex = 13; + this.trkBand3Gain.Text = "80 Hz"; + this.trkBand3Gain.Value = 50; + this.trkBand3Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand2Gain + // + this.trkBand2Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand2Gain.Location = new System.Drawing.Point(45, 23); + this.trkBand2Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand2Gain.Maximum = 200; + this.trkBand2Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand2Gain.Minimum = -200; + this.trkBand2Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand2Gain.Name = "trkBand2Gain"; + this.trkBand2Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand2Gain.TabIndex = 12; + this.trkBand2Gain.Text = "56 Hz"; + this.trkBand2Gain.Value = 50; + this.trkBand2Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand1Gain + // + this.trkBand1Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand1Gain.Location = new System.Drawing.Point(0, 23); + this.trkBand1Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand1Gain.Maximum = 200; + this.trkBand1Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand1Gain.Minimum = -200; + this.trkBand1Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand1Gain.Name = "trkBand1Gain"; + this.trkBand1Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand1Gain.TabIndex = 11; + this.trkBand1Gain.Text = "40 Hz"; + this.trkBand1Gain.Value = 50; + this.trkBand1Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand11Gain + // + this.trkBand11Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand11Gain.Location = new System.Drawing.Point(0, 183); + this.trkBand11Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand11Gain.Maximum = 200; + this.trkBand11Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand11Gain.Minimum = -200; + this.trkBand11Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand11Gain.Name = "trkBand11Gain"; + this.trkBand11Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand11Gain.TabIndex = 17; + this.trkBand11Gain.Text = "1.0 kHz"; + this.trkBand11Gain.Value = 50; + this.trkBand11Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand12Gain + // + this.trkBand12Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand12Gain.Location = new System.Drawing.Point(45, 183); + this.trkBand12Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand12Gain.Maximum = 200; + this.trkBand12Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand12Gain.Minimum = -200; + this.trkBand12Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand12Gain.Name = "trkBand12Gain"; + this.trkBand12Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand12Gain.TabIndex = 18; + this.trkBand12Gain.Text = "2.0 kHz"; + this.trkBand12Gain.Value = 50; + this.trkBand12Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand13Gain + // + this.trkBand13Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand13Gain.Location = new System.Drawing.Point(90, 183); + this.trkBand13Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand13Gain.Maximum = 200; + this.trkBand13Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand13Gain.Minimum = -200; + this.trkBand13Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand13Gain.Name = "trkBand13Gain"; + this.trkBand13Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand13Gain.TabIndex = 19; + this.trkBand13Gain.Text = "3.0 kHz"; + this.trkBand13Gain.Value = 50; + this.trkBand13Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand14Gain + // + this.trkBand14Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand14Gain.Location = new System.Drawing.Point(135, 183); + this.trkBand14Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand14Gain.Maximum = 200; + this.trkBand14Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand14Gain.Minimum = -200; + this.trkBand14Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand14Gain.Name = "trkBand14Gain"; + this.trkBand14Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand14Gain.TabIndex = 20; + this.trkBand14Gain.Text = "4.0 kHz"; + this.trkBand14Gain.Value = 50; + this.trkBand14Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand15Gain + // + this.trkBand15Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand15Gain.Location = new System.Drawing.Point(180, 183); + this.trkBand15Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand15Gain.Maximum = 200; + this.trkBand15Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand15Gain.Minimum = -200; + this.trkBand15Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand15Gain.Name = "trkBand15Gain"; + this.trkBand15Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand15Gain.TabIndex = 21; + this.trkBand15Gain.Text = "5.0 kHz"; + this.trkBand15Gain.Value = 50; + this.trkBand15Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand16Gain + // + this.trkBand16Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand16Gain.Location = new System.Drawing.Point(225, 183); + this.trkBand16Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand16Gain.Maximum = 200; + this.trkBand16Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand16Gain.Minimum = -200; + this.trkBand16Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand16Gain.Name = "trkBand16Gain"; + this.trkBand16Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand16Gain.TabIndex = 22; + this.trkBand16Gain.Text = "6.0 kHz"; + this.trkBand16Gain.Value = 50; + this.trkBand16Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand7Gain + // + this.trkBand7Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand7Gain.Location = new System.Drawing.Point(270, 23); + this.trkBand7Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand7Gain.Maximum = 200; + this.trkBand7Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand7Gain.Minimum = -200; + this.trkBand7Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand7Gain.Name = "trkBand7Gain"; + this.trkBand7Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand7Gain.TabIndex = 23; + this.trkBand7Gain.Text = "320 Hz"; + this.trkBand7Gain.Value = 50; + this.trkBand7Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand8Gain + // + this.trkBand8Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand8Gain.Location = new System.Drawing.Point(315, 23); + this.trkBand8Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand8Gain.Maximum = 200; + this.trkBand8Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand8Gain.Minimum = -200; + this.trkBand8Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand8Gain.Name = "trkBand8Gain"; + this.trkBand8Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand8Gain.TabIndex = 24; + this.trkBand8Gain.Text = "450 Hz"; + this.trkBand8Gain.Value = 50; + this.trkBand8Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand9Gain + // + this.trkBand9Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand9Gain.Location = new System.Drawing.Point(360, 23); + this.trkBand9Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand9Gain.Maximum = 200; + this.trkBand9Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand9Gain.Minimum = -200; + this.trkBand9Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand9Gain.Name = "trkBand9Gain"; + this.trkBand9Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand9Gain.TabIndex = 25; + this.trkBand9Gain.Text = "600 Hz"; + this.trkBand9Gain.Value = 50; + this.trkBand9Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand10Gain + // + this.trkBand10Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand10Gain.Location = new System.Drawing.Point(405, 23); + this.trkBand10Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand10Gain.Maximum = 200; + this.trkBand10Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand10Gain.Minimum = -200; + this.trkBand10Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand10Gain.Name = "trkBand10Gain"; + this.trkBand10Gain.Size = new System.Drawing.Size(52, 160); + this.trkBand10Gain.TabIndex = 26; + this.trkBand10Gain.Text = "750 Hz"; + this.trkBand10Gain.Value = 50; + this.trkBand10Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand17Gain + // + this.trkBand17Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand17Gain.Location = new System.Drawing.Point(270, 183); + this.trkBand17Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand17Gain.Maximum = 200; + this.trkBand17Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand17Gain.Minimum = -200; + this.trkBand17Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand17Gain.Name = "trkBand17Gain"; + this.trkBand17Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand17Gain.TabIndex = 27; + this.trkBand17Gain.Text = "7.0 kHz"; + this.trkBand17Gain.Value = 50; + this.trkBand17Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand18Gain + // + this.trkBand18Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand18Gain.Location = new System.Drawing.Point(315, 183); + this.trkBand18Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand18Gain.Maximum = 200; + this.trkBand18Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand18Gain.Minimum = -200; + this.trkBand18Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand18Gain.Name = "trkBand18Gain"; + this.trkBand18Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand18Gain.TabIndex = 28; + this.trkBand18Gain.Text = "10.0 kHz"; + this.trkBand18Gain.Value = 50; + this.trkBand18Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand19Gain + // + this.trkBand19Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand19Gain.Location = new System.Drawing.Point(360, 183); + this.trkBand19Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand19Gain.Maximum = 200; + this.trkBand19Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand19Gain.Minimum = -200; + this.trkBand19Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand19Gain.Name = "trkBand19Gain"; + this.trkBand19Gain.Size = new System.Drawing.Size(45, 160); + this.trkBand19Gain.TabIndex = 29; + this.trkBand19Gain.Text = "12.5 kHz"; + this.trkBand19Gain.Value = 50; + this.trkBand19Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // trkBand20Gain + // + this.trkBand20Gain.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBand20Gain.Location = new System.Drawing.Point(405, 183); + this.trkBand20Gain.Margin = new System.Windows.Forms.Padding(0); + this.trkBand20Gain.Maximum = 200; + this.trkBand20Gain.MaximumSize = new System.Drawing.Size(63, 160); + this.trkBand20Gain.Minimum = -200; + this.trkBand20Gain.MinimumSize = new System.Drawing.Size(34, 160); + this.trkBand20Gain.Name = "trkBand20Gain"; + this.trkBand20Gain.Size = new System.Drawing.Size(52, 160); + this.trkBand20Gain.TabIndex = 30; + this.trkBand20Gain.Text = "15 kHz"; + this.trkBand20Gain.Value = 50; + this.trkBand20Gain.ValueChanged += new System.EventHandler(this.trkBandGain_ValueChanged); + // + // flowLayoutPanel6 + // + this.flowLayoutPanel6.AutoSize = true; + this.tlpEqualizer.SetColumnSpan(this.flowLayoutPanel6, 5); + this.flowLayoutPanel6.Controls.Add(this.lblEqualizerPreset); + this.flowLayoutPanel6.Controls.Add(this.cboEqualizerPreset); + this.flowLayoutPanel6.Location = new System.Drawing.Point(0, 2); + this.flowLayoutPanel6.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0); + this.flowLayoutPanel6.Name = "flowLayoutPanel6"; + this.flowLayoutPanel6.Size = new System.Drawing.Size(167, 21); + this.flowLayoutPanel6.TabIndex = 33; + this.flowLayoutPanel6.Visible = false; + // + // lblEqualizerPreset + // + this.lblEqualizerPreset.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblEqualizerPreset.AutoSize = true; + this.lblEqualizerPreset.Location = new System.Drawing.Point(3, 4); + this.lblEqualizerPreset.Name = "lblEqualizerPreset"; + this.lblEqualizerPreset.Size = new System.Drawing.Size(40, 13); + this.lblEqualizerPreset.TabIndex = 32; + this.lblEqualizerPreset.Text = "Preset:"; + // + // cboEqualizerPreset + // + this.cboEqualizerPreset.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.cboEqualizerPreset.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboEqualizerPreset.FormattingEnabled = true; + this.cboEqualizerPreset.Location = new System.Drawing.Point(46, 0); + this.cboEqualizerPreset.Margin = new System.Windows.Forms.Padding(0); + this.cboEqualizerPreset.Name = "cboEqualizerPreset"; + this.cboEqualizerPreset.Size = new System.Drawing.Size(121, 21); + this.cboEqualizerPreset.TabIndex = 33; + this.cboEqualizerPreset.SelectedIndexChanged += new System.EventHandler(this.cboEqualizerPreset_SelectedIndexChanged); + // + // flowLayoutPanel7 + // + this.flowLayoutPanel7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.flowLayoutPanel7.AutoSize = true; + this.tlpEqualizer.SetColumnSpan(this.flowLayoutPanel7, 4); + this.flowLayoutPanel7.Controls.Add(this.lblEqualizerFilterType); + this.flowLayoutPanel7.Controls.Add(this.cboEqualizerFilterType); + this.flowLayoutPanel7.Location = new System.Drawing.Point(298, 2); + this.flowLayoutPanel7.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0); + this.flowLayoutPanel7.Name = "flowLayoutPanel7"; + this.flowLayoutPanel7.Size = new System.Drawing.Size(159, 21); + this.flowLayoutPanel7.TabIndex = 34; + this.flowLayoutPanel7.Visible = false; + // + // lblEqualizerFilterType + // + this.lblEqualizerFilterType.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblEqualizerFilterType.AutoSize = true; + this.lblEqualizerFilterType.Location = new System.Drawing.Point(3, 4); + this.lblEqualizerFilterType.Name = "lblEqualizerFilterType"; + this.lblEqualizerFilterType.Size = new System.Drawing.Size(32, 13); + this.lblEqualizerFilterType.TabIndex = 31; + this.lblEqualizerFilterType.Text = "Filter:"; + // + // cboEqualizerFilterType + // + this.cboEqualizerFilterType.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.cboEqualizerFilterType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboEqualizerFilterType.FormattingEnabled = true; + this.cboEqualizerFilterType.Location = new System.Drawing.Point(38, 0); + this.cboEqualizerFilterType.Margin = new System.Windows.Forms.Padding(0); + this.cboEqualizerFilterType.Name = "cboEqualizerFilterType"; + this.cboEqualizerFilterType.Size = new System.Drawing.Size(121, 21); + this.cboEqualizerFilterType.TabIndex = 32; + // // tpgEffects // this.tpgEffects.Controls.Add(this.tableLayoutPanel4); this.tpgEffects.Location = new System.Drawing.Point(4, 22); this.tpgEffects.Name = "tpgEffects"; this.tpgEffects.Padding = new System.Windows.Forms.Padding(3); - this.tpgEffects.Size = new System.Drawing.Size(469, 349); + this.tpgEffects.Size = new System.Drawing.Size(469, 370); this.tpgEffects.TabIndex = 3; this.tpgEffects.Text = "Effects"; this.tpgEffects.UseVisualStyleBackColor = true; @@ -815,7 +1335,7 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel4.Size = new System.Drawing.Size(463, 343); + this.tableLayoutPanel4.Size = new System.Drawing.Size(463, 364); this.tableLayoutPanel4.TabIndex = 0; // // grpStereo @@ -1086,7 +1606,7 @@ namespace Mesen.GUI.Forms.Config this.tpgAdvanced.Location = new System.Drawing.Point(4, 22); this.tpgAdvanced.Name = "tpgAdvanced"; this.tpgAdvanced.Padding = new System.Windows.Forms.Padding(3); - this.tpgAdvanced.Size = new System.Drawing.Size(469, 349); + this.tpgAdvanced.Size = new System.Drawing.Size(469, 370); this.tpgAdvanced.TabIndex = 2; this.tpgAdvanced.Text = "Advanced"; this.tpgAdvanced.UseVisualStyleBackColor = true; @@ -1108,7 +1628,7 @@ namespace Mesen.GUI.Forms.Config this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(463, 343); + this.tableLayoutPanel3.Size = new System.Drawing.Size(463, 364); this.tableLayoutPanel3.TabIndex = 1; // // chkDisableNoiseModeFlag @@ -1156,7 +1676,7 @@ namespace Mesen.GUI.Forms.Config // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(477, 404); + this.ClientSize = new System.Drawing.Size(477, 402); this.Controls.Add(this.tabMain); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; @@ -1181,6 +1701,15 @@ namespace Mesen.GUI.Forms.Config this.tpgVolume.ResumeLayout(false); this.tpgPanning.ResumeLayout(false); this.tableLayoutPanel6.ResumeLayout(false); + this.tpgEqualizer.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.tlpEqualizer.ResumeLayout(false); + this.tlpEqualizer.PerformLayout(); + this.flowLayoutPanel6.ResumeLayout(false); + this.flowLayoutPanel6.PerformLayout(); + this.flowLayoutPanel7.ResumeLayout(false); + this.flowLayoutPanel7.PerformLayout(); this.tpgEffects.ResumeLayout(false); this.tableLayoutPanel4.ResumeLayout(false); this.grpStereo.ResumeLayout(false); @@ -1284,5 +1813,35 @@ namespace Mesen.GUI.Forms.Config private System.Windows.Forms.Label lblCrossFeedRatio; private Controls.ctrlHorizontalTrackbar trkTrianglePan; private ctrlRiskyOption chkDisableNoiseModeFlag; + private System.Windows.Forms.TabPage tpgEqualizer; + private System.Windows.Forms.TableLayoutPanel tlpEqualizer; + private ctrlTrackbar trkBand6Gain; + private ctrlTrackbar trkBand5Gain; + private ctrlTrackbar trkBand4Gain; + private ctrlTrackbar trkBand3Gain; + private ctrlTrackbar trkBand2Gain; + private ctrlTrackbar trkBand1Gain; + private ctrlTrackbar trkBand11Gain; + private ctrlTrackbar trkBand12Gain; + private ctrlTrackbar trkBand13Gain; + private ctrlTrackbar trkBand14Gain; + private ctrlTrackbar trkBand15Gain; + private ctrlTrackbar trkBand16Gain; + private ctrlTrackbar trkBand7Gain; + private ctrlTrackbar trkBand8Gain; + private ctrlTrackbar trkBand9Gain; + private ctrlTrackbar trkBand10Gain; + private ctrlTrackbar trkBand17Gain; + private ctrlTrackbar trkBand18Gain; + private ctrlTrackbar trkBand19Gain; + private ctrlTrackbar trkBand20Gain; + private System.Windows.Forms.Label lblEqualizerFilterType; + private System.Windows.Forms.ComboBox cboEqualizerFilterType; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.CheckBox chkEnableEqualizer; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel6; + private System.Windows.Forms.Label lblEqualizerPreset; + private System.Windows.Forms.ComboBox cboEqualizerPreset; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel7; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmAudioConfig.cs b/GUI.NET/Forms/Config/frmAudioConfig.cs index 1bccde76..d24d6924 100644 --- a/GUI.NET/Forms/Config/frmAudioConfig.cs +++ b/GUI.NET/Forms/Config/frmAudioConfig.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Mesen.GUI.Config; +using Mesen.GUI.Controls; namespace Mesen.GUI.Forms.Config { @@ -25,6 +26,8 @@ namespace Mesen.GUI.Forms.Config Icon = Properties.Resources.Audio; Entity = ConfigManager.Config.AudioInfo; + tlpEqualizer.Enabled = false; + cboAudioDevice.Items.AddRange(InteropEmu.GetAudioDevices().ToArray()); AddBinding("EnableAudio", chkEnableAudio); @@ -57,6 +60,32 @@ namespace Mesen.GUI.Forms.Config AddBinding("SampleRate", cboSampleRate); AddBinding("AudioDevice", cboAudioDevice); + AddBinding("EnableEqualizer", chkEnableEqualizer); + //TODO: Uncomment when equalizer presets are implemented + //AddBinding("EqualizerPreset", cboEqualizerPreset); + //AddBinding("EqualizerFilterType", cboEqualizerFilterType); + + AddBinding("Band1Gain", trkBand1Gain); + AddBinding("Band2Gain", trkBand2Gain); + AddBinding("Band3Gain", trkBand3Gain); + AddBinding("Band4Gain", trkBand4Gain); + AddBinding("Band5Gain", trkBand5Gain); + AddBinding("Band6Gain", trkBand6Gain); + AddBinding("Band7Gain", trkBand7Gain); + AddBinding("Band8Gain", trkBand8Gain); + AddBinding("Band9Gain", trkBand9Gain); + AddBinding("Band10Gain", trkBand10Gain); + AddBinding("Band11Gain", trkBand11Gain); + AddBinding("Band12Gain", trkBand12Gain); + AddBinding("Band13Gain", trkBand13Gain); + AddBinding("Band14Gain", trkBand14Gain); + AddBinding("Band15Gain", trkBand15Gain); + AddBinding("Band16Gain", trkBand16Gain); + AddBinding("Band17Gain", trkBand17Gain); + AddBinding("Band18Gain", trkBand18Gain); + AddBinding("Band19Gain", trkBand19Gain); + AddBinding("Band20Gain", trkBand20Gain); + AddBinding("ReduceSoundInBackground", chkReduceSoundInBackground); AddBinding("MuteSoundInBackground", chkMuteSoundInBackground); @@ -79,6 +108,12 @@ namespace Mesen.GUI.Forms.Config AddBinding("CrossFeedEnabled", chkCrossFeedEnabled); AddBinding("CrossFeedRatio", nudCrossFeedRatio); + + //TODO: Uncomment when equalizer presets are implemented + /*cboEqualizerFilterType.Items.RemoveAt(0); //Remove "None" from dropdown + if(cboEqualizerFilterType.SelectedItem == null) { + cboEqualizerFilterType.SelectedIndex = 0; + }*/ } protected override void OnFormClosed(FormClosedEventArgs e) @@ -113,5 +148,62 @@ namespace Mesen.GUI.Forms.Config picLatencyWarning.Visible = nudLatency.Value <= 30; lblLatencyWarning.Visible = nudLatency.Value <= 30; } + + private void cboEqualizerPreset_SelectedIndexChanged(object sender, EventArgs e) + { + EqualizerPreset preset = cboEqualizerPreset.GetEnumValue(); + + foreach(Control ctrl in tlpEqualizer.Controls) { + if(ctrl is ctrlTrackbar) { + ctrl.Enabled = preset < EqualizerPreset.TwinFamicom60; + } + } + + AudioInfo audio = (AudioInfo)Entity; + audio.EqualizerPreset = preset; + switch(preset) { + case EqualizerPreset.TwinFamicom: + audio.Band1Gain = -44; + audio.Band2Gain = -22; + audio.Band3Gain = -10; + audio.Band4Gain = -7; + audio.Band5Gain = -3; + audio.Band6Gain = 0; + audio.Band7Gain = -2; + audio.Band8Gain = -3; + audio.Band9Gain = 0; + audio.Band10Gain = -3; + audio.Band11Gain = -4; + audio.Band12Gain = -9; + audio.Band13Gain = -17; + audio.Band14Gain = -28; + audio.Band15Gain = -44; + audio.Band16Gain = -65; + audio.Band17Gain = -83; + audio.Band18Gain = -103; + audio.Band19Gain = -109; + audio.Band20Gain = -94; + UpdateUI(); + break; + } + + if(cboEqualizerPreset.GetEnumValue() != preset) { + this.BeginInvoke((Action)(() => { + cboEqualizerPreset.SetEnumValue(preset); + })); + } + } + + private void trkBandGain_ValueChanged(object sender, EventArgs e) + { + if(!this.Updating) { + cboEqualizerPreset.SetEnumValue(EqualizerPreset.Custom); + } + } + + private void chkEnableEqualizer_CheckedChanged(object sender, EventArgs e) + { + tlpEqualizer.Enabled = chkEnableEqualizer.Checked; + } } } diff --git a/GUI.NET/Forms/EntityBinder.cs b/GUI.NET/Forms/EntityBinder.cs index 13f2bb72..69743d41 100644 --- a/GUI.NET/Forms/EntityBinder.cs +++ b/GUI.NET/Forms/EntityBinder.cs @@ -85,7 +85,11 @@ namespace Mesen.GUI.Forms throw new Exception("No radio button matching value found"); } } else if(kvp.Value is ctrlTrackbar) { - ((ctrlTrackbar)kvp.Value).Value = (int)(uint)value; + if(field.FieldType == typeof(Int32)) { + ((ctrlTrackbar)kvp.Value).Value = (int)value; + } else { + ((ctrlTrackbar)kvp.Value).Value = (int)(uint)value; + } } else if(kvp.Value is ctrlHorizontalTrackbar) { ((ctrlHorizontalTrackbar)kvp.Value).Value = (int)value; } else if(kvp.Value is TrackBar) { @@ -173,7 +177,11 @@ namespace Mesen.GUI.Forms } else if(kvp.Value is Panel) { field.SetValue(Entity, kvp.Value.Controls.OfType().FirstOrDefault(r => r.Checked).Tag); } else if(kvp.Value is ctrlTrackbar) { - field.SetValue(Entity, (UInt32)((ctrlTrackbar)kvp.Value).Value); + if(field.FieldType == typeof(Int32)) { + field.SetValue(Entity, (Int32)((ctrlTrackbar)kvp.Value).Value); + } else { + field.SetValue(Entity, (UInt32)((ctrlTrackbar)kvp.Value).Value); + } } else if(kvp.Value is ctrlHorizontalTrackbar) { field.SetValue(Entity, (Int32)((ctrlHorizontalTrackbar)kvp.Value).Value); } else if(kvp.Value is TrackBar) { diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index d58557ff..81901f00 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -133,6 +133,9 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void SetMasterVolume(double volume); [DllImport(DLLPath)] public static extern void SetChannelVolume(AudioChannel channel, double volume); [DllImport(DLLPath)] public static extern void SetChannelPanning(AudioChannel channel, double panning); + [DllImport(DLLPath)] public static extern void SetEqualizerFilterType(EqualizerFilterType filter); + [DllImport(DLLPath)] public static extern void SetEqualizerBands([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]double[] bands, UInt32 length); + [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); @@ -1243,6 +1246,14 @@ namespace Mesen.GUI Sunsoft5B = 10 } + public enum EqualizerFilterType + { + None = 0, + Butterworth = 1, + Chebyshev1 = 2, + Chebyshev2 = 3 + } + public enum VideoCodec { None = 0, diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index b8957203..9ae56591 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -358,6 +358,9 @@ namespace InteropEmu { DllExport void __stdcall SetDisplayLanguage(Language lang) { EmulationSettings::SetDisplayLanguage(lang); } DllExport void __stdcall SetChannelVolume(uint32_t channel, double volume) { EmulationSettings::SetChannelVolume((AudioChannel)channel, volume); } DllExport void __stdcall SetChannelPanning(uint32_t channel, double panning) { EmulationSettings::SetChannelPanning((AudioChannel)channel, panning); } + DllExport void __stdcall SetEqualizerFilterType(EqualizerFilterType filter) { EmulationSettings::SetEqualizerFilterType(filter); } + DllExport void __stdcall SetBandGain(uint32_t band, double gain) { EmulationSettings::SetBandGain(band, gain); } + DllExport void __stdcall SetEqualizerBands(double *bands, uint32_t bandCount) { EmulationSettings::SetEqualizerBands(bands, bandCount); } DllExport void __stdcall SetMasterVolume(double volume) { EmulationSettings::SetMasterVolume(volume); } DllExport void __stdcall SetSampleRate(uint32_t sampleRate) { EmulationSettings::SetSampleRate(sampleRate); } DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { EmulationSettings::SetAudioLatency(msLatency); } diff --git a/Utilities/Utilities.vcxproj b/Utilities/Utilities.vcxproj index 09590945..1fb05c24 100644 --- a/Utilities/Utilities.vcxproj +++ b/Utilities/Utilities.vcxproj @@ -341,6 +341,7 @@ + diff --git a/Utilities/Utilities.vcxproj.filters b/Utilities/Utilities.vcxproj.filters index a8915fee..0da9dc48 100644 --- a/Utilities/Utilities.vcxproj.filters +++ b/Utilities/Utilities.vcxproj.filters @@ -152,6 +152,9 @@ Patches + + Header Files + diff --git a/Utilities/orfanidis_eq.h b/Utilities/orfanidis_eq.h new file mode 100644 index 00000000..012f448d --- /dev/null +++ b/Utilities/orfanidis_eq.h @@ -0,0 +1,1170 @@ +#ifndef ORFANIDIS_EQ_H_ +#define ORFANIDIS_EQ_H_ + +#include +#include + +using namespace std; + +namespace orfanidis_eq { + //Eq data types. + typedef double eq_single_t; + typedef double eq_double_t; + //NOTE: the default float type usage + //can have shortage of precision + + //Eq types + typedef enum + { + none, + butterworth, + chebyshev1, + chebyshev2 + } filter_type; + + static const char *get_eq_text(filter_type type) { + switch(type) { + case none: + return "not initialized"; + case butterworth: + return "butterworth"; + case chebyshev1: + return "chebyshev1"; + case chebyshev2: + return "chebyshev2"; + default: + return "none"; + } + } + + //Eq errors + typedef enum + { + no_error, + invalid_input_data_error, + processing_error + } eq_error_t; + + //Constants + static const eq_double_t pi = 3.1415926535897932384626433832795; + static const unsigned int fo_section_order = 4; + + //Default gains + static const int max_base_gain_db = 0; + static const int min_base_gain_db = -60; + static const int butterworth_band_gain_db = -3; + static const int chebyshev1_band_base_gain_db = -6; + static const int chebyshev2_band_base_gain_db = -40; + static const int eq_min_max_gain_db = 46; + + //Default freq's + static const eq_double_t lowest_grid_center_freq_hz = 31.25; + static const eq_double_t bands_grid_center_freq_hz = 1000; + static const eq_double_t lowest_audio_freq_hz = 20; + static const eq_double_t highest_audio_freq_hz = 20000; + + //Eq config constants + static const unsigned int default_eq_band_filters_order = 4; //>2 + static const eq_double_t default_sample_freq_hz = 48000; + + //Precomputed Eq (eq2) config constants + static const eq_double_t p_eq_min_max_gain_db = 40; + static const eq_double_t p_eq_gain_step_db = 1; + static const eq_double_t common_base_gain_db = 3; + static const eq_double_t p_eq_default_gain_db = 0; + + //Version + static const char* eq_version = "0.01"; + + + //------------ Conversion functions class ------------ + class conversions + { + int db_min_max; + std::vector lin_gains; + + int lin_gains_index(eq_double_t x) { + int int_x = (int)x; + if((x >= -db_min_max) && (x < db_min_max - 1)) + return db_min_max + int_x; + + return db_min_max; + } + + conversions() {} + + public: + conversions(int min_max) { + db_min_max = min_max; + //Update table (vector elements) for fast conversions + int step = -min_max; + while(step <= min_max) + lin_gains.push_back(db_2_lin(step++)); + } + + inline eq_double_t fast_db_2_lin(eq_double_t x) { + int int_part = (int)x; + eq_double_t frac_part = x - int_part; + return lin_gains[lin_gains_index(int_part)] * (1 - frac_part) + + (lin_gains[lin_gains_index(int_part + 1)])*frac_part; + } + + inline eq_double_t fast_lin_2_db(eq_double_t x) { + if((x >= lin_gains[0]) && (x < lin_gains[lin_gains.size() - 1])) { + for(unsigned int i = 0; i < lin_gains.size() - 2; i++) + if((x >= lin_gains[i]) && (x < lin_gains[i + 1])) { + int int_part = i - db_min_max; + eq_double_t frac_part = x - (int)(x); + return int_part + frac_part; + } + } + return 0; + } + + inline static eq_double_t db_2_lin(eq_double_t x) { + return pow(10, x / 20); + } + + inline static eq_double_t lin_2_db(eq_double_t x) { + return 20 * log10(x); + } + + inline static eq_double_t rad_2_hz(eq_double_t x, eq_double_t fs) { + return 2 * pi / x*fs; + } + + inline static eq_double_t hz_2_rad(eq_double_t x, eq_double_t fs) { + return 2 * pi*x / fs; + } + }; + + //------------ Band freq's structure ------------ + struct band_freqs + { + private: + band_freqs(); + + public: + eq_double_t min_freq; + eq_double_t center_freq; + eq_double_t max_freq; + + band_freqs(eq_double_t f1, eq_double_t f0, eq_double_t f2) : + min_freq(f1), center_freq(f0), max_freq(f2) {} + + ~band_freqs() {} + }; + + //------------ Frequency grid class ------------ + class freq_grid + { + private: + std::vector freqs_; + + public: + freq_grid() {} + freq_grid(const freq_grid& fg) { this->freqs_ = fg.freqs_; } + ~freq_grid() {} + + eq_error_t set_band(eq_double_t fmin, eq_double_t f0, eq_double_t fmax) { + freqs_.clear(); + return add_band(fmin, f0, fmax); + } + + //fc, fmin, fmax + eq_error_t add_band(eq_double_t fmin, eq_double_t f0, eq_double_t fmax) { + if(fmin < f0 && f0 < fmax) + freqs_.push_back(band_freqs(fmin, f0, fmax)); + else + return invalid_input_data_error; + return no_error; + } + + //f0, deltaf = fmax - fmin + eq_error_t add_band(eq_double_t f0, eq_double_t df) { + if(f0 >= df / 2) { + eq_double_t fmin = f0 - df / 2; + eq_double_t fmax = f0 + df / 2; + freqs_.push_back(band_freqs(fmin, f0, fmax)); + } else + return invalid_input_data_error; + return no_error; + } + + eq_error_t set_5_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + freqs_.clear(); + if(lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) { + + //Find lowest center frequency in band + eq_double_t lowest_center_freq = center_freq; + while(lowest_center_freq > lowest_grid_center_freq_hz) + lowest_center_freq /= 4.0; + if(lowest_center_freq < lowest_grid_center_freq_hz) + lowest_center_freq *= 4.0; + + //Calculate freq's + eq_double_t f0 = lowest_center_freq; + for(unsigned int i = 0; i < 5; i++) { + freqs_.push_back(band_freqs(f0 / 2, f0, f0 * 2)); + f0 *= 4; + } + } else + return invalid_input_data_error; + return no_error; + } + + eq_error_t set_10_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + freqs_.clear(); + if(lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) { + + //Find lowest center frequency in band + eq_double_t lowest_center_freq = center_freq; + while(lowest_center_freq > lowest_grid_center_freq_hz) + lowest_center_freq /= 2; + if(lowest_center_freq < lowest_grid_center_freq_hz) + lowest_center_freq *= 2; + + //Calculate freq's + eq_double_t f0 = lowest_center_freq; + for(unsigned int i = 0; i < 10; i++) { + freqs_.push_back(band_freqs(f0 / pow(2, 0.5), f0, f0*pow(2, 0.5))); + f0 *= 2; + } + } else + return invalid_input_data_error; + return no_error; + } + + eq_error_t set_20_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + freqs_.clear(); + if(lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) { + + //Find lowest center frequency in band + eq_double_t lowest_center_freq = center_freq; + while(lowest_center_freq > lowest_audio_freq_hz) + lowest_center_freq /= pow(2, 0.5); + if(lowest_center_freq < lowest_audio_freq_hz) + lowest_center_freq *= pow(2, 0.5); + + //Calculate freq's + eq_double_t f0 = lowest_center_freq; + for(unsigned int i = 0; i < 20; i++) { + freqs_.push_back(band_freqs(f0 / pow(2, 0.25), + f0, f0*pow(2, 0.25))); + f0 *= pow(2, 0.5); + } + } else + return invalid_input_data_error; + return no_error; + } + + eq_error_t set_30_bands(eq_double_t center_freq = bands_grid_center_freq_hz) { + freqs_.clear(); + if(lowest_audio_freq_hz < center_freq && + center_freq < highest_audio_freq_hz) { + + //Find lowest center frequency in band + eq_double_t lowest_center_freq = center_freq; + while(lowest_center_freq > lowest_audio_freq_hz) + lowest_center_freq /= pow(2.0, 1.0 / 3.0); + if(lowest_center_freq < lowest_audio_freq_hz) + lowest_center_freq *= pow(2.0, 1.0 / 3.0); + + //Calculate freq's + eq_double_t f0 = lowest_center_freq; + for(unsigned int i = 0; i < 30; i++) { + freqs_.push_back(band_freqs(f0 / pow(2.0, 1.0 / 6.0), + f0, f0*pow(2.0, 1.0 / 6.0))); + f0 *= pow(2, 1.0 / 3.0); + } + } else + return invalid_input_data_error; + return no_error; + } + + unsigned int get_number_of_bands() { return (unsigned int)freqs_.size(); } + + std::vector get_freqs() { return freqs_; } + + unsigned int get_freq(unsigned int number) { + if(number < freqs_.size()) + return (unsigned int)freqs_[number].center_freq; + else + return 0; + } + + unsigned int get_rounded_freq(unsigned int number) { + if(number < freqs_.size()) { + unsigned int freq = (unsigned int)freqs_[number].center_freq; + if(freq < 100) + return freq; + else if(freq >= 100 && freq < 1000) { + unsigned int rest = freq % 10; + if(rest < 5) + return freq - rest; + else + return freq - rest + 10; + } else if(freq >= 1000 && freq < 10000) { + unsigned int rest = freq % 100; + if(rest < 50) + return freq - rest; + else + return freq - rest + 100; + } else if(freq >= 10000) { + unsigned int rest = freq % 1000; + if(rest < 500) + return freq - rest; + else + return freq - rest + 1000; + } + } + return 0; + } + }; + + //------------ Forth order sections ------------ + class fo_section + { + protected: + eq_single_t b0; eq_single_t b1; eq_single_t b2; eq_single_t b3; eq_single_t b4; + eq_single_t a0; eq_single_t a1; eq_single_t a2; eq_single_t a3; eq_single_t a4; + + eq_single_t numBuf[fo_section_order]; + eq_single_t denumBuf[fo_section_order]; + + inline eq_single_t df1_fo_process(eq_single_t in) { + eq_single_t out = 0; + out += b0*in; + out += (b1*numBuf[0] - denumBuf[0] * a1); + out += (b2*numBuf[1] - denumBuf[1] * a2); + out += (b3*numBuf[2] - denumBuf[2] * a3); + out += (b4*numBuf[3] - denumBuf[3] * a4); + + numBuf[3] = numBuf[2]; + numBuf[2] = numBuf[1]; + numBuf[1] = numBuf[0]; + if(in < 0.000000000001 && in > -0.000000000001) { + //Prevent denormalized values (causes extreme performance loss) + in = 0; + } + *numBuf = in; + + denumBuf[3] = denumBuf[2]; + denumBuf[2] = denumBuf[1]; + denumBuf[1] = denumBuf[0]; + if(out < 0.000000000001 && out > -0.000000000001) { + //Prevent denormalized values (causes extreme performance loss) + out = 0; + } + *denumBuf = out; + + return(out); + } + + public: + fo_section() { + b0 = 1; b1 = 0; b2 = 0; b3 = 0; b4 = 0; + a0 = 1; a1 = 0; a2 = 0; a3 = 0; a4 = 0; + + for(unsigned int i = 0; i < fo_section_order; i++) { + numBuf[i] = 0; + denumBuf[i] = 0; + } + } + + virtual ~fo_section() {} + + eq_single_t process(eq_single_t in) { + return df1_fo_process(in); + } + + virtual fo_section get() { + return *this; + } + }; + + class butterworth_fo_section : public fo_section + { + butterworth_fo_section() {} + butterworth_fo_section(butterworth_fo_section&) {} + public: + butterworth_fo_section(eq_double_t beta, + eq_double_t s, eq_double_t g, eq_double_t g0, + eq_double_t D, eq_double_t c0) { + b0 = (g*g*beta*beta + 2 * g*g0*s*beta + g0*g0) / D; + b1 = -4 * c0*(g0*g0 + g*g0*s*beta) / D; + b2 = 2 * (g0*g0*(1 + 2 * c0*c0) - g*g*beta*beta) / D; + b3 = -4 * c0*(g0*g0 - g*g0*s*beta) / D; + b4 = (g*g*beta*beta - 2 * g*g0*s*beta + g0*g0) / D; + + a0 = 1; + a1 = -4 * c0*(1 + s*beta) / D; + a2 = 2 * (1 + 2 * c0*c0 - beta*beta) / D; + a3 = -4 * c0*(1 - s*beta) / D; + a4 = (beta*beta - 2 * s*beta + 1) / D; + } + + fo_section get() { return *this; } + }; + + class chebyshev_type1_fo_section : public fo_section + { + chebyshev_type1_fo_section() {} + chebyshev_type1_fo_section(chebyshev_type1_fo_section&) {} + public: + chebyshev_type1_fo_section(eq_double_t a, + eq_double_t c, eq_double_t tetta_b, + eq_double_t g0, eq_double_t s, eq_double_t b, + eq_double_t D, eq_double_t c0) { + b0 = ((b*b + g0*g0*c*c)*tetta_b*tetta_b + 2 * g0*b*s*tetta_b + g0*g0) / D; + b1 = -4 * c0*(g0*g0 + g0*b*s*tetta_b) / D; + b2 = 2 * (g0*g0*(1 + 2 * c0*c0) - (b*b + g0*g0*c*c)*tetta_b*tetta_b) / D; + b3 = -4 * c0*(g0*g0 - g0*b*s*tetta_b) / D; + b4 = ((b*b + g0*g0*c*c)*tetta_b*tetta_b - 2 * g0*b*s*tetta_b + g0*g0) / D; + + a0 = 1; + a1 = -4 * c0*(1 + a*s*tetta_b) / D; + a2 = 2 * (1 + 2 * c0*c0 - (a*a + c*c)*tetta_b*tetta_b) / D; + a3 = -4 * c0*(1 - a*s*tetta_b) / D; + a4 = ((a*a + c*c)*tetta_b*tetta_b - 2 * a*s*tetta_b + 1) / D; + } + + fo_section get() { return *this; } + }; + + class chebyshev_type2_fo_section : public fo_section + { + chebyshev_type2_fo_section() {} + chebyshev_type2_fo_section(chebyshev_type2_fo_section&) {} + public: + chebyshev_type2_fo_section(eq_double_t a, + eq_double_t c, eq_double_t tetta_b, + eq_double_t g, eq_double_t s, eq_double_t b, + eq_double_t D, eq_double_t c0) { + b0 = (g*g*tetta_b*tetta_b + 2 * g*b*s*tetta_b + b*b + g*g*c*c) / D; + b1 = -4 * c0*(b*b + g*g*c*c + g*b*s*tetta_b) / D; + b2 = 2 * ((b*b + g*g*c*c)*(1 + 2 * c0*c0) - g*g*tetta_b*tetta_b) / D; + b3 = -4 * c0*(b*b + g*g*c*c - g*b*s*tetta_b) / D; + b4 = (g*g*tetta_b*tetta_b - 2 * g*b*s*tetta_b + b*b + g*g*c*c) / D; + + a0 = 1; + a1 = -4 * c0*(a*a + c*c + a*s*tetta_b) / D; + a2 = 2 * ((a*a + c*c)*(1 + 2 * c0*c0) - tetta_b*tetta_b) / D; + a3 = -4 * c0*(a*a + c*c - a*s*tetta_b) / D; + a4 = (tetta_b*tetta_b - 2 * a*s*tetta_b + a*a + c*c) / D; + } + + fo_section get() { return *this; } + }; + + //------------ Bandpass filters ------------ + class bp_filter + { + public: + bp_filter() {} + virtual ~bp_filter() {} + + virtual eq_single_t process(eq_single_t in) = 0; + }; + + class butterworth_bp_filter : public bp_filter + { + private: + std::vector sections_; + + butterworth_bp_filter() {} + public: + butterworth_bp_filter(butterworth_bp_filter& f) { + this->sections_ = f.sections_; + } + + butterworth_bp_filter(unsigned int N, + eq_double_t w0, eq_double_t wb, + eq_double_t G, eq_double_t Gb, eq_double_t G0) { + //Case if G == 0 : allpass + if(G == 0 && G0 == 0) { + sections_.push_back(fo_section()); + return; + } + + //Get number of analog sections + unsigned int r = N % 2; + unsigned int L = (N - r) / 2; + + //Convert gains to linear scale + G = conversions::db_2_lin(G); + Gb = conversions::db_2_lin(Gb); + G0 = conversions::db_2_lin(G0); + + eq_double_t epsilon = pow(((eq_double_t)(G*G - Gb*Gb)) / + (Gb*Gb - G0*G0), 0.5); + eq_double_t g = pow(((eq_double_t)G), 1.0 / ((eq_double_t)N)); + eq_double_t g0 = pow(((eq_double_t)G0), 1.0 / ((eq_double_t)N)); + eq_double_t beta = pow(((eq_double_t)epsilon), -1.0 / ((eq_double_t)N))* + tan(wb / 2.0); + + eq_double_t c0 = cos(w0); + if(w0 == 0) c0 = 1; + if(w0 == pi / 2) c0 = 0; + if(w0 == pi) c0 = -1; + + //Calculate every section + for(unsigned int i = 1; i <= L; i++) { + eq_double_t ui = (2.0*i - 1) / N; + eq_double_t si = sin(pi*ui / 2.0); + + eq_double_t Di = beta*beta + 2 * si*beta + 1; + + sections_.push_back + (butterworth_fo_section(beta, si, g, g0, Di, c0)); + } + } + + ~butterworth_bp_filter() {} + + static eq_single_t compute_bw_gain_db(eq_single_t gain) { + eq_single_t bw_gain = 0; + if(gain <= -6) + bw_gain = gain + common_base_gain_db; + else if(gain > -6 && gain < 6) + bw_gain = gain*0.5; + else if(gain >= 6) + bw_gain = gain - common_base_gain_db; + + return bw_gain; + } + + virtual eq_single_t process(eq_single_t in) { + eq_single_t p0 = in; + eq_single_t p1 = 0; + //Process FO sections in serial connection + for(size_t i = 0, len = sections_.size(); i < len; i++) { + p1 = sections_[i].process(p0); + p0 = p1; + } + + return p1; + } + }; + + class chebyshev_type1_bp_filter : public bp_filter + { + private: + std::vector sections_; + + chebyshev_type1_bp_filter() {} + public: + chebyshev_type1_bp_filter(unsigned int N, + eq_double_t w0, eq_double_t wb, + eq_double_t G, eq_double_t Gb, eq_double_t G0) { + //Case if G == 0 : allpass + if(G == 0 && G0 == 0) { + sections_.push_back(fo_section()); + return; + } + + //Get number of analog sections + unsigned int r = N % 2; + unsigned int L = (N - r) / 2; + + //Convert gains to linear scale + G = conversions::db_2_lin(G); + Gb = conversions::db_2_lin(Gb); + G0 = conversions::db_2_lin(G0); + + eq_double_t epsilon = pow((eq_double_t)(G*G - Gb*Gb) / + (Gb*Gb - G0*G0), 0.5); + eq_double_t g0 = pow((eq_double_t)(G0), 1.0 / N); + eq_double_t alfa = + pow(1.0 / epsilon + pow(1 + pow(epsilon, -2.0), 0.5), 1.0 / N); + eq_double_t beta = + pow(G / epsilon + Gb*pow(1 + pow(epsilon, -2.0), 0.5), 1.0 / N); + eq_double_t a = 0.5*(alfa - 1.0 / alfa); + eq_double_t b = 0.5*(beta - g0*g0*(1 / beta)); + eq_double_t tetta_b = tan(wb / 2); + + eq_double_t c0 = cos(w0); + if(w0 == 0) c0 = 1; + if(w0 == pi / 2) c0 = 0; + if(w0 == pi) c0 = -1; + + //Calculate every section + for(unsigned int i = 1; i <= L; i++) { + eq_double_t ui = (2.0*i - 1.0) / N; + eq_double_t ci = cos(pi*ui / 2.0); + eq_double_t si = sin(pi*ui / 2.0); + + eq_double_t Di = (a*a + ci*ci)*tetta_b*tetta_b + + 2.0*a*si*tetta_b + 1; + sections_.push_back( + chebyshev_type1_fo_section(a, ci, tetta_b, g0, si, b, Di, c0)); + } + } + + + ~chebyshev_type1_bp_filter() {} + + static eq_single_t compute_bw_gain_db(eq_single_t gain) { + eq_single_t bw_gain = 0; + if(gain <= -6) + bw_gain = gain + 1; + else if(gain > -6 && gain < 6) + bw_gain = gain*0.9; + else if(gain >= 6) + bw_gain = gain - 1; + + return bw_gain; + } + + eq_single_t process(eq_single_t in) { + eq_single_t p0 = in; + eq_single_t p1 = 0; + //Process FO sections in serial connection + for(size_t i = 0, len = sections_.size(); i < len; i++) { + p1 = sections_[i].process(p0); + p0 = p1; + } + + return p1; + } + }; + + class chebyshev_type2_bp_filter : public bp_filter + { + private: + std::vector sections_; + + chebyshev_type2_bp_filter() {} + public: + chebyshev_type2_bp_filter(unsigned int N, + eq_double_t w0, eq_double_t wb, + eq_double_t G, eq_double_t Gb, eq_double_t G0) { + //Case if G == 0 : allpass + if(G == 0 && G0 == 0) { + sections_.push_back(fo_section()); + return; + } + + //Get number of analog sections + unsigned int r = N % 2; + unsigned int L = (N - r) / 2; + + //Convert gains to linear scale + G = conversions::db_2_lin(G); + Gb = conversions::db_2_lin(Gb); + G0 = conversions::db_2_lin(G0); + + eq_double_t epsilon = pow((eq_double_t)((G*G - Gb*Gb) / + (Gb*Gb - G0*G0)), 0.5); + eq_double_t g = pow((eq_double_t)(G), 1.0 / N); + eq_double_t eu = pow(epsilon + sqrt(1 + epsilon*epsilon), 1.0 / N); + eq_double_t ew = pow(G0*epsilon + Gb*sqrt(1 + epsilon*epsilon), 1.0 / N); + eq_double_t a = (eu - 1.0 / eu) / 2.0; + eq_double_t b = (ew - g*g / ew) / 2.0; + eq_double_t tetta_b = tan(wb / 2); + + eq_double_t c0 = cos(w0); + if(w0 == 0) c0 = 1; + if(w0 == pi / 2) c0 = 0; + if(w0 == pi) c0 = -1; + + //Calculate every section + for(unsigned int i = 1; i <= L; i++) { + eq_double_t ui = (2.0*i - 1.0) / N; + eq_double_t ci = cos(pi*ui / 2.0); + eq_double_t si = sin(pi*ui / 2.0); + eq_double_t Di = tetta_b*tetta_b + 2 * a*si*tetta_b + a*a + ci*ci; + + sections_.push_back( + chebyshev_type2_fo_section(a, ci, tetta_b, g, si, b, Di, c0)); + } + } + + ~chebyshev_type2_bp_filter() {} + + static eq_single_t compute_bw_gain_db(eq_single_t gain) { + eq_single_t bw_gain = 0; + if(gain <= -6) + bw_gain = -common_base_gain_db; + else if(gain > -6 && gain < 6) + bw_gain = gain*0.3; + else if(gain >= 6) + bw_gain = common_base_gain_db; + + return bw_gain; + } + + eq_single_t process(eq_single_t in) { + eq_single_t p0 = in; + eq_single_t p1 = 0; + + //Process FO sections in serial connection + for(size_t i = 0, len = sections_.size(); i < len; i++) { + p1 = sections_[i].process(p0); + p0 = p1; + } + + return p1; + } + }; + + // ------------ eq1 ------------ + // Equalizer with single precomputed filter for every band + class eq1 + { + private: + conversions conv_; + eq_double_t sampling_frequency_; + freq_grid freq_grid_; + std::vector band_gains_; + std::vector filters_; + filter_type current_eq_type_; + + eq1() :conv_(eq_min_max_gain_db) {} + eq1(const eq1&) :conv_(eq_min_max_gain_db) {} + + void cleanup_filters_array() { + for(unsigned int j = 0; j < filters_.size(); j++) + delete filters_[j]; + } + + public: + eq1(const freq_grid *fg, filter_type eq_t) : conv_(eq_min_max_gain_db) { + sampling_frequency_ = default_sample_freq_hz; + freq_grid_ = *fg; + current_eq_type_ = eq_t; + set_eq(freq_grid_, eq_t); + } + ~eq1() { cleanup_filters_array(); } + + eq_error_t set_eq(freq_grid& fg, filter_type eqt) { + band_gains_.clear(); + cleanup_filters_array(); + filters_.clear(); + freq_grid_ = fg; + + for(unsigned int i = 0; i < freq_grid_.get_number_of_bands(); i++) { + + eq_double_t wb = conversions::hz_2_rad( + freq_grid_.get_freqs()[i].max_freq - + freq_grid_.get_freqs()[i].min_freq, + sampling_frequency_); + + eq_double_t w0 = conversions::hz_2_rad( + freq_grid_.get_freqs()[i].center_freq, + sampling_frequency_); + + switch(eqt) { + case (butterworth): { + butterworth_bp_filter* bf = + new butterworth_bp_filter( + default_eq_band_filters_order, + w0, + wb, + max_base_gain_db, + butterworth_band_gain_db, + min_base_gain_db + ); + + filters_.push_back(bf); + break; + } + + case (chebyshev1): { + chebyshev_type1_bp_filter* cf1 = + new chebyshev_type1_bp_filter( + default_eq_band_filters_order, + w0, + wb, + max_base_gain_db, + chebyshev1_band_base_gain_db, + min_base_gain_db + ); + + filters_.push_back(cf1); + break; + } + + case (chebyshev2): { + chebyshev_type2_bp_filter* cf2 = + new chebyshev_type2_bp_filter( + default_eq_band_filters_order, + w0, + wb, + max_base_gain_db, + chebyshev2_band_base_gain_db, + min_base_gain_db + ); + + filters_.push_back(cf2); + break; + } + + default: + current_eq_type_ = none; + return invalid_input_data_error; + + } + band_gains_.push_back(max_base_gain_db); + } + + current_eq_type_ = eqt; + return no_error; + } + + eq_error_t set_eq(filter_type eqt) + { + return set_eq(freq_grid_, eqt); + } + + eq_error_t set_sample_rate(eq_double_t sr) { + eq_error_t err = no_error; + sampling_frequency_ = sr; + err = set_eq(freq_grid_, current_eq_type_); + + return err; + } + + eq_error_t change_gains(std::vector band_gains) { + if(band_gains_.size() == band_gains.size()) + band_gains_ = band_gains; + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t change_gains_db(std::vector band_gains) { + if(band_gains_.size() == band_gains.size()) + for(unsigned int j = 0; j < get_number_of_bands(); j++) + band_gains_[j] = conv_.fast_db_2_lin(band_gains[j]); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t change_band_gain(unsigned int band_number, + eq_single_t band_gain) { + if(band_number < get_number_of_bands()) + band_gains_[band_number] = band_gain; + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t change_band_gain_db(unsigned int band_number, eq_single_t band_gain) { + if(band_number < get_number_of_bands()) + band_gains_[band_number] = conv_.fast_db_2_lin(band_gain); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t sbs_process_band(unsigned int band_number, eq_single_t *in, eq_single_t *out) { + //if(band_number < get_number_of_bands()) + *out = band_gains_[band_number] * + filters_[band_number]->process(*in); + //else + //return invalid_input_data_error; + + return no_error; + } + + eq_error_t sbs_process(eq_single_t *in, eq_single_t *out) { + eq_error_t err = no_error; + eq_single_t acc_out = 0; + for(unsigned int j = 0, len = get_number_of_bands(); j < len; j++) { + eq_single_t band_out = 0; + err = sbs_process_band(j, in, &band_out); + acc_out += band_out; + } + *out = acc_out; + + return err; + } + + filter_type get_eq_type() { return current_eq_type_; } + const char* get_string_eq_type() { return get_eq_text(current_eq_type_); } + unsigned int get_number_of_bands() { + return freq_grid_.get_number_of_bands(); + } + const char* get_version() { return eq_version; } + }; + + //!!! New functionality + + // ------------ eq_channel ------------ + // Precomputed equalizer channel, + // consists of vector of filters for every gain value + class eq_channel + { + eq_single_t f0_; + eq_single_t fb_; + eq_single_t sampling_frequency_; + eq_single_t min_max_gain_db_; + eq_single_t gain_step_db_; + + unsigned int current_filter_index_; + eq_single_t current_gain_db_; + + std::vector filters_; + filter_type current_channel_type_; + + eq_channel() {} + + unsigned int get_flt_index(eq_single_t gain_db) { + unsigned int number_of_filters = (unsigned int)filters_.size(); + eq_single_t scale_coef = gain_db / min_max_gain_db_; + return (unsigned int)((number_of_filters / 2) + (number_of_filters / 2)*scale_coef); + } + + void cleanup_filters_array() { + for(unsigned int j = 0; j < filters_.size(); j++) + delete filters_[j]; + } + + public: + eq_channel(filter_type ft, + eq_single_t fs, eq_single_t f0, eq_single_t fb, + eq_single_t min_max_gain_db = p_eq_min_max_gain_db, + eq_single_t step_db = p_eq_gain_step_db) { + + //Init data fields + sampling_frequency_ = fs; + f0_ = f0; + fb_ = fb; + min_max_gain_db_ = min_max_gain_db; + gain_step_db_ = step_db; + + current_gain_db_ = 0; + current_filter_index_ = 0; + + current_channel_type_ = ft; + + set_channel(current_channel_type_, sampling_frequency_); + } + + ~eq_channel() { cleanup_filters_array(); } + + eq_error_t set_channel(filter_type ft, eq_single_t fs) { + + eq_double_t wb = conversions::hz_2_rad(fb_, sampling_frequency_); + eq_double_t w0 = conversions::hz_2_rad(f0_, sampling_frequency_); + + for(eq_single_t gain = -min_max_gain_db_; gain <= min_max_gain_db_; + gain += gain_step_db_) { + + switch(ft) { + case (butterworth): { + eq_single_t bw_gain = + butterworth_bp_filter::compute_bw_gain_db(gain); + + butterworth_bp_filter* bf = + new butterworth_bp_filter( + default_eq_band_filters_order, + w0, + wb, + gain, + bw_gain, + p_eq_default_gain_db + ); + + filters_.push_back(bf); + break; + } + case (chebyshev1): { + eq_single_t bw_gain = + chebyshev_type1_bp_filter::compute_bw_gain_db(gain); + + chebyshev_type1_bp_filter* cf1 = + new chebyshev_type1_bp_filter( + default_eq_band_filters_order, + w0, + wb, + gain, + bw_gain, + p_eq_default_gain_db + ); + + filters_.push_back(cf1); + break; + } + case (chebyshev2): { + eq_single_t bw_gain = + chebyshev_type2_bp_filter::compute_bw_gain_db(gain); + + chebyshev_type2_bp_filter* cf2 = + new chebyshev_type2_bp_filter( + default_eq_band_filters_order, + w0, + wb, + gain, + bw_gain, + p_eq_default_gain_db + ); + + filters_.push_back(cf2); + break; + } + default: { + current_channel_type_ = none; + return invalid_input_data_error; + } + } + } + + //Get current filter index + current_gain_db_ = 0; + current_filter_index_ = get_flt_index(current_gain_db_); + + return no_error; + } + + eq_error_t set_gain_db(eq_single_t db) { + if(db > -min_max_gain_db_ && db < min_max_gain_db_) { + current_gain_db_ = db; + current_filter_index_ = get_flt_index(db); + } else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t sbs_process(eq_single_t *in, eq_single_t *out) { + *out = filters_[current_filter_index_]->process(*in); + return no_error; + } + }; + + // ------------ eq2 ------------ + // Precomputed equalizer + + class eq2 + { + conversions conv_; + eq_double_t sampling_frequency_; + freq_grid freq_grid_; + std::vector channels_; + filter_type current_eq_type_; + + void cleanup_channels_array() { + for(unsigned int j = 0; j < channels_.size(); j++) + delete channels_[j]; + } + + public: + eq2(freq_grid &fg, filter_type eq_t) : conv_(eq_min_max_gain_db) { + sampling_frequency_ = default_sample_freq_hz; + freq_grid_ = fg; + current_eq_type_ = eq_t; + set_eq(freq_grid_, eq_t); + } + ~eq2() { cleanup_channels_array(); } + + eq_error_t set_eq(const freq_grid& fg, filter_type ft) { + cleanup_channels_array(); + channels_.clear(); + freq_grid_ = fg; + + for(unsigned int i = 0; i < freq_grid_.get_number_of_bands(); i++) { + band_freqs b_fres = freq_grid_.get_freqs()[i]; + + eq_channel* eq_ch = new eq_channel(ft, sampling_frequency_, + b_fres.center_freq, b_fres.max_freq - b_fres.min_freq); + + channels_.push_back(eq_ch); + channels_[i]->set_gain_db(p_eq_default_gain_db); + } + + current_eq_type_ = ft; + return no_error; + } + + eq_error_t set_eq(filter_type ft) { + eq_error_t err = set_eq(freq_grid_, ft); + return err; + } + + eq_error_t set_sample_rate(eq_double_t sr) { + sampling_frequency_ = sr; + eq_error_t err = set_eq(current_eq_type_); + return err; + } + + eq_error_t change_gains(std::vector band_gains) { + if(channels_.size() == band_gains.size()) + for(unsigned int j = 0; j < channels_.size(); j++) + channels_[j]->set_gain_db(conv_.fast_lin_2_db(band_gains[j])); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t change_gains_db(std::vector band_gains) { + if(channels_.size() == band_gains.size()) + for(unsigned int j = 0; j < channels_.size(); j++) + channels_[j]->set_gain_db(band_gains[j]); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t change_band_gain(unsigned int band_number, + eq_single_t band_gain) { + if(band_number < channels_.size()) + channels_[band_number]->set_gain_db(conv_.fast_lin_2_db(band_gain)); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t change_band_gain_db(unsigned int band_number, + eq_single_t band_gain) { + if(band_number < channels_.size()) + channels_[band_number]->set_gain_db(band_gain); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t sbs_process_band(unsigned int band_number, + eq_single_t *in, eq_single_t *out) { + if(band_number < get_number_of_bands()) + channels_[band_number]->sbs_process(in, out); + else + return invalid_input_data_error; + + return no_error; + } + + eq_error_t sbs_process(eq_single_t *in, eq_single_t *out) { + eq_error_t err = no_error; + eq_single_t in_out = *in; + for(unsigned int i = 0; i < get_number_of_bands(); i++) + err = sbs_process_band(i, &in_out, &in_out); + + *out = in_out; + + return err; + } + + filter_type get_eq_type() { return current_eq_type_; } + const char* get_string_eq_type() { return get_eq_text(current_eq_type_); } + unsigned int get_number_of_bands() { + return freq_grid_.get_number_of_bands(); + } + const char* get_version() { return eq_version; } + }; + +} //namespace orfanidis_eq +#endif //ORFANIDIS_EQ_H_