diff --git a/KeyboardAudioVisualizer.sln.DotSettings b/KeyboardAudioVisualizer.sln.DotSettings new file mode 100644 index 0000000..3157d76 --- /dev/null +++ b/KeyboardAudioVisualizer.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/KeyboardAudioVisualizer/AudioProcessing/AudioProcessor.cs b/KeyboardAudioVisualizer/AudioProcessing/AudioProcessor.cs index 71661aa..d1e51f1 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/AudioProcessor.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/AudioProcessor.cs @@ -59,7 +59,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing _spectrumProvider.Initialize(); //TODO DarthAffe 03.08.2017: Initialize correctly; Settings - MultiBandEqualizer equalizer = new MultiBandEqualizer { [0] = -3, [1] = -1, [2] = 1, [3] = 2, [4] = 3 }; + MultiBandEqualizer equalizer = new MultiBandEqualizer(); PrimaryVisualizationProvider = new FrequencyBarsVisualizationProvider(new FrequencyBarsVisualizationProviderConfiguration(), _spectrumProvider) { Equalizer = equalizer }; //PrimaryVisualizationProvider = new BeatVisualizationProvider(new BeatVisualizationProviderConfiguration(), _spectrumProvider); PrimaryVisualizationProvider.Initialize(); diff --git a/KeyboardAudioVisualizer/AudioProcessing/Equalizer/EqualizerBand.cs b/KeyboardAudioVisualizer/AudioProcessing/Equalizer/EqualizerBand.cs new file mode 100644 index 0000000..6d27b76 --- /dev/null +++ b/KeyboardAudioVisualizer/AudioProcessing/Equalizer/EqualizerBand.cs @@ -0,0 +1,42 @@ +using RGB.NET.Core; + +namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer +{ + public class EqualizerBand : AbstractBindable + { + #region Properties & Fields + + private float _offset; + public float Offset + { + get => _offset; + set + { + if (!IsFixedOffset) + SetProperty(ref _offset, value); + } + } + + private float _value; + public float Value + { + get => _value; + set => SetProperty(ref _value, value); + } + + public bool IsFixedOffset { get; } + + #endregion + + #region Constructors + + public EqualizerBand(float offset, float value = 0, bool fixedOffset = false) + { + this.Offset = offset; + this.Value = value; + this.IsFixedOffset = fixedOffset; + } + + #endregion + } +} diff --git a/KeyboardAudioVisualizer/AudioProcessing/Equalizer/IEqualizer.cs b/KeyboardAudioVisualizer/AudioProcessing/Equalizer/IEqualizer.cs index 03427e8..dca2d9c 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/Equalizer/IEqualizer.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/Equalizer/IEqualizer.cs @@ -1,8 +1,13 @@ -namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer +using System.Collections.ObjectModel; + +namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer { public interface IEqualizer { bool IsEnabled { get; set; } - float[] CalculateValues(int values); + + ObservableCollection Bands { get; } + + float[] CalculateValues(int count); } } diff --git a/KeyboardAudioVisualizer/AudioProcessing/Equalizer/MultiBandEqualizer.cs b/KeyboardAudioVisualizer/AudioProcessing/Equalizer/MultiBandEqualizer.cs index 6c77654..4cbb630 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/Equalizer/MultiBandEqualizer.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/Equalizer/MultiBandEqualizer.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer @@ -8,46 +7,35 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer { #region Properties & Fields + public ObservableCollection Bands { get; } = new ObservableCollection(); + private float[] _values; - private readonly List _bands = new List(); - - public int Bands => _bands.Count; - public float this[int band] - { - get => _bands[band].Value; - set - { - _bands[band].Value = value; - RecalculateValues(); - } - } - public bool IsEnabled { get; set; } = true; #endregion #region Constructors - public MultiBandEqualizer(int bands = 5) + public MultiBandEqualizer() { - if (bands < 2) throw new ArgumentOutOfRangeException(nameof(bands), "There must be at least two bands for an working equalizer!"); - - float reference = (float)Math.Log(bands); - - for (int i = bands - 1; i >= 0; i--) - { - Band band = new Band((reference - (float)Math.Log(i + 1)) / reference); - _bands.Add(band); - } - - CalculateValues(1); + AddBand(0, 0, true); + AddBand(1, 0, true); } #endregion #region Methods + public void AddBand(float frequency, float modification, bool isFixedFrequency = false) + { + EqualizerBand band = new EqualizerBand(frequency, modification, isFixedFrequency); + band.PropertyChanged += (sender, args) => InvalidateCache(); + Bands.Add(band); + + InvalidateCache(); + } + public float[] CalculateValues(int values) { if ((_values == null) || (_values.Length != values)) @@ -55,7 +43,6 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer _values = new float[values]; RecalculateValues(); } - return _values; } @@ -65,40 +52,15 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Equalizer for (int i = 0; i < _values.Length; i++) { float offset = (i / width); - - Band bandBefore = _bands.Last(n => n.Offset <= offset); - Band bandAfter = _bands.First(n => n.Offset >= offset); - + EqualizerBand bandBefore = Bands.Last(n => n.Offset <= offset); + EqualizerBand bandAfter = Bands.First(n => n.Offset >= offset); offset = bandAfter.Offset <= 0 ? 0 : (offset - bandBefore.Offset) / (bandAfter.Offset - bandBefore.Offset); - float value = (float)((3.0 * (offset * offset)) - (2.0 * (offset * offset * offset))); _values[i] = bandBefore.Value + (value * (bandAfter.Value - bandBefore.Value)); } } - #endregion - - #region Data - - private class Band - { - #region Properties & Fields - - public float Offset { get; set; } - public float Value { get; set; } - - #endregion - - #region Constructors - - public Band(float offset, float value = 0) - { - this.Offset = offset; - this.Value = value; - } - - #endregion - } + private void InvalidateCache() => _values = null; #endregion } diff --git a/KeyboardAudioVisualizer/AudioProcessing/Spectrum/Band.cs b/KeyboardAudioVisualizer/AudioProcessing/Spectrum/Band.cs index 38505ac..cefcb0e 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/Spectrum/Band.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/Spectrum/Band.cs @@ -11,6 +11,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Spectrum public float LowerFrequency { get; } public float UpperFrequency { get; } + public float CenterFrequency { get; } private float? _average = null; public float Average => _average ?? (_average = _data.Average()).Value; @@ -35,6 +36,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Spectrum { this.LowerFrequency = lowerFrequency; this.UpperFrequency = upperFrequency; + this.CenterFrequency = (LowerFrequency + UpperFrequency) / 2f; //TODO DarthAffe 12.08.2017: Is this valid for logarithmic scaling? this._data = data; _resolution = (UpperFrequency - LowerFrequency) / data.Length; diff --git a/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs b/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs index 267eaa9..6007b9b 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs @@ -127,22 +127,16 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider ISpectrum spectrum = GetSpectrum(); if (spectrum == null) return; + float[] equalizerValues = Equalizer?.IsEnabled == true ? Equalizer.CalculateValues(spectrum.BandCount) : null; + for (int i = 0; i < spectrum.BandCount; i++) { double binPower = Math.Max(0, 20 * Math.Log10(GetBandValue(spectrum[i]))); - //TODO DarthAffe 10.08.2017: Rewrite Equalizer - //if (Equalizer?.IsEnabled == true) - //{ - // float value = Equalizer.CalculateValues(VisualizationData.Length)[i]; - // if (Math.Abs(value) > 0.000001) - // { - // bool lower = value < 0; - // value = 1 + (value * value); - // binPower *= lower ? 1f / value : value; - // } - //} + if (equalizerValues != null) + binPower += equalizerValues[i]; + binPower = Math.Max(0, binPower); binPower /= _configuration.ReferenceLevel; if (_configuration.EmphasisePeaks > 0.001) binPower = Math.Pow(binPower, 1 + _configuration.EmphasisePeaks) * _emphasiseFactor; diff --git a/KeyboardAudioVisualizer/Configuration/AbstractConfiguration.cs b/KeyboardAudioVisualizer/Configuration/AbstractConfiguration.cs index fed82f4..e918473 100644 --- a/KeyboardAudioVisualizer/Configuration/AbstractConfiguration.cs +++ b/KeyboardAudioVisualizer/Configuration/AbstractConfiguration.cs @@ -1,20 +1,15 @@ using System; using System.ComponentModel; using System.Runtime.CompilerServices; +using RGB.NET.Core; namespace KeyboardAudioVisualizer.Configuration { - public class AbstractConfiguration : IConfiguration, INotifyPropertyChanged + public class AbstractConfiguration : AbstractBindable, IConfiguration, INotifyPropertyChanged { - #region Events - - public event PropertyChangedEventHandler PropertyChanged; - - #endregion - #region Methods - protected virtual bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null) + protected override bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null) { if ((typeof(T) == typeof(double)) || (typeof(T) == typeof(float))) { @@ -31,8 +26,6 @@ namespace KeyboardAudioVisualizer.Configuration return true; } - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - #endregion } } diff --git a/KeyboardAudioVisualizer/Converter/BoolToVisibilityConverter.cs b/KeyboardAudioVisualizer/Converter/BoolToVisibilityConverter.cs new file mode 100644 index 0000000..50958ca --- /dev/null +++ b/KeyboardAudioVisualizer/Converter/BoolToVisibilityConverter.cs @@ -0,0 +1,19 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace KeyboardAudioVisualizer.Converter +{ + [ValueConversion(typeof(bool), typeof(Visibility))] + public class BoolToVisibilityConverter : IValueConverter + { + #region Methods + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (value as bool?) == true ? Visibility.Visible : Visibility.Collapsed; + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => value as Visibility? == Visibility.Visible; + + #endregion + } +} diff --git a/KeyboardAudioVisualizer/Converter/OffsetToPosXConverter.cs b/KeyboardAudioVisualizer/Converter/OffsetToPosXConverter.cs new file mode 100644 index 0000000..8aa97a8 --- /dev/null +++ b/KeyboardAudioVisualizer/Converter/OffsetToPosXConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace KeyboardAudioVisualizer.Converter +{ + public class ValueToPosYConverter : IMultiValueConverter + { + #region Methods + + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if ((values.Length != 3) || (values[0] == null) || (values[0] == DependencyProperty.UnsetValue) + || (values[1] == null) || (values[1] == DependencyProperty.UnsetValue) + || (values[2] == null) || (values[2] == DependencyProperty.UnsetValue)) + return 0; + + float val = (float)values[0]; + double height = (double)values[1]; + double reference = (double)values[2]; + + double halfHeight = height / 2.0; + + double offset = val / reference; + if (offset < 0) + return halfHeight + (-offset * halfHeight); + + if (offset > 0) + return halfHeight - (offset * halfHeight); + + return halfHeight; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); + + #endregion + } +} diff --git a/KeyboardAudioVisualizer/Converter/ValueToPosYConverter.cs b/KeyboardAudioVisualizer/Converter/ValueToPosYConverter.cs new file mode 100644 index 0000000..19a975c --- /dev/null +++ b/KeyboardAudioVisualizer/Converter/ValueToPosYConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace KeyboardAudioVisualizer.Converter +{ + public class OffsetToPosXConverter : IMultiValueConverter + { + #region Methods + + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if ((values.Length != 2) || (values[0] == null) || (values[0] == DependencyProperty.UnsetValue) + || (values[1] == null) || (values[1] == DependencyProperty.UnsetValue)) + return 0; + + float offset = (float)values[0]; + double width = (double)values[1]; + + return offset * width; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); + + #endregion + } +} diff --git a/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj b/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj index df90530..b252c77 100644 --- a/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj +++ b/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj @@ -106,6 +106,7 @@ + @@ -129,7 +130,10 @@ + + + @@ -142,6 +146,7 @@ + diff --git a/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml b/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml index dc8baaf..e67945c 100644 --- a/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml +++ b/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml @@ -15,6 +15,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + +