diff --git a/KeyboardAudioVisualizer/ApplicationManager.cs b/KeyboardAudioVisualizer/ApplicationManager.cs index 7db2abb..73b8390 100644 --- a/KeyboardAudioVisualizer/ApplicationManager.cs +++ b/KeyboardAudioVisualizer/ApplicationManager.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Windows; using KeyboardAudioVisualizer.AudioProcessing; using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider; @@ -69,6 +67,8 @@ namespace KeyboardAudioVisualizer surface.LoadDevices(LogitechDeviceProvider.Instance); surface.LoadDevices(CoolerMasterDeviceProvider.Instance); + surface.AlignDevies(); + ILedGroup background = new ListLedGroup(surface.Leds); background.Brush = new SolidColorBrush(new Color(64, 0, 0, 0)); //TODO DarthAffe 06.08.2017: A-Channel gives some kind of blur - settings! @@ -90,7 +90,7 @@ namespace KeyboardAudioVisualizer IGradient keyboardLevelGradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)), new GradientStop(1, new Color(255, 0, 0))); ILedGroup lightbarLeft = new ListLedGroup(lightbar.Left); - lightbarLeft.Brush = new LinearGradientBrush(keyboardLevelGradient); + lightbarLeft.Brush = new LinearGradientBrush(new Point(1.0, 0.5), new Point(0.0, 0.5), keyboardLevelGradient); tertiaryGroups.Add((lightbarLeft, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Left, 0))); ILedGroup lightbarRight = new ListLedGroup(lightbar.Right); diff --git a/KeyboardAudioVisualizer/AudioCapture/AudioBuffer.cs b/KeyboardAudioVisualizer/AudioCapture/AudioBuffer.cs index 07d0afd..66859e6 100644 --- a/KeyboardAudioVisualizer/AudioCapture/AudioBuffer.cs +++ b/KeyboardAudioVisualizer/AudioCapture/AudioBuffer.cs @@ -52,24 +52,27 @@ namespace KeyboardAudioVisualizer.AudioCapture } } - public void CopyLeftInto(ref float[] data, int offset) + public void CopyLeftInto(ref float[] data, int offset) => CopyLeftInto(ref data, offset, _capacity); + public void CopyLeftInto(ref float[] data, int offset, int count) { lock (_bufferLeft) - for (int i = 0; i < _capacity; i++) + for (int i = _capacity - count; i < count; i++) data[offset + i] = _bufferLeft[(_currentIndex + i) % _capacity]; } - public void CopyRightInto(ref float[] data, int offset) + public void CopyRightInto(ref float[] data, int offset) => CopyRightInto(ref data, offset, _capacity); + public void CopyRightInto(ref float[] data, int offset, int count) { - lock (_bufferLeft) - for (int i = 0; i < _capacity; i++) + lock (_bufferRight) + for (int i = _capacity - count; i < count; i++) data[offset + i] = _bufferRight[(_currentIndex + i) % _capacity]; } - public void CopyMixInto(ref float[] data, int offset) + public void CopyMixInto(ref float[] data, int offset) => CopyMixInto(ref data, offset, _capacity); + public void CopyMixInto(ref float[] data, int offset, int count) { lock (_bufferLeft) - for (int i = 0; i < _capacity; i++) + for (int i = _capacity - count; i < count; i++) { int index = (_currentIndex + i) % _capacity; data[offset + i] = (_bufferLeft[index] + _bufferRight[index]) / 2f; diff --git a/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs b/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs index e76f02e..9fa7bc1 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/VisualizationPRovider/FrequencyBarsVisualizationProvider.cs @@ -2,7 +2,6 @@ using KeyboardAudioVisualizer.AudioProcessing.Equalizer; using KeyboardAudioVisualizer.AudioProcessing.Spectrum; using KeyboardAudioVisualizer.Configuration; -using RGB.NET.Core; namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider { @@ -93,9 +92,6 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider public IConfiguration Configuration => _configuration; public float[] VisualizationData { get; private set; } - public string DisplayName => "Spectrometer"; - public RGBDeviceType VisualizerFor => RGBDeviceType.Keyboard | RGBDeviceType.LedMatrix; - #endregion #region Constructors diff --git a/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/BeatVisualizationProvider.cs b/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/BeatVisualizationProvider.cs index 25175a7..53f041c 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/BeatVisualizationProvider.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/BeatVisualizationProvider.cs @@ -1,9 +1,6 @@ -using System; -using System.Linq; -using KeyboardAudioVisualizer.AudioProcessing.Spectrum; +using KeyboardAudioVisualizer.AudioProcessing.Spectrum; using KeyboardAudioVisualizer.Configuration; using KeyboardAudioVisualizer.Helper; -using RGB.NET.Core; namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider { @@ -16,7 +13,6 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider #endregion - // Port of https://github.com/kctess5/Processing-Beat-Detection public class BeatVisualizationProvider : AbstractAudioProcessor, IVisualizationProvider { #region Properties & Fields @@ -24,47 +20,11 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider private readonly BeatVisualizationProviderConfiguration _configuration; private readonly ISpectrumProvider _specturProvider; - private int _beatBands = 30; //Number of bands to montiter, higher for more accuracy, lower for speed - private int _longTermAverageSamples = 60; //gets average volume over a period of time - private int _shortTermAverageSamples = 1; //average volume over a shorter "instantanious" time - private int _deltaArraySamples = 300; //number of energy deltas between long & short average to sum together - private int _beatAverageSamples = 100; - private int _beatCounterArraySamples = 400; - private int _maxTime = 200; - private float _predictiveInfluenceConstant = 0.1f; - private float _predictiveInfluence; - private int _cyclePerBeatIntensity; - private float[][] _deltaArray; - private float[][] _shortAverageArray; - private float[][] _longAverageArray; - private float[] _globalAverageArray; - private int[] _beatCounterArray; - private int[] _beatSpread; - private int _beatCounterPosition; - private int _cyclesPerBeat; - private int _longPosition; - private int _shortPosition; - private int _deltaPosition; - private int[] _count; - private float[] _totalLong; - private float[] _totalShort; - private float[] _delta; - private float[] _c; - private int _beat; - private int _beatCounter; - private float[] _beatAverage; - private float _totalBeat; - private int _beatPosition; - private float _totalGlobal; - private float _threshold; - private float _standardDeviation; + private RingBuffer[] _history; public IConfiguration Configuration => _configuration; public float[] VisualizationData { get; } = new float[1]; - public string DisplayName => "Beat"; - public RGBDeviceType VisualizerFor => (RGBDeviceType)0xFF; - #endregion #region Constructors @@ -81,181 +41,30 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider public override void Initialize() { - _deltaArray = new float[_deltaArraySamples][]; - for (int i = 0; i < _deltaArray.Length; i++) - _deltaArray[i] = new float[_beatBands]; - - _shortAverageArray = new float[_shortTermAverageSamples][]; - for (int i = 0; i < _shortAverageArray.Length; i++) - _shortAverageArray[i] = new float[_beatBands]; - - _longAverageArray = new float[_longTermAverageSamples / _shortTermAverageSamples][]; - for (int i = 0; i < _longAverageArray.Length; i++) - _longAverageArray[i] = new float[_beatBands]; - - _globalAverageArray = new float[_longTermAverageSamples]; - _beatCounterArray = new int[_beatCounterArraySamples]; - _beatSpread = new int[_maxTime]; - _count = new int[_beatBands]; - _totalLong = new float[_beatBands]; - _totalShort = new float[_beatBands]; - _delta = new float[_beatBands]; - _c = new float[_beatBands]; //multiplier used to determain threshold - _beatAverage = new float[_beatAverageSamples]; + _history = new RingBuffer[64]; + for (int i = 0; i < _history.Length; i++) + _history[i] = new RingBuffer(32); } public override void Update() { - ISpectrum spectrum = _specturProvider.GetLogarithmicSpectrum(60, minFrequency: 60); + VisualizationData[0] = 0; - if (_shortPosition >= _shortTermAverageSamples) _shortPosition = 0; //Resets incremental variables - if (_longPosition >= (_longTermAverageSamples / _shortTermAverageSamples)) _longPosition = 0; - if (_deltaPosition >= _deltaArraySamples) _deltaPosition = 0; - if (_beatPosition >= _beatAverageSamples) _beatPosition = 0; - - /////////////////////////////////////Calculate short and long term array averages/////////////////////////////////////////////////////////////////////////////////////////////////////////// - for (int i = 0; i < _beatBands; i++) + ISpectrum spectrum = _specturProvider.GetLogarithmicSpectrum(64); + for (int i = 0; i < 32; i++) { - _shortAverageArray[_shortPosition][i] = spectrum[i].Average; //stores the average intensity between the freq. bounds to the short term array - _totalLong[i] = 0; - _totalShort[i] = 0; - for (int j = 0; j < (_longTermAverageSamples / _shortTermAverageSamples); j++) - _totalLong[i] += _longAverageArray[j][i]; //adds up all the values in both of these arrays, for averaging - for (int j = 0; j < _shortTermAverageSamples; j++) - _totalShort[i] += _shortAverageArray[j][i]; - } + float currentEnergy = spectrum[i].Average; + float averageEnergy = _history[i].Average; + _history[i].Put(currentEnergy); - ///////////////////////////////////////////Find wideband frequency average intensity///////////////////////////////////////////////////////////////////////////////////////////////////// - _totalGlobal = 0; - _globalAverageArray[_longPosition] = spectrum[0, 2000].Average(x => x.Average); - for (int j = 0; j < _longTermAverageSamples; j++) - _totalGlobal += _globalAverageArray[j]; - _totalGlobal = _totalGlobal / _longTermAverageSamples; - - //////////////////////////////////Populate long term average array////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if ((_shortPosition % _shortTermAverageSamples) == 0) - { //every time the short array is completely new it is added to long array - for (int i = 0; i < _beatBands; i++) - _longAverageArray[_longPosition][i] = _totalShort[i]; //increases speed of program, but is the same as if each individual value was stored in long array - _longPosition++; - } - - /////////////////////////////////////////Find index of variation for each band/////////////////////////////////////////////////////////////////////////////////////////////////////// - for (int i = 0; i < _beatBands; i++) - { - _totalLong[i] = _totalLong[i] / (float)_longTermAverageSamples / (float)_shortTermAverageSamples; - _delta[i] = 0; - _deltaArray[_deltaPosition][i] = (float)Math.Pow(Math.Abs(_totalLong[i] - _totalShort[i]), 2); - - for (int j = 0; j < _deltaArraySamples; j++) - _delta[i] += _deltaArray[j][i]; - _delta[i] /= _deltaArraySamples; - - ///////////////////////////////////////////Find local beats///////////////////////////////////////////////////////////////////////////////////////////////////// - _c[i] = (float)((1.3 + MathHelper.Clamp(Map(_delta[i], 0, 3000, 0, 0.4), 0, 0.4) //delta is usually bellow 2000 - + Map(MathHelper.Clamp(Math.Pow(_totalLong[i], 0.5), 0, 6), 0, 20, 0.3, 0) //possibly comment this out, adds weight to the lower end - + Map(MathHelper.Clamp(_count[i], 0, 15), 0, 15, 1, 0)) - - Map(MathHelper.Clamp(_count[i], 30, 200), 30, 200, 0, 0.75)); - - if ((_cyclePerBeatIntensity / _standardDeviation) > 3.5) + if (currentEnergy > (35 * averageEnergy)) { - _predictiveInfluence = (float)(_predictiveInfluenceConstant * (1 - (Math.Cos(_beatCounter * (Math.PI * Math.PI)) / _cyclesPerBeat))); - _predictiveInfluence *= (float)Map(MathHelper.Clamp(_cyclePerBeatIntensity / _standardDeviation, 3.5, 20), 3.5, 15, 1, 6); - if (_cyclesPerBeat > 10) - _c[i] += _predictiveInfluence; + VisualizationData[0] = 1; + break; } } - _beat = 0; - for (int i = 0; i < _beatBands; i++) - { - if ((_totalShort[i] > (_totalLong[i] * _c[i])) & (_count[i] > 7)) - { //If beat is detected - if ((_count[i] > 12) & (_count[i] < 200)) - { - _beatCounterArray[_beatCounterPosition % _beatCounterArraySamples] = _count[i]; - _beatCounterPosition++; - } - _count[i] = 0; //resets counter - } - } - - /////////////////////////////////////////Figure out # of beats, and average/////////////////////////////////////////////////////////////////////////////////////////////////////// - for (int i = 0; i < _beatBands; i++) - if (_count[i] < 2) - _beat++; //If there has been a recent beat in a band add to the global beat value - _beatAverage[_beatPosition] = _beat; - - for (int j = 0; j < _beatAverageSamples; j++) - _totalBeat += _beatAverage[j]; - _totalBeat = _totalBeat / _beatAverageSamples; - - /////////////////////////////////////////////////find global beat/////////////////////////////////////////////////////////////////////////////////////////////// - _c[0] = (float)(3.25 + Map(MathHelper.Clamp(_beatCounter, 0, 5), 0, 5, 5, 0)); - if (_cyclesPerBeat > 10) - _c[0] = (float)(_c[0] + (0.75 * (1 - (Math.Cos(_beatCounter * (Math.PI * Math.PI)) / _cyclesPerBeat)))); - - _threshold = (float)MathHelper.Clamp((_c[0] * _totalBeat) + Map(MathHelper.Clamp(_totalGlobal, 0, 2), 0, 2, 4, 0), 5, 1000); - - if ((_beat > _threshold) & (_beatCounter > 5)) - { - VisualizationData[0] = 1; - _beatCounter = 0; - } - else - VisualizationData[0] = 0; - - /////////////////////////////////////////////////////Calculate beat spreads/////////////////////////////////////////////////////////////////////////////////////////// - //average = beatCounterArraySamples/200 !!! - for (int i = 0; i < _maxTime; i++) - _beatSpread[i] = 0; - - for (int i = 0; i < _beatCounterArraySamples; i++) - _beatSpread[_beatCounterArray[i]]++; - - _cyclesPerBeat = Mode(_beatCounterArray); - if (_cyclesPerBeat < 20) - _cyclesPerBeat *= 2; - - _cyclePerBeatIntensity = _beatSpread.Max(); - _standardDeviation = 0; - - for (int i = 0; i < _maxTime; i++) - _standardDeviation += (float)Math.Pow((_beatCounterArraySamples / _maxTime) - _beatSpread[i], 2); - - _standardDeviation = (float)Math.Pow(_standardDeviation / _maxTime, 0.5); - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - _shortPosition++; - _deltaPosition++; - for (int i = 0; i < _beatBands; i++) _count[i]++; - _beatCounter++; - _beatPosition++; } - private int Mode(int[] array) - { - int[] modeMap = new int[array.Length]; - int maxEl = array[0]; - int maxCount = 1; - for (int i = 0; i < array.Length; i++) - { - int el = array[i]; - if (modeMap[el] == 0) - modeMap[el] = 1; - else - modeMap[el]++; - - if (modeMap[el] > maxCount) - { - maxEl = el; - maxCount = modeMap[el]; - } - } - return maxEl; - } - - private static double Map(double value, double oldMin, double oldMax, double newMin, double newMax) => newMin + ((newMax - newMin) * ((value - oldMin) / (oldMax - oldMin))); - #endregion } } diff --git a/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/LevelVisualizationProvider.cs b/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/LevelVisualizationProvider.cs index e71535c..4c62f33 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/LevelVisualizationProvider.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/VisualizationProvider/LevelVisualizationProvider.cs @@ -3,7 +3,6 @@ using System.Linq; using KeyboardAudioVisualizer.AudioCapture; using KeyboardAudioVisualizer.Configuration; using KeyboardAudioVisualizer.Helper; -using RGB.NET.Core; namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider { @@ -63,10 +62,6 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider public IConfiguration Configuration => _configuration; public float[] VisualizationData { get; } = new float[3]; - public string DisplayName => "Level"; - - public RGBDeviceType VisualizerFor => RGBDeviceType.Keyboard | RGBDeviceType.LedMatrix | RGBDeviceType.LedStripe | RGBDeviceType.Mousepad; - #endregion #region Constructors diff --git a/KeyboardAudioVisualizer/Controls/Formular.cs b/KeyboardAudioVisualizer/Controls/Form.cs similarity index 93% rename from KeyboardAudioVisualizer/Controls/Formular.cs rename to KeyboardAudioVisualizer/Controls/Form.cs index ed82f12..1571f96 100644 --- a/KeyboardAudioVisualizer/Controls/Formular.cs +++ b/KeyboardAudioVisualizer/Controls/Form.cs @@ -4,12 +4,12 @@ using System.Windows.Controls; namespace KeyboardAudioVisualizer.Controls { - public class Formular : Panel + public class Form : Panel { #region DependencyProperties // ReSharper disable InconsistentNaming - public static readonly DependencyProperty RowHeightProperty = DependencyProperty.Register("RowHeight", typeof(double), typeof(Formular), + public static readonly DependencyProperty RowHeightProperty = DependencyProperty.Register("RowHeight", typeof(double), typeof(Form), new FrameworkPropertyMetadata(24.0, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public double RowHeight @@ -22,7 +22,7 @@ namespace KeyboardAudioVisualizer.Controls } } - public static readonly DependencyProperty LabelWidthProperty = DependencyProperty.Register("LabelWidth", typeof(double), typeof(Formular), + public static readonly DependencyProperty LabelWidthProperty = DependencyProperty.Register("LabelWidth", typeof(double), typeof(Form), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public double LabelWidth @@ -35,7 +35,7 @@ namespace KeyboardAudioVisualizer.Controls } } - public static readonly DependencyProperty ElementSpacingProperty = DependencyProperty.Register("ElementSpacing", typeof(double), typeof(Formular), + public static readonly DependencyProperty ElementSpacingProperty = DependencyProperty.Register("ElementSpacing", typeof(double), typeof(Form), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public double ElementSpacing @@ -44,7 +44,7 @@ namespace KeyboardAudioVisualizer.Controls set => SetValue(ElementSpacingProperty, value); } - public static readonly DependencyProperty RowSpacingProperty = DependencyProperty.Register("RowSpacing", typeof(double), typeof(Formular), + public static readonly DependencyProperty RowSpacingProperty = DependencyProperty.Register("RowSpacing", typeof(double), typeof(Form), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public double RowSpacing @@ -59,25 +59,25 @@ namespace KeyboardAudioVisualizer.Controls #region AttachedProperties // ReSharper disable InconsistentNaming - public static readonly DependencyProperty IsLabelProperty = DependencyProperty.RegisterAttached("IsLabel", typeof(bool), typeof(Formular), + public static readonly DependencyProperty IsLabelProperty = DependencyProperty.RegisterAttached("IsLabel", typeof(bool), typeof(Form), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public static void SetIsLabel(UIElement element, bool value) => element.SetValue(IsLabelProperty, value); public static bool GetIsLabel(UIElement element) => (bool)element.GetValue(IsLabelProperty); - public static readonly DependencyProperty LineBreaksProperty = DependencyProperty.RegisterAttached("LineBreaks", typeof(int), typeof(Formular), + public static readonly DependencyProperty LineBreaksProperty = DependencyProperty.RegisterAttached("LineBreaks", typeof(int), typeof(Form), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public static void SetLineBreaks(UIElement element, int value) => element.SetValue(LineBreaksProperty, value); public static int GetLineBreaks(UIElement element) => (int)element.GetValue(LineBreaksProperty); - public static readonly DependencyProperty RowSpanProperty = DependencyProperty.RegisterAttached("RowSpan", typeof(int), typeof(Formular), + public static readonly DependencyProperty RowSpanProperty = DependencyProperty.RegisterAttached("RowSpan", typeof(int), typeof(Form), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public static void SetRowSpan(DependencyObject element, int value) => element.SetValue(RowSpanProperty, value); public static int GetRowSpan(DependencyObject element) => (int)element.GetValue(RowSpanProperty); - public static readonly DependencyProperty FillProperty = DependencyProperty.RegisterAttached("Fill", typeof(bool), typeof(Formular), + public static readonly DependencyProperty FillProperty = DependencyProperty.RegisterAttached("Fill", typeof(bool), typeof(Form), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); public static void SetFill(DependencyObject element, bool value) => element.SetValue(FillProperty, value); @@ -92,7 +92,7 @@ namespace KeyboardAudioVisualizer.Controls { if (InternalChildren.Count == 0) return new Size(0, 0); - FormularLayout layout = new FormularLayout(RowHeight, LabelWidth, ElementSpacing, RowSpacing); + FormLayout layout = new FormLayout(RowHeight, LabelWidth, ElementSpacing, RowSpacing); foreach (UIElement child in InternalChildren) { @@ -107,7 +107,7 @@ namespace KeyboardAudioVisualizer.Controls { if (InternalChildren.Count == 0) return new Size(0, 0); - FormularLayout layout = new FormularLayout(RowHeight, LabelWidth, ElementSpacing, RowSpacing); + FormLayout layout = new FormLayout(RowHeight, LabelWidth, ElementSpacing, RowSpacing); foreach (UIElement child in InternalChildren) child.Arrange(layout.AddElement(child, finalSize.Width)); @@ -119,7 +119,7 @@ namespace KeyboardAudioVisualizer.Controls #region Data - private class FormularLayout + private class FormLayout { #region Properties & Fields @@ -140,7 +140,7 @@ namespace KeyboardAudioVisualizer.Controls #region Constructors - public FormularLayout(double rowHeight, double labelWidth, double elementSpacing, double rowSpacing) + public FormLayout(double rowHeight, double labelWidth, double elementSpacing, double rowSpacing) { this._rowHeight = rowHeight; this._labelWidth = labelWidth; diff --git a/KeyboardAudioVisualizer/Helper/RingBuffer.cs b/KeyboardAudioVisualizer/Helper/RingBuffer.cs new file mode 100644 index 0000000..ab2cbb3 --- /dev/null +++ b/KeyboardAudioVisualizer/Helper/RingBuffer.cs @@ -0,0 +1,68 @@ +using System.Linq; + +namespace KeyboardAudioVisualizer.Helper +{ + public class RingBuffer + { + #region Properties & Fields + + private readonly int _capacity; + private readonly float[] _buffer; + private int _currentIndex; + + public int Size => _capacity; + + public float Average => _buffer.Average(); + public float Min => _buffer.Min(); + public float Max => _buffer.Max(); + public float Sum => _buffer.Sum(); + + #endregion + + #region Constructors + + public RingBuffer(int capacity) + { + this._capacity = capacity; + + _buffer = new float[capacity]; + } + + #endregion + + #region Methods + + public void Put(float value) => Put(new[] { value }, 0, 1); + + public void Put(float[] src, int offset, int count) + { + lock (_buffer) + { + if (count > _capacity) + { + offset += count - _capacity; + count = _capacity; + } + + for (int i = 0; i < count; i++) + { + _currentIndex++; + if (_currentIndex >= _capacity) _currentIndex = 0; + + _buffer[_currentIndex] = src[offset + i]; + } + } + } + + + public void CopyInto(ref float[] data, int offset) => CopyInto(ref data, offset, _capacity); + public void CopyInto(ref float[] data, int offset, int count) + { + lock (_buffer) + for (int i = _capacity - count; i < count; i++) + data[offset + i] = _buffer[(_currentIndex + i) % _capacity]; + } + + #endregion + } +} diff --git a/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj b/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj index fdaf5c8..8864425 100644 --- a/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj +++ b/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj @@ -149,7 +149,7 @@ - + @@ -162,6 +162,7 @@ + @@ -256,7 +257,7 @@ MSBuild:Compile Designer - + MSBuild:Compile Designer diff --git a/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml b/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml index d468d75..d1fdcb2 100644 --- a/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml +++ b/KeyboardAudioVisualizer/Resources/KeyboardAudioVisualizer.xaml @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ - - - - diff --git a/KeyboardAudioVisualizer/UI/Configuration/BeatConfiguration.xaml b/KeyboardAudioVisualizer/UI/Configuration/BeatConfiguration.xaml index c72c70d..13677f8 100644 --- a/KeyboardAudioVisualizer/UI/Configuration/BeatConfiguration.xaml +++ b/KeyboardAudioVisualizer/UI/Configuration/BeatConfiguration.xaml @@ -13,14 +13,14 @@ -