mirror of
https://github.com/DarthAffe/KeyboardAudioVisualizer.git
synced 2025-12-12 15:18:30 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 008fd65c08 | |||
| f7f30f36c7 | |||
| e62259ca63 | |||
| b30bb88762 | |||
| 6ad2e861a0 | |||
| 967dde1d3d | |||
| 7216eae954 | |||
| e94c0723c5 | |||
| 5dfc02eeab | |||
| 806dd3aae7 | |||
| dde304b007 | |||
| 7eac420a8e | |||
| 7cf179421f | |||
| b54e01a96b | |||
| 7b6c2c184e | |||
| 8f53049bdf | |||
|
|
0ec92488e4 | ||
| 4141a5dd36 | |||
| 2ad4a6f333 | |||
| 4543dcb787 | |||
| 1cef641c62 | |||
| 940d2eb631 | |||
| 8d1488db24 | |||
| 3c76269c65 | |||
| f42334aa2b | |||
| 2f9286e39d | |||
| d4b4071f71 | |||
| cb8146c594 | |||
| 1af8bb67c3 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -286,6 +286,3 @@ __pycache__/
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
/NuGet.Config
|
||||
/NuGet.Config
|
||||
/KeyboardAudioVisualizer/NuGet.Config
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@ -4,9 +4,12 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Hardcodet.Wpf.TaskbarNotification;
|
||||
using KeyboardAudioVisualizer.AudioProcessing;
|
||||
using KeyboardAudioVisualizer.Configuration;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using KeyboardAudioVisualizer.Legacy;
|
||||
using Newtonsoft.Json;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using Settings = KeyboardAudioVisualizer.Configuration.Settings;
|
||||
|
||||
namespace KeyboardAudioVisualizer
|
||||
@ -40,7 +43,7 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
//Settings settings = SerializationHelper.LoadObjectFromFile<Settings>(PATH_SETTINGS);
|
||||
Settings settings = null;
|
||||
try { settings = JsonConvert.DeserializeObject<Settings>(File.ReadAllText(PATH_SETTINGS)); }
|
||||
try { settings = JsonConvert.DeserializeObject<Settings>(File.ReadAllText(PATH_SETTINGS), new ColorSerializer()); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
@ -52,9 +55,16 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new Settings();
|
||||
settings = new Settings
|
||||
{
|
||||
Version = Settings.CURRENT_VERSION,
|
||||
Background = new LinearGradient(new GradientStop(0.5, new Color(64, 0, 0, 0)))
|
||||
};
|
||||
_taskbarIcon.ShowBalloonTip("Keyboard Audio-Visualizer is starting in the tray!", "Click on the icon to open the configuration.", BalloonIcon.Info);
|
||||
}
|
||||
else if (settings.Version != Settings.CURRENT_VERSION)
|
||||
ConfigurationUpdates.PerformOn(settings);
|
||||
|
||||
ApplicationManager.Instance.Settings = settings;
|
||||
|
||||
AudioVisualizationFactory.Initialize();
|
||||
@ -74,7 +84,7 @@ namespace KeyboardAudioVisualizer
|
||||
{
|
||||
base.OnExit(e);
|
||||
|
||||
File.WriteAllText(PATH_SETTINGS, JsonConvert.SerializeObject(ApplicationManager.Instance.Settings));
|
||||
File.WriteAllText(PATH_SETTINGS, JsonConvert.SerializeObject(ApplicationManager.Instance.Settings, new ColorSerializer()));
|
||||
ConfigurationMigrator.CleanupOldConfigs();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -13,8 +11,10 @@ using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Devices.CoolerMaster;
|
||||
using RGB.NET.Devices.Corsair;
|
||||
using RGB.NET.Devices.Corsair.SpecialParts;
|
||||
using RGB.NET.Devices.Logitech;
|
||||
using RGB.NET.Devices.Novation;
|
||||
using RGB.NET.Devices.Razer;
|
||||
using RGB.NET.Devices.SteelSeries;
|
||||
using RGB.NET.Groups;
|
||||
using Point = RGB.NET.Core.Point;
|
||||
using GetDecoratorFunc = System.Func<KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider.VisualizationType, KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider.IVisualizationProvider, RGB.NET.Core.IBrushDecorator>;
|
||||
@ -38,6 +38,8 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
private readonly Dictionary<VisualizationIndex, IEnumerable<(ILedGroup group, GetDecoratorFunc getDecoratorFunc)>> _groups = new Dictionary<VisualizationIndex, IEnumerable<(ILedGroup group, GetDecoratorFunc getDecoratorFunc)>>();
|
||||
|
||||
public TimerUpdateTrigger UpdateTrigger { get; } = new TimerUpdateTrigger();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Commands
|
||||
@ -62,15 +64,24 @@ namespace KeyboardAudioVisualizer
|
||||
{
|
||||
RGBSurface surface = RGBSurface.Instance;
|
||||
|
||||
surface.UpdateFrequency = 1.0 / MathHelper.Clamp(Settings.UpdateRate, 1, 40);
|
||||
surface.UpdateMode = UpdateMode.Continuous;
|
||||
UpdateTrigger.UpdateFrequency = 1.0 / MathHelper.Clamp(Settings.UpdateRate, 1, 60);
|
||||
surface.RegisterUpdateTrigger(UpdateTrigger);
|
||||
|
||||
surface.LoadDevices(CorsairDeviceProvider.Instance);
|
||||
surface.LoadDevices(LogitechDeviceProvider.Instance);
|
||||
surface.LoadDevices(CoolerMasterDeviceProvider.Instance);
|
||||
LoadDevices(surface, CorsairDeviceProvider.Instance);
|
||||
LoadDevices(surface, CoolerMasterDeviceProvider.Instance);
|
||||
LoadDevices(surface, NovationDeviceProvider.Instance);
|
||||
LoadDevices(surface, RazerDeviceProvider.Instance);
|
||||
LoadDevices(surface, LogitechDeviceProvider.Instance);
|
||||
LoadDevices(surface, SteelSeriesDeviceProvider.Instance);
|
||||
|
||||
surface.AlignDevices();
|
||||
|
||||
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!
|
||||
background.Brush = new LinearGradientBrush(Settings.Background);
|
||||
|
||||
LinearGradient primaryGradient = Settings[VisualizationIndex.Primary].Gradient;
|
||||
LinearGradient secondaryGradient = Settings[VisualizationIndex.Secondary].Gradient;
|
||||
LinearGradient tertiaryGradient = Settings[VisualizationIndex.Tertiary].Gradient;
|
||||
|
||||
List<(ILedGroup, GetDecoratorFunc)> primaryGroups = new List<(ILedGroup, GetDecoratorFunc)>();
|
||||
List<(ILedGroup, GetDecoratorFunc)> secondaryGroups = new List<(ILedGroup, GetDecoratorFunc)>();
|
||||
@ -79,6 +90,7 @@ namespace KeyboardAudioVisualizer
|
||||
switch (device.DeviceInfo.DeviceType)
|
||||
{
|
||||
case RGBDeviceType.Keyboard:
|
||||
case RGBDeviceType.Keypad:
|
||||
case RGBDeviceType.LedMatrix:
|
||||
ListLedGroup primary = new ListLedGroup(device);
|
||||
|
||||
@ -87,42 +99,44 @@ namespace KeyboardAudioVisualizer
|
||||
{
|
||||
primary.RemoveLeds(lightbar.Leds);
|
||||
|
||||
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), tertiaryGradient);
|
||||
tertiaryGroups.Add((lightbarLeft, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Left, 0)));
|
||||
|
||||
ILedGroup lightbarRight = new ListLedGroup(lightbar.Right);
|
||||
lightbarRight.Brush = new LinearGradientBrush(keyboardLevelGradient);
|
||||
lightbarRight.Brush = new LinearGradientBrush(tertiaryGradient);
|
||||
tertiaryGroups.Add((lightbarRight, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Right, 1)));
|
||||
|
||||
ILedGroup lightbarCenter = new ListLedGroup(lightbar.Center);
|
||||
lightbarCenter.Brush = new SolidColorBrush(new Color(255, 255, 255));
|
||||
lightbarCenter.Brush = new LinearGradientBrush(secondaryGradient);
|
||||
secondaryGroups.Add((lightbarCenter, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer)));
|
||||
}
|
||||
|
||||
primary.Brush = new LinearGradientBrush(new RainbowGradient(300, -14));
|
||||
primaryGroups.Add((primary, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Horizontal)));
|
||||
primary.Brush = new LinearGradientBrush(primaryGradient);
|
||||
primaryGroups.Add((primary, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Horizontal, 0, primaryGradient)));
|
||||
break;
|
||||
|
||||
case RGBDeviceType.Mousepad:
|
||||
case RGBDeviceType.LedStripe:
|
||||
IGradient mousepadLevelGradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)), new GradientStop(1, new Color(255, 0, 0)));
|
||||
|
||||
case RGBDeviceType.HeadsetStand:
|
||||
ILedGroup left = new RectangleLedGroup(new Rectangle(device.Location.X, device.Location.Y, device.Size.Width / 2.0, device.Size.Height));
|
||||
left.Brush = new LinearGradientBrush(new Point(0.5, 1), new Point(0.5, 0), mousepadLevelGradient);
|
||||
left.Brush = new LinearGradientBrush(new Point(0.5, 1), new Point(0.5, 0), tertiaryGradient);
|
||||
tertiaryGroups.Add((left, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Top, 0)));
|
||||
|
||||
ILedGroup right = new RectangleLedGroup(new Rectangle(device.Location.X + (device.Size.Width / 2.0), device.Location.Y, device.Size.Width / 2.0, device.Size.Height));
|
||||
right.Brush = new LinearGradientBrush(new Point(0.5, 1), new Point(0.5, 0), mousepadLevelGradient);
|
||||
right.Brush = new LinearGradientBrush(new Point(0.5, 1), new Point(0.5, 0), tertiaryGradient);
|
||||
tertiaryGroups.Add((right, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Top, 1)));
|
||||
break;
|
||||
|
||||
case RGBDeviceType.Mouse:
|
||||
case RGBDeviceType.Headset:
|
||||
case RGBDeviceType.Speaker:
|
||||
case RGBDeviceType.Fan:
|
||||
case RGBDeviceType.GraphicsCard:
|
||||
case RGBDeviceType.DRAM:
|
||||
case RGBDeviceType.Mainboard:
|
||||
ILedGroup deviceGroup = new ListLedGroup(device);
|
||||
deviceGroup.Brush = new SolidColorBrush(new Color(255, 255, 255));
|
||||
deviceGroup.Brush = new LinearGradientBrush(secondaryGradient);
|
||||
secondaryGroups.Add((deviceGroup, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer)));
|
||||
break;
|
||||
}
|
||||
@ -138,6 +152,14 @@ namespace KeyboardAudioVisualizer
|
||||
surface.Updating += args => AudioVisualizationFactory.Instance.Update();
|
||||
}
|
||||
|
||||
private void LoadDevices(RGBSurface surface, IRGBDeviceProvider deviceProvider)
|
||||
{
|
||||
surface.LoadDevices(deviceProvider, RGBDeviceType.Keyboard | RGBDeviceType.LedMatrix
|
||||
| RGBDeviceType.Mousepad | RGBDeviceType.LedStripe
|
||||
| RGBDeviceType.Mouse | RGBDeviceType.Headset
|
||||
| RGBDeviceType.HeadsetStand);
|
||||
}
|
||||
|
||||
//TODO DarthAffe 12.09.2017: This is just a big mess - is this worth to rework before arge?
|
||||
public void ApplyVisualization(VisualizationIndex visualizationIndex, VisualizationType visualizationType)
|
||||
{
|
||||
@ -157,13 +179,13 @@ namespace KeyboardAudioVisualizer
|
||||
}
|
||||
}
|
||||
|
||||
private IBrushDecorator CreateDecorator(VisualizationType visualizationType, IVisualizationProvider visualizationProvider, LevelBarDirection direction = LevelBarDirection.Top, int dataIndex = 0)
|
||||
private IBrushDecorator CreateDecorator(VisualizationType visualizationType, IVisualizationProvider visualizationProvider, LevelBarDirection direction = LevelBarDirection.Top, int dataIndex = 0, LinearGradient gradient = null)
|
||||
{
|
||||
if (visualizationType == VisualizationType.FrequencyBars)
|
||||
return new FrequencyBarsDecorator(visualizationProvider);
|
||||
|
||||
if (visualizationType == VisualizationType.Level)
|
||||
return new LevelBarDecorator(visualizationProvider, direction, dataIndex);
|
||||
return new LevelBarDecorator(visualizationProvider, direction, dataIndex, gradient);
|
||||
|
||||
if (visualizationType == VisualizationType.Beat)
|
||||
return new BeatDecorator(visualizationProvider);
|
||||
@ -179,8 +201,8 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
private void Exit()
|
||||
{
|
||||
RGBSurface.Instance?.Dispose();
|
||||
AudioVisualizationFactory.Instance?.Dispose();
|
||||
try { AudioVisualizationFactory.Instance?.Dispose(); } catch { }
|
||||
try { RGBSurface.Instance?.Dispose(); } catch { }
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,8 @@ namespace KeyboardAudioVisualizer.AudioCapture
|
||||
|
||||
public int Size => _capacity;
|
||||
|
||||
public float? Prescale { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
@ -29,51 +31,68 @@ namespace KeyboardAudioVisualizer.AudioCapture
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Put(float left, float right)
|
||||
{
|
||||
_currentIndex++;
|
||||
if (_currentIndex >= _capacity) _currentIndex = 0;
|
||||
|
||||
_bufferLeft[_currentIndex] = left;
|
||||
_bufferRight[_currentIndex] = right;
|
||||
}
|
||||
|
||||
public void Put(float[] src, int offset, int count)
|
||||
{
|
||||
lock (_bufferLeft)
|
||||
if ((count & 1) != 0) return; // we expect stereo-data to be an even amount of values
|
||||
|
||||
if (count > _capacity)
|
||||
{
|
||||
if ((count & 1) != 0) return; // we expect stereo-data to be an even amount of values
|
||||
offset += count - _capacity;
|
||||
count = _capacity;
|
||||
}
|
||||
|
||||
if (count > _capacity)
|
||||
for (int i = 0; i < count; i += 2)
|
||||
{
|
||||
_currentIndex++;
|
||||
if (_currentIndex >= _capacity) _currentIndex = 0;
|
||||
|
||||
if (Prescale.HasValue)
|
||||
{
|
||||
offset += count - _capacity;
|
||||
count = _capacity;
|
||||
_bufferLeft[_currentIndex] = src[offset + i] / Prescale.Value;
|
||||
_bufferRight[_currentIndex] = src[offset + i + 1] / Prescale.Value;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i += 2)
|
||||
else
|
||||
{
|
||||
_currentIndex++;
|
||||
if (_currentIndex >= _capacity) _currentIndex = 0;
|
||||
|
||||
_bufferLeft[_currentIndex] = src[offset + i];
|
||||
_bufferRight[_currentIndex] = src[offset + i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyLeftInto(ref float[] data, int offset)
|
||||
public void CopyLeftInto(ref float[] data, int offset) => CopyLeftInto(ref data, offset, Math.Min(data.Length, _capacity));
|
||||
public void CopyLeftInto(ref float[] data, int offset, int count)
|
||||
{
|
||||
lock (_bufferLeft)
|
||||
for (int i = 0; i < _capacity; i++)
|
||||
data[offset + i] = _bufferLeft[(_currentIndex + i) % _capacity];
|
||||
int bufferOffset = _capacity - count;
|
||||
for (int i = 0; i < count; i++)
|
||||
data[offset + i] = _bufferLeft[(_currentIndex + (bufferOffset + i)) % _capacity];
|
||||
}
|
||||
|
||||
public void CopyRightInto(ref float[] data, int offset)
|
||||
public void CopyRightInto(ref float[] data, int offset) => CopyRightInto(ref data, offset, Math.Min(data.Length, _capacity));
|
||||
public void CopyRightInto(ref float[] data, int offset, int count)
|
||||
{
|
||||
lock (_bufferLeft)
|
||||
for (int i = 0; i < _capacity; i++)
|
||||
data[offset + i] = _bufferRight[(_currentIndex + i) % _capacity];
|
||||
int bufferOffset = _capacity - count;
|
||||
for (int i = 0; i < count; i++)
|
||||
data[offset + i] = _bufferRight[(_currentIndex + (bufferOffset + i)) % _capacity];
|
||||
}
|
||||
|
||||
public void CopyMixInto(ref float[] data, int offset)
|
||||
public void CopyMixInto(ref float[] data, int offset) => CopyMixInto(ref data, offset, Math.Min(data.Length, _capacity));
|
||||
public void CopyMixInto(ref float[] data, int offset, int count)
|
||||
{
|
||||
lock (_bufferLeft)
|
||||
for (int i = 0; i < _capacity; i++)
|
||||
{
|
||||
int index = (_currentIndex + i) % _capacity;
|
||||
data[offset + i] = (_bufferLeft[index] + _bufferRight[index]) / 2f;
|
||||
}
|
||||
int bufferOffset = _capacity - count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int index = (_currentIndex + (bufferOffset + i)) % _capacity;
|
||||
data[offset + i] = (_bufferLeft[index] + _bufferRight[index]) / 2f;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using CSCore;
|
||||
using System;
|
||||
using CSCore;
|
||||
using CSCore.CoreAudioAPI;
|
||||
using CSCore.SoundIn;
|
||||
using CSCore.Streams;
|
||||
|
||||
@ -10,11 +12,12 @@ namespace KeyboardAudioVisualizer.AudioCapture
|
||||
|
||||
private WasapiCapture _capture;
|
||||
private SoundInSource _soundInSource;
|
||||
private IWaveSource _source;
|
||||
private SingleBlockNotificationStream _stream;
|
||||
|
||||
private readonly float[] _readBuffer = new float[2048];
|
||||
private AudioEndpointVolume _audioEndpointVolume;
|
||||
|
||||
public int SampleRate => _soundInSource?.WaveFormat?.SampleRate ?? -1;
|
||||
public float MasterVolume => _audioEndpointVolume.MasterVolumeLevelScalar;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -28,15 +31,34 @@ namespace KeyboardAudioVisualizer.AudioCapture
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_capture = new WasapiLoopbackCapture();
|
||||
MMDevice captureDevice = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Console);
|
||||
WaveFormat deviceFormat = captureDevice.DeviceFormat;
|
||||
_audioEndpointVolume = AudioEndpointVolume.FromDevice(captureDevice);
|
||||
|
||||
//DarthAffe 07.02.2018: This is a really stupid workaround to (hopefully) finally fix the surround driver issues
|
||||
for (int i = 1; i < 13; i++)
|
||||
try { _capture = new WasapiLoopbackCapture(100, new WaveFormat(deviceFormat.SampleRate, deviceFormat.BitsPerSample, i)); } catch { /* We're just trying ... */ }
|
||||
|
||||
if (_capture == null)
|
||||
throw new NullReferenceException("Failed to initialize WasapiLoopbackCapture");
|
||||
|
||||
_capture.Initialize();
|
||||
|
||||
_soundInSource = new SoundInSource(_capture) { FillWithZeros = false };
|
||||
_source = _soundInSource.WaveFormat.SampleRate == 44100
|
||||
? _soundInSource.ToStereo()
|
||||
: _soundInSource.ChangeSampleRate(44100).ToStereo();
|
||||
|
||||
_stream = _soundInSource.WaveFormat.SampleRate == 44100
|
||||
? new SingleBlockNotificationStream(_soundInSource.ToStereo().ToSampleSource())
|
||||
: new SingleBlockNotificationStream(_soundInSource.ChangeSampleRate(44100).ToStereo().ToSampleSource());
|
||||
_stream = new SingleBlockNotificationStream(_source.ToSampleSource());
|
||||
_stream.SingleBlockRead += StreamOnSingleBlockRead;
|
||||
|
||||
_soundInSource.DataAvailable += OnSoundDataAvailable;
|
||||
_source = _stream.ToWaveSource();
|
||||
|
||||
byte[] buffer = new byte[_source.WaveFormat.BytesPerSecond / 2];
|
||||
_soundInSource.DataAvailable += (s, aEvent) =>
|
||||
{
|
||||
while ((_source.Read(buffer, 0, buffer.Length)) > 0) ;
|
||||
};
|
||||
|
||||
_capture.Start();
|
||||
}
|
||||
@ -47,12 +69,8 @@ namespace KeyboardAudioVisualizer.AudioCapture
|
||||
_capture?.Dispose();
|
||||
}
|
||||
|
||||
private void OnSoundDataAvailable(object sender, DataAvailableEventArgs dataAvailableEventArgs)
|
||||
{
|
||||
int readCount;
|
||||
while ((readCount = _stream.Read(_readBuffer, 0, _readBuffer.Length)) > 0)
|
||||
DataAvailable?.Invoke(_readBuffer, 0, readCount);
|
||||
}
|
||||
private void StreamOnSingleBlockRead(object sender, SingleBlockReadEventArgs singleBlockReadEventArgs)
|
||||
=> DataAvailable?.Invoke(singleBlockReadEventArgs.Left, singleBlockReadEventArgs.Right);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -2,11 +2,12 @@
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioCapture
|
||||
{
|
||||
public delegate void AudioData(float[] data, int offset, int count);
|
||||
public delegate void AudioData(float left, float right);
|
||||
|
||||
public interface IAudioInput : IDisposable
|
||||
{
|
||||
int SampleRate { get; }
|
||||
float MasterVolume { get; }
|
||||
|
||||
event AudioData DataAvailable;
|
||||
|
||||
|
||||
@ -31,6 +31,11 @@ namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (ApplicationManager.Instance.Settings.EnableAudioPrescale)
|
||||
_audioBuffer.Prescale = _audioInput.MasterVolume;
|
||||
else
|
||||
_audioBuffer.Prescale = null;
|
||||
|
||||
foreach (IAudioProcessor processor in _processors.Where(x => x.IsActive))
|
||||
processor.Update();
|
||||
}
|
||||
@ -49,7 +54,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
_audioInput.Initialize();
|
||||
|
||||
_audioBuffer = new AudioBuffer(4096); // Working with ~93ms -
|
||||
_audioInput.DataAvailable += (data, offset, count) => _audioBuffer.Put(data, offset, count);
|
||||
_audioInput.DataAvailable += (left, right) => _audioBuffer.Put(left, right);
|
||||
|
||||
_processors.Add(new FourierSpectrumProvider(_audioBuffer));
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -85,9 +80,9 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_sampleDataLeft = new float[_audioBuffer.Size];
|
||||
_sampleDataRight = new float[_audioBuffer.Size];
|
||||
_sampleDataMix = new float[_audioBuffer.Size];
|
||||
_sampleDataLeft = new float[2048];
|
||||
_sampleDataRight = new float[2048];
|
||||
_sampleDataMix = new float[2048];
|
||||
|
||||
RecalculateConfigValues(null);
|
||||
}
|
||||
|
||||
@ -1,25 +1,12 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml.Serialization;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Configuration
|
||||
{
|
||||
public class AbstractConfiguration : AbstractBindable, IConfiguration, INotifyPropertyChanged
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private IBrush _brush;
|
||||
[XmlIgnore]
|
||||
public IBrush Brush
|
||||
{
|
||||
get => _brush;
|
||||
set => SetProperty(ref _brush, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
||||
|
||||
47
KeyboardAudioVisualizer/Configuration/ColorSerializer.cs
Normal file
47
KeyboardAudioVisualizer/Configuration/ColorSerializer.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Configuration
|
||||
{
|
||||
public class ColorSerializer : JsonConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public override bool CanConvert(Type objectType) => objectType == typeof(Color);
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (!(value is Color color)) return;
|
||||
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName("A");
|
||||
writer.WriteValue(color.A);
|
||||
writer.WritePropertyName("R");
|
||||
writer.WriteValue(color.R);
|
||||
writer.WritePropertyName("G");
|
||||
writer.WriteValue(color.G);
|
||||
writer.WritePropertyName("B");
|
||||
writer.WriteValue(color.B);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
JObject jsonObject = JObject.Load(reader);
|
||||
if (jsonObject.Property("A").Value.ToObject<double>() > 1.0) //DarthAffe 09.06.2019: Convert old Settings
|
||||
return new Color(jsonObject.Property("A").Value.ToObject<byte>(),
|
||||
jsonObject.Property("R").Value.ToObject<byte>(),
|
||||
jsonObject.Property("G").Value.ToObject<byte>(),
|
||||
jsonObject.Property("B").Value.ToObject<byte>());
|
||||
else
|
||||
return new Color(jsonObject.Property("A").Value.ToObject<double>(),
|
||||
jsonObject.Property("R").Value.ToObject<double>(),
|
||||
jsonObject.Property("G").Value.ToObject<double>(),
|
||||
jsonObject.Property("B").Value.ToObject<double>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,7 @@
|
||||
using System.ComponentModel;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Configuration
|
||||
{
|
||||
public interface IConfiguration : INotifyPropertyChanged
|
||||
{
|
||||
IBrush Brush { get; set; }
|
||||
}
|
||||
{ }
|
||||
}
|
||||
|
||||
@ -2,15 +2,29 @@
|
||||
using System.Collections.Generic;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Configuration
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
#region Constants
|
||||
|
||||
public const int CURRENT_VERSION = 1;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public int Version { get; set; } = 0;
|
||||
|
||||
public double UpdateRate { get; set; } = 40.0;
|
||||
|
||||
public bool EnableAudioPrescale { get; set; } = false;
|
||||
|
||||
public LinearGradient Background { get; set; }
|
||||
|
||||
public Dictionary<VisualizationIndex, VisualizationSettings> Visualizations { get; set; } = new Dictionary<VisualizationIndex, VisualizationSettings>();
|
||||
|
||||
public VisualizationSettings this[VisualizationIndex visualizationIndex]
|
||||
@ -32,6 +46,8 @@ namespace KeyboardAudioVisualizer.Configuration
|
||||
|
||||
public VisualizationType SelectedVisualization { get; set; }
|
||||
|
||||
public LinearGradient Gradient { get; set; }
|
||||
|
||||
public EqualizerConfiguration EqualizerConfiguration { get; set; } = new EqualizerConfiguration();
|
||||
|
||||
public FrequencyBarsVisualizationProviderConfiguration FrequencyBarsConfiguration { get; set; } = new FrequencyBarsVisualizationProviderConfiguration();
|
||||
@ -72,14 +88,24 @@ namespace KeyboardAudioVisualizer.Configuration
|
||||
{
|
||||
case VisualizationIndex.Primary:
|
||||
SelectedVisualization = VisualizationType.FrequencyBars;
|
||||
Gradient = new LinearGradient(new GradientStop(0, HSVColor.Create(300, 1, 1)),
|
||||
new GradientStop(0.20, HSVColor.Create(225, 1, 1)),
|
||||
new GradientStop(0.35, HSVColor.Create(180, 1, 1)),
|
||||
new GradientStop(0.50, HSVColor.Create(135, 1, 1)),
|
||||
new GradientStop(0.65, HSVColor.Create(90, 1, 1)),
|
||||
new GradientStop(0.80, HSVColor.Create(45, 1, 1)),
|
||||
new GradientStop(0.95, HSVColor.Create(0, 1, 1)));
|
||||
break;
|
||||
|
||||
case VisualizationIndex.Secondary:
|
||||
SelectedVisualization = VisualizationType.Beat;
|
||||
Gradient = new LinearGradient(new GradientStop(0.5, new Color(255, 255, 255)));
|
||||
break;
|
||||
|
||||
case VisualizationIndex.Tertiary:
|
||||
SelectedVisualization = VisualizationType.Level;
|
||||
Gradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)),
|
||||
new GradientStop(1, new Color(255, 0, 0)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
483
KeyboardAudioVisualizer/Controls/ColorSelector.cs
Normal file
483
KeyboardAudioVisualizer/Controls/ColorSelector.cs
Normal file
@ -0,0 +1,483 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using RGB.NET.Core;
|
||||
using Color = RGB.NET.Core.Color;
|
||||
using Point = System.Windows.Point;
|
||||
using Rectangle = System.Windows.Shapes.Rectangle;
|
||||
using WpfColor = System.Windows.Media.Color;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Controls
|
||||
{
|
||||
[TemplatePart(Name = "PART_Selector", Type = typeof(Panel))]
|
||||
[TemplatePart(Name = "PART_SliderAlpha", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_SliderRed", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_SliderGreen", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_SliderBlue", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_SliderHue", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_SliderSaturation", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_SliderValue", Type = typeof(Slider))]
|
||||
[TemplatePart(Name = "PART_Preview", Type = typeof(Rectangle))]
|
||||
public class ColorSelector : Control
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private bool _ignorePropertyChanged;
|
||||
private bool _dragSelector;
|
||||
|
||||
private byte _a;
|
||||
private byte _r;
|
||||
private byte _g;
|
||||
private byte _b;
|
||||
private double _hue;
|
||||
private double _saturation;
|
||||
private double _value;
|
||||
|
||||
private Panel _selector;
|
||||
private Rectangle _selectorColor;
|
||||
private Grid _selectorGrip;
|
||||
private Slider _sliderAlpha;
|
||||
private Slider _sliderRed;
|
||||
private Slider _sliderGreen;
|
||||
private Slider _sliderBlue;
|
||||
private Slider _sliderHue;
|
||||
private Slider _sliderSaturation;
|
||||
private Slider _sliderValue;
|
||||
private Rectangle _preview;
|
||||
|
||||
private SolidColorBrush _previewBrush;
|
||||
private SolidColorBrush _selectorBrush;
|
||||
private LinearGradientBrush _alphaBrush;
|
||||
private LinearGradientBrush _redBrush;
|
||||
private LinearGradientBrush _greenBrush;
|
||||
private LinearGradientBrush _blueBrush;
|
||||
private LinearGradientBrush _hueBrush;
|
||||
private LinearGradientBrush _saturationBrush;
|
||||
private LinearGradientBrush _valueBrush;
|
||||
|
||||
#endregion
|
||||
|
||||
#region DependencyProperties
|
||||
|
||||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register(
|
||||
"SelectedColor", typeof(Color), typeof(ColorSelector), new FrameworkPropertyMetadata(new Color(255, 0, 0),
|
||||
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
|
||||
SelectedColorChanged));
|
||||
|
||||
public Color SelectedColor
|
||||
{
|
||||
get => (Color)GetValue(SelectedColorProperty);
|
||||
set => SetValue(SelectedColorProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
if ((_selector = GetTemplateChild("PART_Selector") as Panel) != null)
|
||||
{
|
||||
_selectorBrush = new SolidColorBrush();
|
||||
_selectorColor = new Rectangle
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
SnapsToDevicePixels = true,
|
||||
StrokeThickness = 0,
|
||||
Fill = _selectorBrush
|
||||
};
|
||||
_selector.Children.Add(_selectorColor);
|
||||
|
||||
Rectangle selectorWhite = new Rectangle
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
SnapsToDevicePixels = true,
|
||||
StrokeThickness = 0,
|
||||
Fill = new LinearGradientBrush(WpfColor.FromRgb(255, 255, 255), WpfColor.FromArgb(0, 255, 255, 255), new Point(0, 0.5), new Point(1, 0.5))
|
||||
};
|
||||
_selector.Children.Add(selectorWhite);
|
||||
|
||||
Rectangle selectorBlack = new Rectangle
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
SnapsToDevicePixels = true,
|
||||
StrokeThickness = 0,
|
||||
Fill = new LinearGradientBrush(WpfColor.FromRgb(0, 0, 0), WpfColor.FromArgb(0, 0, 0, 0), new Point(0.5, 1), new Point(0.5, 0))
|
||||
};
|
||||
_selector.Children.Add(selectorBlack);
|
||||
|
||||
_selectorGrip = new Grid
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Bottom,
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
SnapsToDevicePixels = true
|
||||
};
|
||||
_selectorGrip.Children.Add(new Ellipse
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
SnapsToDevicePixels = true,
|
||||
Stroke = new SolidColorBrush(WpfColor.FromRgb(0, 0, 0)),
|
||||
StrokeThickness = 2,
|
||||
Fill = null,
|
||||
Width = 12,
|
||||
Height = 12
|
||||
});
|
||||
_selectorGrip.Children.Add(new Ellipse
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
SnapsToDevicePixels = true,
|
||||
Stroke = new SolidColorBrush(WpfColor.FromRgb(255, 255, 255)),
|
||||
StrokeThickness = 1,
|
||||
Fill = null,
|
||||
Width = 10,
|
||||
Height = 10
|
||||
});
|
||||
_selector.Children.Add(_selectorGrip);
|
||||
|
||||
_selector.SizeChanged += (sender, args) => UpdateSelector();
|
||||
_selector.MouseLeftButtonDown += (sender, args) =>
|
||||
{
|
||||
_dragSelector = true;
|
||||
UpdateSelectorValue(args.GetPosition(_selector));
|
||||
};
|
||||
_selector.MouseEnter += (sender, args) =>
|
||||
{
|
||||
if (args.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
_dragSelector = true;
|
||||
UpdateSelectorValue(args.GetPosition(_selector));
|
||||
}
|
||||
};
|
||||
_selector.MouseLeftButtonUp += (sender, args) => _dragSelector = false;
|
||||
_selector.MouseLeave += (sender, args) => _dragSelector = false;
|
||||
_selector.MouseMove += (sender, args) => UpdateSelectorValue(args.GetPosition(_selector));
|
||||
_selector.ClipToBounds = true;
|
||||
}
|
||||
|
||||
if ((_sliderAlpha = GetTemplateChild("PART_SliderAlpha") as Slider) != null)
|
||||
{
|
||||
_alphaBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderAlpha.Background = _alphaBrush;
|
||||
_sliderAlpha.ValueChanged += AChanged;
|
||||
}
|
||||
|
||||
if ((_sliderRed = GetTemplateChild("PART_SliderRed") as Slider) != null)
|
||||
{
|
||||
_redBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderRed.Background = _redBrush;
|
||||
_sliderRed.ValueChanged += RChanged;
|
||||
}
|
||||
|
||||
if ((_sliderGreen = GetTemplateChild("PART_SliderGreen") as Slider) != null)
|
||||
{
|
||||
_greenBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderGreen.Background = _greenBrush;
|
||||
_sliderGreen.ValueChanged += GChanged;
|
||||
}
|
||||
|
||||
if ((_sliderBlue = GetTemplateChild("PART_SliderBlue") as Slider) != null)
|
||||
{
|
||||
_blueBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderBlue.Background = _blueBrush;
|
||||
_sliderBlue.ValueChanged += BChanged;
|
||||
}
|
||||
|
||||
if ((_sliderHue = GetTemplateChild("PART_SliderHue") as Slider) != null)
|
||||
{
|
||||
_hueBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1.0 / 6.0),
|
||||
new GradientStop(new WpfColor(), 2.0 / 6.0),
|
||||
new GradientStop(new WpfColor(), 3.0 / 6.0),
|
||||
new GradientStop(new WpfColor(), 4.0 / 6.0),
|
||||
new GradientStop(new WpfColor(), 5.0 / 6.0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderHue.Background = _hueBrush;
|
||||
_sliderHue.ValueChanged += HueChanged;
|
||||
}
|
||||
|
||||
if ((_sliderSaturation = GetTemplateChild("PART_SliderSaturation") as Slider) != null)
|
||||
{
|
||||
_saturationBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderSaturation.Background = _saturationBrush;
|
||||
_sliderSaturation.ValueChanged += SaturationChanged;
|
||||
}
|
||||
|
||||
if ((_sliderValue = GetTemplateChild("PART_SliderValue") as Slider) != null)
|
||||
{
|
||||
_valueBrush = new LinearGradientBrush(new GradientStopCollection(new[] { new GradientStop(new WpfColor(), 0),
|
||||
new GradientStop(new WpfColor(), 1) }));
|
||||
_sliderValue.Background = _valueBrush;
|
||||
_sliderValue.ValueChanged += ValueChanged;
|
||||
}
|
||||
|
||||
if ((_preview = GetTemplateChild("PART_Preview") as Rectangle) != null)
|
||||
{
|
||||
_previewBrush = new SolidColorBrush();
|
||||
_preview.Fill = _previewBrush;
|
||||
}
|
||||
|
||||
SetColor(SelectedColor);
|
||||
}
|
||||
|
||||
private static void SelectedColorChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is ColorSelector cs) || !(dependencyPropertyChangedEventArgs.NewValue is Color color)) return;
|
||||
cs.SetColor(color);
|
||||
}
|
||||
|
||||
private void SetColor(Color color)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
SetA(color);
|
||||
SetRGB(color);
|
||||
SetHSV(color);
|
||||
|
||||
UpdateSelector();
|
||||
UpdateUIColors();
|
||||
}
|
||||
|
||||
private void AChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_a = (byte)routedPropertyChangedEventArgs.NewValue.Clamp(0, byte.MaxValue);
|
||||
Color color = new Color(_a, _r, _g, _b);
|
||||
UpdateSelectedColor(color);
|
||||
UpdateUIColors();
|
||||
UpdateSelector();
|
||||
}
|
||||
|
||||
private void RChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_r = (byte)routedPropertyChangedEventArgs.NewValue.Clamp(0, byte.MaxValue);
|
||||
RGBChanged();
|
||||
}
|
||||
|
||||
private void GChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_g = (byte)routedPropertyChangedEventArgs.NewValue.Clamp(0, byte.MaxValue);
|
||||
RGBChanged();
|
||||
}
|
||||
|
||||
private void BChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_b = (byte)routedPropertyChangedEventArgs.NewValue.Clamp(0, byte.MaxValue);
|
||||
RGBChanged();
|
||||
}
|
||||
|
||||
private void RGBChanged()
|
||||
{
|
||||
Color color = new Color(_a, _r, _g, _b);
|
||||
UpdateSelectedColor(color);
|
||||
SetHSV(color);
|
||||
UpdateUIColors();
|
||||
UpdateSelector();
|
||||
}
|
||||
|
||||
private void HueChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_hue = routedPropertyChangedEventArgs.NewValue.Clamp(0, 360);
|
||||
HSVChanged();
|
||||
}
|
||||
|
||||
private void SaturationChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_saturation = routedPropertyChangedEventArgs.NewValue.Clamp(0, 1);
|
||||
HSVChanged();
|
||||
}
|
||||
|
||||
private void ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
|
||||
{
|
||||
if (_ignorePropertyChanged) return;
|
||||
|
||||
_value = routedPropertyChangedEventArgs.NewValue.Clamp(0, 1);
|
||||
HSVChanged();
|
||||
}
|
||||
|
||||
private void HSVChanged()
|
||||
{
|
||||
Color color = HSVColor.Create(_a, _hue, _saturation, _value);
|
||||
UpdateSelectedColor(color);
|
||||
SetRGB(color);
|
||||
UpdateUIColors();
|
||||
UpdateSelector();
|
||||
}
|
||||
|
||||
private void SetA(Color color)
|
||||
{
|
||||
_ignorePropertyChanged = true;
|
||||
|
||||
_a = color.GetA();
|
||||
if (_sliderAlpha != null)
|
||||
_sliderAlpha.Value = _a;
|
||||
|
||||
_ignorePropertyChanged = false;
|
||||
}
|
||||
|
||||
private void SetRGB(Color color)
|
||||
{
|
||||
_ignorePropertyChanged = true;
|
||||
|
||||
_r = color.GetR();
|
||||
if (_sliderRed != null)
|
||||
_sliderRed.Value = _r;
|
||||
|
||||
_g = color.GetG();
|
||||
if (_sliderGreen != null)
|
||||
_sliderGreen.Value = _g;
|
||||
|
||||
_b = color.GetB();
|
||||
if (_sliderBlue != null)
|
||||
_sliderBlue.Value = _b;
|
||||
|
||||
_ignorePropertyChanged = false;
|
||||
}
|
||||
|
||||
private void SetHSV(Color color)
|
||||
{
|
||||
_ignorePropertyChanged = true;
|
||||
|
||||
_hue = color.GetHue();
|
||||
if (_sliderHue != null)
|
||||
_sliderHue.Value = _hue;
|
||||
|
||||
_saturation = color.GetSaturation();
|
||||
if (_sliderSaturation != null)
|
||||
_sliderSaturation.Value = _saturation;
|
||||
|
||||
_value = color.GetValue();
|
||||
if (_sliderValue != null)
|
||||
_sliderValue.Value = _value;
|
||||
|
||||
_ignorePropertyChanged = false;
|
||||
}
|
||||
|
||||
private void UpdateSelectedColor(Color color)
|
||||
{
|
||||
_ignorePropertyChanged = true;
|
||||
|
||||
SelectedColor = color;
|
||||
|
||||
_ignorePropertyChanged = false;
|
||||
}
|
||||
|
||||
private void UpdateSelector()
|
||||
{
|
||||
if (_selector == null) return;
|
||||
|
||||
double selectorX = (_selector.ActualWidth * _saturation) - (_selectorGrip.ActualWidth / 2);
|
||||
double selectorY = (_selector.ActualHeight * _value) - (_selectorGrip.ActualHeight / 2);
|
||||
if (!double.IsNaN(selectorX) && !double.IsNaN(selectorY))
|
||||
_selectorGrip.Margin = new Thickness(selectorX, 0, 0, selectorY);
|
||||
}
|
||||
|
||||
private void UpdateSelectorValue(Point mouseLocation)
|
||||
{
|
||||
if (!_dragSelector) return;
|
||||
|
||||
double saturation = mouseLocation.X / _selector.ActualWidth;
|
||||
double value = 1 - (mouseLocation.Y / _selector.ActualHeight);
|
||||
if (!double.IsNaN(saturation) && !double.IsNaN(value))
|
||||
{
|
||||
_saturation = saturation;
|
||||
_value = value;
|
||||
HSVChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUIColors()
|
||||
{
|
||||
Color hueColor = HSVColor.Create(_hue, 1, 1);
|
||||
|
||||
if (_previewBrush != null)
|
||||
_previewBrush.Color = WpfColor.FromArgb(_a, _r, _g, _b);
|
||||
|
||||
if (_selectorBrush != null)
|
||||
_selectorBrush.Color = WpfColor.FromRgb(hueColor.GetR(), hueColor.GetG(), hueColor.GetB());
|
||||
|
||||
if (_alphaBrush != null)
|
||||
{
|
||||
_alphaBrush.GradientStops[0].Color = WpfColor.FromArgb(0, _r, _g, _b);
|
||||
_alphaBrush.GradientStops[1].Color = WpfColor.FromArgb(255, _r, _g, _b);
|
||||
}
|
||||
|
||||
if (_redBrush != null)
|
||||
{
|
||||
_redBrush.GradientStops[0].Color = WpfColor.FromArgb(_a, 0, _g, _b);
|
||||
_redBrush.GradientStops[1].Color = WpfColor.FromArgb(_a, 255, _g, _b);
|
||||
}
|
||||
|
||||
if (_greenBrush != null)
|
||||
{
|
||||
_greenBrush.GradientStops[0].Color = WpfColor.FromArgb(_a, _r, 0, _b);
|
||||
_greenBrush.GradientStops[1].Color = WpfColor.FromArgb(_a, _r, 255, _b);
|
||||
}
|
||||
|
||||
if (_blueBrush != null)
|
||||
{
|
||||
_blueBrush.GradientStops[0].Color = WpfColor.FromArgb(_a, _r, _g, 0);
|
||||
_blueBrush.GradientStops[1].Color = WpfColor.FromArgb(_a, _r, _g, 255);
|
||||
}
|
||||
|
||||
if (_hueBrush != null)
|
||||
{
|
||||
Color referenceColor1 = HSVColor.Create(0, _saturation, _value);
|
||||
Color referenceColor2 = HSVColor.Create(60, _saturation, _value);
|
||||
Color referenceColor3 = HSVColor.Create(120, _saturation, _value);
|
||||
Color referenceColor4 = HSVColor.Create(180, _saturation, _value);
|
||||
Color referenceColor5 = HSVColor.Create(240, _saturation, _value);
|
||||
Color referenceColor6 = HSVColor.Create(300, _saturation, _value);
|
||||
|
||||
_hueBrush.GradientStops[0].Color = WpfColor.FromArgb(_a, referenceColor1.GetR(), referenceColor1.GetG(), referenceColor1.GetB());
|
||||
_hueBrush.GradientStops[1].Color = WpfColor.FromArgb(_a, referenceColor2.GetR(), referenceColor2.GetG(), referenceColor2.GetB());
|
||||
_hueBrush.GradientStops[2].Color = WpfColor.FromArgb(_a, referenceColor3.GetR(), referenceColor3.GetG(), referenceColor3.GetB());
|
||||
_hueBrush.GradientStops[3].Color = WpfColor.FromArgb(_a, referenceColor4.GetR(), referenceColor4.GetG(), referenceColor4.GetB());
|
||||
_hueBrush.GradientStops[4].Color = WpfColor.FromArgb(_a, referenceColor5.GetR(), referenceColor5.GetG(), referenceColor5.GetB());
|
||||
_hueBrush.GradientStops[5].Color = WpfColor.FromArgb(_a, referenceColor6.GetR(), referenceColor6.GetG(), referenceColor6.GetB());
|
||||
_hueBrush.GradientStops[6].Color = WpfColor.FromArgb(_a, referenceColor1.GetR(), referenceColor1.GetG(), referenceColor1.GetB());
|
||||
}
|
||||
|
||||
if (_saturationBrush != null)
|
||||
{
|
||||
Color referenceColor = HSVColor.Create(_hue, 1, _value);
|
||||
|
||||
_saturationBrush.GradientStops[0].Color = WpfColor.FromArgb(_a, 255, 255, 255);
|
||||
_saturationBrush.GradientStops[1].Color = WpfColor.FromArgb(_a, referenceColor.GetR(), referenceColor.GetG(), referenceColor.GetB());
|
||||
}
|
||||
|
||||
if (_valueBrush != null)
|
||||
{
|
||||
Color referenceColor = HSVColor.Create(_hue, _saturation, 1);
|
||||
|
||||
_valueBrush.GradientStops[0].Color = WpfColor.FromArgb(_a, 0, 0, 0);
|
||||
_valueBrush.GradientStops[1].Color = WpfColor.FromArgb(_a, referenceColor.GetR(), referenceColor.GetG(), referenceColor.GetB());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
424
KeyboardAudioVisualizer/Controls/GradientEditor.cs
Normal file
424
KeyboardAudioVisualizer/Controls/GradientEditor.cs
Normal file
@ -0,0 +1,424 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using Point = System.Windows.Point;
|
||||
using Size = System.Windows.Size;
|
||||
using Rectangle = System.Windows.Shapes.Rectangle;
|
||||
using GradientStop = RGB.NET.Brushes.Gradients.GradientStop;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Controls
|
||||
{
|
||||
[TemplatePart(Name = "PART_Gradient", Type = typeof(Canvas))]
|
||||
[TemplatePart(Name = "PART_Stops", Type = typeof(Canvas))]
|
||||
public class GradientEditor : Control
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private Canvas _gradientContainer;
|
||||
private Canvas _stopContainer;
|
||||
private readonly List<Rectangle> _previewRectangles = new List<Rectangle>();
|
||||
private readonly Dictionary<GradientStop, ContentControl> _stops = new Dictionary<GradientStop, ContentControl>();
|
||||
private ContentControl _draggingStop;
|
||||
private AdornerLayer _adornerLayer;
|
||||
private ColorPickerAdorner _adorner;
|
||||
private Window _window;
|
||||
|
||||
#endregion
|
||||
|
||||
#region DepdencyProperties
|
||||
|
||||
public static readonly DependencyProperty GradientProperty = DependencyProperty.Register(
|
||||
"Gradient", typeof(LinearGradient), typeof(GradientEditor), new FrameworkPropertyMetadata(null,
|
||||
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
|
||||
OnGradientChanged));
|
||||
|
||||
public LinearGradient Gradient
|
||||
{
|
||||
get => (LinearGradient)GetValue(GradientProperty);
|
||||
set => SetValue(GradientProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty GradientStopStyleProperty = DependencyProperty.Register(
|
||||
"GradientStopStyle", typeof(Style), typeof(GradientEditor), new PropertyMetadata(default(Style)));
|
||||
|
||||
public Style GradientStopStyle
|
||||
{
|
||||
get => (Style)GetValue(GradientStopStyleProperty);
|
||||
set => SetValue(GradientStopStyleProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SelectedStopProperty = DependencyProperty.Register(
|
||||
"SelectedStop", typeof(GradientStop), typeof(GradientEditor), new PropertyMetadata(default(GradientStop), SelectedStopChanged));
|
||||
|
||||
public GradientStop SelectedStop
|
||||
{
|
||||
get => (GradientStop)GetValue(SelectedStopProperty);
|
||||
set => SetValue(SelectedStopProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ColorSelectorTemplateProperty = DependencyProperty.Register(
|
||||
"ColorSelectorTemplate", typeof(DataTemplate), typeof(GradientEditor), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
public DataTemplate ColorSelectorTemplate
|
||||
{
|
||||
get => (DataTemplate)GetValue(ColorSelectorTemplateProperty);
|
||||
set => SetValue(ColorSelectorTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty CanAddOrDeleteStopsProperty = DependencyProperty.Register(
|
||||
"CanAddOrDeleteStops", typeof(bool), typeof(GradientEditor), new PropertyMetadata(true));
|
||||
|
||||
public bool CanAddOrDeleteStops
|
||||
{
|
||||
get => (bool)GetValue(CanAddOrDeleteStopsProperty);
|
||||
set => SetValue(CanAddOrDeleteStopsProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AttachedProperties
|
||||
|
||||
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.RegisterAttached(
|
||||
"IsSelected", typeof(bool), typeof(GradientEditor), new PropertyMetadata(default(bool)));
|
||||
|
||||
public static void SetIsSelected(DependencyObject element, bool value) => element.SetValue(IsSelectedProperty, value);
|
||||
public static bool GetIsSelected(DependencyObject element) => (bool)element.GetValue(IsSelectedProperty);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public GradientEditor()
|
||||
{
|
||||
if (Gradient == null)
|
||||
Gradient = new LinearGradient();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
if ((_gradientContainer = GetTemplateChild("PART_Gradient") as Canvas) != null)
|
||||
{
|
||||
_gradientContainer.SizeChanged += (sender, args) => UpdateGradientPreview();
|
||||
_gradientContainer.MouseDown += GradientContainerOnMouseDown;
|
||||
}
|
||||
|
||||
if ((_stopContainer = GetTemplateChild("PART_Stops") as Canvas) != null)
|
||||
_stopContainer.SizeChanged += (sender, args) => UpdateGradientStops();
|
||||
|
||||
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||
_window = Window.GetWindow(this);
|
||||
if (_window != null)
|
||||
{
|
||||
_window.PreviewMouseDown += WindowMouseDown;
|
||||
_window.PreviewKeyDown += (sender, args) =>
|
||||
{
|
||||
if (args.Key == Key.Escape)
|
||||
SelectedStop = null;
|
||||
};
|
||||
}
|
||||
|
||||
UpdateGradientPreview();
|
||||
UpdateGradientStops();
|
||||
}
|
||||
|
||||
private void UpdateGradientPreview()
|
||||
{
|
||||
if ((_gradientContainer == null) || (Gradient == null)) return;
|
||||
|
||||
List<GradientStop> gradientStops = Gradient.GradientStops.OrderBy(x => x.Offset).ToList();
|
||||
if (gradientStops.Count == 0)
|
||||
UpdatePreviewRectangleCount(gradientStops.Count);
|
||||
else if (gradientStops.Count == 1)
|
||||
{
|
||||
UpdatePreviewRectangleCount(gradientStops.Count);
|
||||
GradientStop firstStop = gradientStops[0];
|
||||
UpdatePreviewRectangle(_previewRectangles[0], _gradientContainer.ActualWidth, _gradientContainer.ActualHeight, 0, 1, firstStop.Color, firstStop.Color);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdatePreviewRectangleCount(gradientStops.Count + 1);
|
||||
|
||||
GradientStop firstStop = gradientStops[0];
|
||||
UpdatePreviewRectangle(_previewRectangles[0], _gradientContainer.ActualWidth, _gradientContainer.ActualHeight, 0, firstStop.Offset, firstStop.Color, firstStop.Color);
|
||||
for (int i = 0; i < (gradientStops.Count - 1); i++)
|
||||
{
|
||||
GradientStop stop = gradientStops[i];
|
||||
GradientStop nextStop = gradientStops[i + 1];
|
||||
Rectangle rect = _previewRectangles[i + 1];
|
||||
UpdatePreviewRectangle(rect, _gradientContainer.ActualWidth, _gradientContainer.ActualHeight, stop.Offset, nextStop.Offset, stop.Color, nextStop.Color);
|
||||
}
|
||||
GradientStop lastStop = gradientStops[gradientStops.Count - 1];
|
||||
UpdatePreviewRectangle(_previewRectangles[_previewRectangles.Count - 1], _gradientContainer.ActualWidth, _gradientContainer.ActualHeight, lastStop.Offset, 1, lastStop.Color, lastStop.Color);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePreviewRectangle(Rectangle rect, double referenceWidth, double referenceHeight, double from, double to,
|
||||
RGB.NET.Core.Color startColor, RGB.NET.Core.Color endColor)
|
||||
{
|
||||
rect.Fill = new LinearGradientBrush(Color.FromArgb(startColor.GetA(), startColor.GetR(), startColor.GetG(), startColor.GetB()),
|
||||
Color.FromArgb(endColor.GetA(), endColor.GetR(), endColor.GetG(), endColor.GetB()),
|
||||
new Point(0, 0.5), new Point(1, 0.5));
|
||||
|
||||
//DarthAffe 09.02.2018: Forced rounding to prevent render issues on resize
|
||||
Canvas.SetLeft(rect, Math.Floor(referenceWidth * from.Clamp(0, 1)));
|
||||
rect.Width = Math.Ceiling(referenceWidth * (to.Clamp(0, 1) - from.Clamp(0, 1)));
|
||||
|
||||
Canvas.SetTop(rect, 0);
|
||||
rect.Height = referenceHeight;
|
||||
}
|
||||
|
||||
private void UpdatePreviewRectangleCount(int gradientCount)
|
||||
{
|
||||
int countDiff = gradientCount - _previewRectangles.Count;
|
||||
if (countDiff > 0)
|
||||
for (int i = 0; i < countDiff; i++)
|
||||
{
|
||||
Rectangle rect = new Rectangle { VerticalAlignment = VerticalAlignment.Stretch };
|
||||
_previewRectangles.Add(rect);
|
||||
_gradientContainer.Children.Add(rect);
|
||||
}
|
||||
|
||||
if (countDiff < 0)
|
||||
for (int i = 0; i < Math.Abs(countDiff); i++)
|
||||
{
|
||||
int index = _previewRectangles.Count - i - 1;
|
||||
Rectangle rect = _previewRectangles[index];
|
||||
_previewRectangles.RemoveAt(index);
|
||||
_gradientContainer.Children.Remove(rect);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGradientStops()
|
||||
{
|
||||
if (Gradient == null) return;
|
||||
|
||||
List<GradientStop> gradientStops = Gradient.GradientStops.OrderBy(x => x.Offset).ToList();
|
||||
UpdateGradientStopsCount(gradientStops);
|
||||
foreach (GradientStop stop in gradientStops)
|
||||
UpdateGradientStop(_stops[stop], _stopContainer.ActualWidth, _stopContainer.ActualHeight, stop);
|
||||
}
|
||||
|
||||
private void UpdateGradientStop(ContentControl control, double referenceWidth, double referenceHeight, GradientStop stop)
|
||||
{
|
||||
control.Background = new SolidColorBrush(Color.FromArgb(stop.Color.GetA(), stop.Color.GetR(), stop.Color.GetG(), stop.Color.GetB()));
|
||||
|
||||
Canvas.SetLeft(control, (referenceWidth * stop.Offset.Clamp(0, 1)) - (control.Width / 2.0));
|
||||
|
||||
Canvas.SetTop(control, 0);
|
||||
control.Height = referenceHeight;
|
||||
}
|
||||
|
||||
private void UpdateGradientStopsCount(List<GradientStop> gradientStops)
|
||||
{
|
||||
foreach (GradientStop stop in gradientStops)
|
||||
{
|
||||
if (!_stops.ContainsKey(stop))
|
||||
{
|
||||
ContentControl control = new ContentControl
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
Style = GradientStopStyle,
|
||||
Content = stop
|
||||
};
|
||||
control.MouseDown += GradientStopOnMouseDown;
|
||||
_stops.Add(stop, control);
|
||||
_stopContainer.Children.Add(control);
|
||||
}
|
||||
}
|
||||
|
||||
List<GradientStop> stopsToRemove = new List<GradientStop>();
|
||||
foreach (KeyValuePair<GradientStop, ContentControl> stopPair in _stops)
|
||||
if (!gradientStops.Contains(stopPair.Key))
|
||||
{
|
||||
ContentControl control = stopPair.Value;
|
||||
control.MouseDown -= GradientStopOnMouseDown;
|
||||
stopsToRemove.Add(stopPair.Key);
|
||||
_stopContainer.Children.Remove(control);
|
||||
}
|
||||
|
||||
foreach (GradientStop stop in stopsToRemove)
|
||||
_stops.Remove(stop);
|
||||
}
|
||||
|
||||
private void AttachGradient(AbstractGradient gradient) => gradient.GradientChanged += GradientChanged;
|
||||
private void DetachGradient(AbstractGradient gradient) => gradient.GradientChanged -= GradientChanged;
|
||||
|
||||
private void GradientChanged(object o, EventArgs eventArgs)
|
||||
{
|
||||
UpdateGradientPreview();
|
||||
UpdateGradientStops();
|
||||
}
|
||||
|
||||
private static void OnGradientChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is GradientEditor ge)) return;
|
||||
|
||||
if (dependencyPropertyChangedEventArgs.OldValue is AbstractGradient oldGradient)
|
||||
ge.DetachGradient(oldGradient);
|
||||
|
||||
if (dependencyPropertyChangedEventArgs.NewValue is AbstractGradient newGradient)
|
||||
ge.AttachGradient(newGradient);
|
||||
}
|
||||
|
||||
private void GradientContainerOnMouseDown(object o, MouseButtonEventArgs mouseButtonEventArgs)
|
||||
{
|
||||
if ((mouseButtonEventArgs.ChangedButton != MouseButton.Left) || (Gradient == null) || !CanAddOrDeleteStops) return;
|
||||
|
||||
double offset = mouseButtonEventArgs.GetPosition(_gradientContainer).X / _gradientContainer.ActualWidth;
|
||||
RGB.NET.Core.Color color = Gradient.GetColor(offset);
|
||||
GradientStop newStop = new GradientStop(offset, color);
|
||||
Gradient.GradientStops.Add(newStop);
|
||||
SelectedStop = newStop;
|
||||
}
|
||||
|
||||
private void GradientStopOnMouseDown(object o, MouseButtonEventArgs mouseButtonEventArgs)
|
||||
{
|
||||
if (!((o as ContentControl)?.Content is GradientStop stop) || (Gradient == null)) return;
|
||||
|
||||
if (mouseButtonEventArgs.ChangedButton == MouseButton.Right)
|
||||
{
|
||||
if (CanAddOrDeleteStops)
|
||||
Gradient.GradientStops.Remove(stop);
|
||||
}
|
||||
else if (mouseButtonEventArgs.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
SelectedStop = stop;
|
||||
_draggingStop = (ContentControl)o;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
if (_draggingStop?.Content is GradientStop stop)
|
||||
{
|
||||
double location = e.GetPosition(_gradientContainer).X;
|
||||
stop.Offset = (location / _gradientContainer.ActualWidth).Clamp(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
_draggingStop = null;
|
||||
}
|
||||
|
||||
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
|
||||
{
|
||||
base.OnMouseLeftButtonUp(e);
|
||||
|
||||
_draggingStop = null;
|
||||
}
|
||||
|
||||
private static void SelectedStopChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is GradientEditor gradientEditor)) return;
|
||||
|
||||
if (gradientEditor._adorner != null)
|
||||
gradientEditor._adornerLayer.Remove(gradientEditor._adorner);
|
||||
|
||||
if (dependencyPropertyChangedEventArgs.OldValue is GradientStop oldStop)
|
||||
{
|
||||
if (gradientEditor._stops.TryGetValue(oldStop, out ContentControl oldcontrol))
|
||||
SetIsSelected(oldcontrol, false);
|
||||
}
|
||||
|
||||
if (dependencyPropertyChangedEventArgs.NewValue is GradientStop stop)
|
||||
{
|
||||
ContentControl stopContainer = gradientEditor._stops[stop];
|
||||
SetIsSelected(stopContainer, true);
|
||||
|
||||
if (gradientEditor._adornerLayer != null)
|
||||
{
|
||||
ContentControl contentControl = new ContentControl
|
||||
{
|
||||
ContentTemplate = gradientEditor.ColorSelectorTemplate,
|
||||
Content = stop
|
||||
};
|
||||
|
||||
ColorPickerAdorner adorner = new ColorPickerAdorner(stopContainer, contentControl);
|
||||
gradientEditor._adorner = adorner;
|
||||
gradientEditor._adornerLayer.Add(adorner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WindowMouseDown(object o, MouseButtonEventArgs mouseButtonEventArgs)
|
||||
{
|
||||
if ((_adorner != null) && (VisualTreeHelper.HitTest(_adorner, mouseButtonEventArgs.GetPosition(_adorner)) == null))
|
||||
SelectedStop = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class ColorPickerAdorner : Adorner
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly VisualCollection _visualChildren;
|
||||
private readonly FrameworkElement _colorSelector;
|
||||
protected override int VisualChildrenCount => 1;
|
||||
protected override Visual GetVisualChild(int index) => _colorSelector;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ColorPickerAdorner(UIElement adornedElement, FrameworkElement colorSelector)
|
||||
: base(adornedElement)
|
||||
{
|
||||
this._colorSelector = colorSelector;
|
||||
|
||||
_visualChildren = new VisualCollection(this) { colorSelector };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
Window referenceWindow = Window.GetWindow(AdornedElement);
|
||||
Point referenceLocation = AdornedElement.TranslatePoint(new Point(0, 0), referenceWindow);
|
||||
|
||||
double referenceWidth = ((FrameworkElement)AdornedElement).ActualWidth / 2.0;
|
||||
double referenceHeight = ((FrameworkElement)AdornedElement).Height;
|
||||
double referenceX = referenceLocation.X + referenceWidth;
|
||||
double halfWidth = finalSize.Width / 2.0;
|
||||
double maxOffset = referenceWindow.Width - halfWidth;
|
||||
|
||||
double offset = (referenceX < halfWidth ? referenceX
|
||||
: (((referenceX + (referenceWidth * 2)) > maxOffset)
|
||||
? halfWidth - ((maxOffset - referenceX) - (referenceWidth * 2))
|
||||
: halfWidth));
|
||||
|
||||
_colorSelector.Arrange(new Rect(new Point(referenceWidth - offset, referenceHeight), finalSize));
|
||||
return _colorSelector.RenderSize;
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
_colorSelector.Measure(constraint);
|
||||
return _colorSelector.DesiredSize;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -24,11 +24,8 @@ namespace KeyboardAudioVisualizer.Decorators
|
||||
|
||||
protected override void Update(double deltaTime) => _visualizationProvider.Update();
|
||||
|
||||
public void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color)
|
||||
{
|
||||
color.APercent *= _visualizationProvider.VisualizationData[0];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetA(color.A * _visualizationProvider.VisualizationData[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,14 +27,13 @@ namespace KeyboardAudioVisualizer.Decorators
|
||||
|
||||
protected override void Update(double deltaTime) => _visualizationProvider.Update();
|
||||
|
||||
public void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color)
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)
|
||||
{
|
||||
int barSampleIndex = Math.Min(_visualizationProvider.VisualizationData.Length, (int)Math.Floor(_visualizationProvider.VisualizationData.Length * (renderTarget.Point.X / (rectangle.Location.X + rectangle.Size.Width))));
|
||||
double curBarHeight = 1.0 - Math.Max(0f, _visualizationProvider.VisualizationData[barSampleIndex]);
|
||||
double verticalPos = (renderTarget.Point.Y / rectangle.Size.Height);
|
||||
|
||||
if (curBarHeight > verticalPos)
|
||||
color.A = 0;
|
||||
return curBarHeight > verticalPos ? color.SetA(0) : color;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Decorators
|
||||
@ -10,16 +11,18 @@ namespace KeyboardAudioVisualizer.Decorators
|
||||
private readonly IVisualizationProvider _visualizationProvider;
|
||||
public LevelBarDirection Direction { get; set; }
|
||||
public int DataIndex { get; set; }
|
||||
public LinearGradient Gradient { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public LevelBarDecorator(IVisualizationProvider visualizationProvider, LevelBarDirection direction, int dataIndex)
|
||||
public LevelBarDecorator(IVisualizationProvider visualizationProvider, LevelBarDirection direction, int dataIndex, LinearGradient gradient)
|
||||
{
|
||||
this._visualizationProvider = visualizationProvider;
|
||||
this.Direction = direction;
|
||||
this.DataIndex = dataIndex;
|
||||
this.Gradient = gradient;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -28,30 +31,37 @@ namespace KeyboardAudioVisualizer.Decorators
|
||||
|
||||
protected override void Update(double deltaTime) => _visualizationProvider.Update();
|
||||
|
||||
public void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color)
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)
|
||||
{
|
||||
double offset = CalculateOffset(rectangle, renderTarget);
|
||||
|
||||
if (Direction == LevelBarDirection.Horizontal)
|
||||
{
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
offset = (-offset * 2);
|
||||
if (offset >= _visualizationProvider.VisualizationData[0])
|
||||
color.A = 0;
|
||||
return color.SetA(0);
|
||||
else
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset *= 2;
|
||||
if (offset >= _visualizationProvider.VisualizationData[1])
|
||||
color.A = 0;
|
||||
return color.SetA(0);
|
||||
else
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset >= _visualizationProvider.VisualizationData[DataIndex])
|
||||
color.A = 0;
|
||||
return color.SetA(0);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
private double CalculateOffset(Rectangle rectangle, BrushRenderTarget renderTarget)
|
||||
|
||||
68
KeyboardAudioVisualizer/Helper/RingBuffer.cs
Normal file
68
KeyboardAudioVisualizer/Helper/RingBuffer.cs
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
@ -41,51 +41,69 @@
|
||||
<ApplicationIcon>Resources\Icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="CSCore, Version=1.2.1.1, Culture=neutral, PublicKeyToken=5a08f2b6f4415dea, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CSCore.1.2.1.1\lib\net35-client\CSCore.dll</HintPath>
|
||||
<Reference Include="CSCore, Version=1.2.1.2, Culture=neutral, PublicKeyToken=5a08f2b6f4415dea, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CSCore.1.2.1.2\lib\net35-client\CSCore.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Hardcodet.Wpf.TaskbarNotification, Version=1.0.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Hardcodet.NotifyIcon.Wpf.1.0.8\lib\net451\Hardcodet.Wpf.TaskbarNotification.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MathNet.Numerics, Version=3.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MathNet.Numerics.3.20.0\lib\net40\MathNet.Numerics.dll</HintPath>
|
||||
<Reference Include="HidSharp, Version=2.0.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HidSharp.2.0.5\lib\net35\HidSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Interop.AuraServiceLib, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Asus.0.1.31\lib\net45\Interop.AuraServiceLib.dll</HintPath>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Brushes">
|
||||
<HintPath>..\packages\RGB.NET.Brushes.1.0.0\lib\net45\RGB.NET.Brushes.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="MathNet.Numerics, Version=4.7.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MathNet.Numerics.4.7.0\lib\net461\MathNet.Numerics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Core">
|
||||
<HintPath>..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.CoolerMaster">
|
||||
<HintPath>..\packages\RGB.NET.Devices.CoolerMaster.1.0.0\lib\net45\RGB.NET.Devices.CoolerMaster.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="RGB.NET.Brushes, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Brushes.0.1.31\lib\net45\RGB.NET.Brushes.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.Corsair, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Corsair.1.0.0\lib\net45\RGB.NET.Devices.Corsair.dll</HintPath>
|
||||
<Reference Include="RGB.NET.Core, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Core.0.1.31\lib\net45\RGB.NET.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.Logitech, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Logitech.1.0.0\lib\net45\RGB.NET.Devices.Logitech.dll</HintPath>
|
||||
<Reference Include="RGB.NET.Decorators, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Decorators.0.1.31\lib\net45\RGB.NET.Decorators.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.Novation, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Novation.1.0.0\lib\net45\RGB.NET.Devices.Novation.dll</HintPath>
|
||||
<Reference Include="RGB.NET.Devices.Asus, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Asus.0.1.31\lib\net45\RGB.NET.Devices.Asus.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Groups, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Groups.1.0.0\lib\net45\RGB.NET.Groups.dll</HintPath>
|
||||
<Reference Include="RGB.NET.Devices.CoolerMaster, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.CoolerMaster.0.1.31\lib\net45\RGB.NET.Devices.CoolerMaster.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Sanford.Multimedia.Midi, Version=6.4.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Sanford.Multimedia.Midi.6.4.1\lib\net20\Sanford.Multimedia.Midi.dll</HintPath>
|
||||
<Reference Include="RGB.NET.Devices.Corsair, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Corsair.0.1.31\lib\net45\RGB.NET.Devices.Corsair.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.Logitech, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Logitech.0.1.31\lib\net45\RGB.NET.Devices.Logitech.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.Novation, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Novation.0.1.31\lib\net45\RGB.NET.Devices.Novation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.Razer, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.Razer.0.1.31\lib\net45\RGB.NET.Devices.Razer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Devices.SteelSeries, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Devices.SteelSeries.0.1.31\lib\netstandard2.0\RGB.NET.Devices.SteelSeries.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Groups, Version=0.1.31.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RGB.NET.Groups.0.1.31\lib\net45\RGB.NET.Groups.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Sanford.Multimedia.Midi, Version=6.6.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Sanford.Multimedia.Midi.6.6.0\lib\net20\Sanford.Multimedia.Midi.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll</HintPath>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@ -140,6 +158,9 @@
|
||||
<Compile Include="AudioProcessing\VisualizationProvider\LevelVisualizationProvider.cs" />
|
||||
<Compile Include="AudioProcessing\Spectrum\RawSpectrumProvider.cs" />
|
||||
<Compile Include="AudioProcessing\VisualizationProvider\VisualizationType.cs" />
|
||||
<Compile Include="Configuration\ColorSerializer.cs" />
|
||||
<Compile Include="Controls\ColorSelector.cs" />
|
||||
<Compile Include="Controls\GradientEditor.cs" />
|
||||
<Compile Include="Converter\VisualizationProviderDisplayNameConverter.cs" />
|
||||
<Compile Include="Converter\VisualizationToLastChildFillConverter.cs" />
|
||||
<Compile Include="Converter\VisualizationTypeSelectableConverter.cs" />
|
||||
@ -149,7 +170,7 @@
|
||||
<Compile Include="Configuration\AbstractConfiguration.cs" />
|
||||
<Compile Include="Configuration\EqualizerConfiguration.cs" />
|
||||
<Compile Include="Configuration\IConfiguration.cs" />
|
||||
<Compile Include="Controls\Formular.cs" />
|
||||
<Compile Include="Controls\Form.cs" />
|
||||
<Compile Include="Controls\ImageButton.cs" />
|
||||
<Compile Include="Converter\BoolToVisibilityConverter.cs" />
|
||||
<Compile Include="Converter\EqualizerBandsToPointsConverter.cs" />
|
||||
@ -162,11 +183,13 @@
|
||||
<Compile Include="Helper\FrequencyHelper.cs" />
|
||||
<Compile Include="Helper\MathHelper.cs" />
|
||||
<Compile Include="Helper\ObservableDictionary.cs" />
|
||||
<Compile Include="Helper\RingBuffer.cs" />
|
||||
<Compile Include="Helper\VisualizationIndex.cs" />
|
||||
<Compile Include="Helper\WPFHelper.cs" />
|
||||
<Compile Include="Configuration\Settings.cs" />
|
||||
<Compile Include="Controls\BlurredDecorationWindow.cs" />
|
||||
<Compile Include="Legacy\ConfigurationMigrator.cs" />
|
||||
<Compile Include="Legacy\ConfigurationUpdates.cs" />
|
||||
<Compile Include="Legacy\Settings.cs" />
|
||||
<Compile Include="Styles\CachedResourceDictionary.cs" />
|
||||
<Compile Include="UI\ConfigurationWindow.xaml.cs">
|
||||
@ -198,7 +221,6 @@
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<None Include="NuGet.Config" />
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
@ -224,6 +246,10 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles\ColorSelector.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles\FrameworkElement.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -236,6 +262,10 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles\GradientEditor.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles\Slider.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -256,7 +286,7 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles\Formular.xaml">
|
||||
<Page Include="Styles\Form.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
@ -304,15 +334,21 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\packages\RGB.NET.Devices.Corsair.1.0.0\build\net45\RGB.NET.Devices.Corsair.targets" Condition="Exists('..\packages\RGB.NET.Devices.Corsair.1.0.0\build\net45\RGB.NET.Devices.Corsair.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Devices.Corsair.1.0.0\build\net45\RGB.NET.Devices.Corsair.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Devices.Corsair.1.0.0\build\net45\RGB.NET.Devices.Corsair.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Devices.CoolerMaster.1.0.0\build\net45\RGB.NET.Devices.CoolerMaster.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Devices.CoolerMaster.1.0.0\build\net45\RGB.NET.Devices.CoolerMaster.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Devices.Logitech.1.0.0\build\net45\RGB.NET.Devices.Logitech.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Devices.Logitech.1.0.0\build\net45\RGB.NET.Devices.Logitech.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Resources.Novation.0.1.0\build\RGB.NET.Resources.Novation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Resources.Novation.0.1.0\build\RGB.NET.Resources.Novation.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Resources.CoolerMaster.0.2.0\build\RGB.NET.Resources.CoolerMaster.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Resources.CoolerMaster.0.2.0\build\RGB.NET.Resources.CoolerMaster.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Resources.Corsair.0.3.0.234\build\RGB.NET.Resources.Corsair.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Resources.Corsair.0.3.0.234\build\RGB.NET.Resources.Corsair.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Resources.Logitech.0.3.0\build\RGB.NET.Resources.Logitech.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Resources.Logitech.0.3.0\build\RGB.NET.Resources.Logitech.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Resources.Razer.0.3.2.4\build\RGB.NET.Resources.Razer.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Resources.Razer.0.3.2.4\build\RGB.NET.Resources.Razer.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\RGB.NET.Resources.Asus.0.3.0\build\RGB.NET.Resources.Asus.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RGB.NET.Resources.Asus.0.3.0\build\RGB.NET.Resources.Asus.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\RGB.NET.Devices.CoolerMaster.1.0.0\build\net45\RGB.NET.Devices.CoolerMaster.targets" Condition="Exists('..\packages\RGB.NET.Devices.CoolerMaster.1.0.0\build\net45\RGB.NET.Devices.CoolerMaster.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Devices.Logitech.1.0.0\build\net45\RGB.NET.Devices.Logitech.targets" Condition="Exists('..\packages\RGB.NET.Devices.Logitech.1.0.0\build\net45\RGB.NET.Devices.Logitech.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Resources.Novation.0.1.0\build\RGB.NET.Resources.Novation.targets" Condition="Exists('..\packages\RGB.NET.Resources.Novation.0.1.0\build\RGB.NET.Resources.Novation.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Resources.CoolerMaster.0.2.0\build\RGB.NET.Resources.CoolerMaster.targets" Condition="Exists('..\packages\RGB.NET.Resources.CoolerMaster.0.2.0\build\RGB.NET.Resources.CoolerMaster.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Resources.Corsair.0.3.0.234\build\RGB.NET.Resources.Corsair.targets" Condition="Exists('..\packages\RGB.NET.Resources.Corsair.0.3.0.234\build\RGB.NET.Resources.Corsair.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Resources.Logitech.0.3.0\build\RGB.NET.Resources.Logitech.targets" Condition="Exists('..\packages\RGB.NET.Resources.Logitech.0.3.0\build\RGB.NET.Resources.Logitech.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Resources.Razer.0.3.2.4\build\RGB.NET.Resources.Razer.targets" Condition="Exists('..\packages\RGB.NET.Resources.Razer.0.3.2.4\build\RGB.NET.Resources.Razer.targets')" />
|
||||
<Import Project="..\packages\RGB.NET.Resources.Asus.0.3.0\build\RGB.NET.Resources.Asus.targets" Condition="Exists('..\packages\RGB.NET.Resources.Asus.0.3.0\build\RGB.NET.Resources.Asus.targets')" />
|
||||
</Project>
|
||||
37
KeyboardAudioVisualizer/Legacy/ConfigurationUpdates.cs
Normal file
37
KeyboardAudioVisualizer/Legacy/ConfigurationUpdates.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Legacy
|
||||
{
|
||||
public static class ConfigurationUpdates
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public static void PerformOn(Configuration.Settings settings)
|
||||
{
|
||||
if (settings.Version < 1)
|
||||
UpdateTo1(settings);
|
||||
}
|
||||
|
||||
private static void UpdateTo1(Configuration.Settings settings)
|
||||
{
|
||||
settings.Visualizations[VisualizationIndex.Primary].Gradient = new LinearGradient(new GradientStop(0, HSVColor.Create(300, 1, 1)),
|
||||
new GradientStop(0.20, HSVColor.Create(225, 1, 1)),
|
||||
new GradientStop(0.35, HSVColor.Create(180, 1, 1)),
|
||||
new GradientStop(0.50, HSVColor.Create(135, 1, 1)),
|
||||
new GradientStop(0.65, HSVColor.Create(90, 1, 1)),
|
||||
new GradientStop(0.80, HSVColor.Create(45, 1, 1)),
|
||||
new GradientStop(0.95, HSVColor.Create(0, 1, 1)));
|
||||
|
||||
settings.Visualizations[VisualizationIndex.Secondary].Gradient = new LinearGradient(new GradientStop(0.5, new Color(255, 255, 255)));
|
||||
|
||||
settings.Visualizations[VisualizationIndex.Tertiary].Gradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)),
|
||||
new GradientStop(1, new Color(255, 0, 0)));
|
||||
|
||||
settings.Version = 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -49,5 +49,5 @@ using System.Windows;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.1.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.1.0")]
|
||||
[assembly: AssemblyVersion("1.3.1.1")]
|
||||
[assembly: AssemblyFileVersion("1.3.1.1")]
|
||||
|
||||
@ -8,12 +8,14 @@
|
||||
<styles:CachedResourceDictionary.MergedDictionaries>
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/BlurredDecorationWindow.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/ImageButton.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Formular.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Form.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/GroupBox.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/ToolTip.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/ComboBox.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Button.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Slider.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/ColorSelector.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/GradientEditor.xaml" />
|
||||
</styles:CachedResourceDictionary.MergedDictionaries>
|
||||
|
||||
<converter:EqualsToBoolConverter x:Key="EqualsToBoolConverter" />
|
||||
@ -22,7 +24,7 @@
|
||||
<Style TargetType="{x:Type controls:BlurredDecorationWindow}" BasedOn="{StaticResource StyleBlurredDecorationWindow}" />
|
||||
<Style TargetType="{x:Type ui:ConfigurationWindow}" BasedOn="{StaticResource StyleBlurredDecorationWindow}" />
|
||||
<Style TargetType="{x:Type controls:ImageButton}" BasedOn="{StaticResource StyleImageButton}" />
|
||||
<Style TargetType="{x:Type controls:Formular}" BasedOn="{StaticResource StyleFormular}" />
|
||||
<Style TargetType="{x:Type controls:Form}" BasedOn="{StaticResource StyleForm}" />
|
||||
<Style TargetType="GroupBox" BasedOn="{StaticResource StyleGroupBoxBox}" />
|
||||
<Style TargetType="ToolTip" BasedOn="{StaticResource StyleToolTip}" />
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource StyleComboBox}" />
|
||||
|
||||
305
KeyboardAudioVisualizer/Styles/ColorSelector.xaml
Normal file
305
KeyboardAudioVisualizer/Styles/ColorSelector.xaml
Normal file
@ -0,0 +1,305 @@
|
||||
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
|
||||
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles">
|
||||
|
||||
<DrawingBrush x:Key="BrushChessboard"
|
||||
TileMode="Tile"
|
||||
Viewport="0,0,16,16"
|
||||
ViewportUnits="Absolute">
|
||||
<DrawingBrush.Drawing>
|
||||
<GeometryDrawing Brush="#FF808080"
|
||||
Geometry="M5,5 L0,5 0,10 5,10 5,5 10,5 10,0 5,0 Z"/>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
|
||||
<DrawingBrush x:Key="BrushChessboardSmall"
|
||||
TileMode="Tile"
|
||||
Viewport="0,0,8,8"
|
||||
ViewportUnits="Absolute">
|
||||
<DrawingBrush.Drawing>
|
||||
<GeometryDrawing Brush="#FF808080"
|
||||
Geometry="M5,5 L0,5 0,10 5,10 5,5 10,5 10,0 5,0 Z"/>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
|
||||
<Style x:Key="StyleSliderLabel"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="TextAlignment" Value="Right" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleSliderValue"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleThumbSlider"
|
||||
TargetType="Thumb">
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Height" Value="NaN" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Thumb">
|
||||
<Border VerticalAlignment="Stretch"
|
||||
Width="4"
|
||||
SnapsToDevicePixels="True"
|
||||
Opacity="0.66"
|
||||
BorderThickness="1"
|
||||
Background="#FFFFFFFF"
|
||||
BorderBrush="#FF000000" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleSlider"
|
||||
TargetType="Slider">
|
||||
|
||||
<Setter Property="Focusable" Value="False" />
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="BorderBrush" Value="#FF000000" />
|
||||
<Setter Property="IsMoveToPointEnabled" Value="True" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Slider">
|
||||
<Border SnapsToDevicePixels="True"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Background="#FFFFFFFF">
|
||||
<Border Margin="1"
|
||||
SnapsToDevicePixels="True"
|
||||
Background="{StaticResource BrushChessboardSmall}">
|
||||
<Border SnapsToDevicePixels="True"
|
||||
Background="{TemplateBinding Background}">
|
||||
<Grid x:Name="GridTrackParent" SnapsToDevicePixels="True">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Track x:Name="PART_Track"
|
||||
Grid.Row="1"
|
||||
Width="{Binding ActualWidth, ElementName=GridTrackParent}"
|
||||
Height="{Binding ActualHeight, ElementName=GridTrackParent}">
|
||||
<Track.DecreaseRepeatButton>
|
||||
<RepeatButton Visibility="Hidden" Command="Slider.DecreaseLarge" />
|
||||
</Track.DecreaseRepeatButton>
|
||||
|
||||
<Track.Thumb>
|
||||
<Thumb Style="{StaticResource StyleThumbSlider}" />
|
||||
</Track.Thumb>
|
||||
|
||||
<Track.IncreaseRepeatButton>
|
||||
<RepeatButton Visibility="Hidden" Command="Slider.IncreaseLarge" />
|
||||
</Track.IncreaseRepeatButton>
|
||||
</Track>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleColorSelector"
|
||||
TargetType="{x:Type controls:ColorSelector}">
|
||||
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Width" Value="504" />
|
||||
<Setter Property="Height" Value="232" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type controls:ColorSelector}">
|
||||
<Border BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Background="{TemplateBinding Background}">
|
||||
<DockPanel Margin="{TemplateBinding Padding}">
|
||||
<Border DockPanel.Dock="Left"
|
||||
SnapsToDevicePixels="True"
|
||||
Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
|
||||
BorderThickness="1"
|
||||
BorderBrush="#FF000000"
|
||||
Background="#FFFFFFFF">
|
||||
<Grid x:Name="PART_Selector"
|
||||
Margin="1"
|
||||
SnapsToDevicePixels="True" />
|
||||
</Border>
|
||||
|
||||
<Slider DockPanel.Dock="Left"
|
||||
Margin="8,0"
|
||||
Height="24"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
Background="{Binding Background, ElementName=PART_SliderHue}"
|
||||
Minimum="{Binding Minimum, ElementName=PART_SliderHue}"
|
||||
Maximum="{Binding Maximum, ElementName=PART_SliderHue}"
|
||||
Value="{Binding Value, ElementName=PART_SliderHue}">
|
||||
<Slider.LayoutTransform>
|
||||
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90" />
|
||||
</Slider.LayoutTransform>
|
||||
</Slider>
|
||||
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Bottom">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="12" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="12" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="4" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="4" />
|
||||
<ColumnDefinition Width="28" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Alpha:" />
|
||||
<Slider x:Name="PART_SliderAlpha"
|
||||
Grid.Row="0" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderAlpha, StringFormat=##0}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Hue:" />
|
||||
<Slider x:Name="PART_SliderHue"
|
||||
Grid.Row="2" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
IsSnapToTickEnabled="False"
|
||||
Minimum="0"
|
||||
Maximum="360" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderHue, StringFormat=##0}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Sat:" />
|
||||
<Slider x:Name="PART_SliderSaturation"
|
||||
Grid.Row="4" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
IsSnapToTickEnabled="False"
|
||||
Minimum="0"
|
||||
Maximum="1" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderSaturation, StringFormat=0.00}" />
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Value:" />
|
||||
<Slider x:Name="PART_SliderValue"
|
||||
Grid.Row="6" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
IsSnapToTickEnabled="False"
|
||||
Minimum="0"
|
||||
Maximum="1" />
|
||||
<TextBlock Grid.Row="6" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderValue, StringFormat=0.00}" />
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Red:" />
|
||||
<Slider x:Name="PART_SliderRed"
|
||||
Grid.Row="8" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
<TextBlock Grid.Row="8" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderRed, StringFormat=000}" />
|
||||
|
||||
<TextBlock Grid.Row="10" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Green:" />
|
||||
<Slider x:Name="PART_SliderGreen"
|
||||
Grid.Row="10" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
<TextBlock Grid.Row="10" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderGreen, StringFormat=000}" />
|
||||
|
||||
<TextBlock Grid.Row="12" Grid.Column="0"
|
||||
Style="{StaticResource StyleSliderLabel}"
|
||||
Text="Blue:" />
|
||||
<Slider x:Name="PART_SliderBlue"
|
||||
Grid.Row="12" Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource StyleSlider}"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
<TextBlock Grid.Row="12" Grid.Column="4"
|
||||
Style="{StaticResource StyleSliderValue}"
|
||||
Text="{Binding Value, ElementName=PART_SliderBlue, StringFormat=000}" />
|
||||
</Grid>
|
||||
|
||||
<Border HorizontalAlignment="Stretch"
|
||||
Margin="0,0,0,4"
|
||||
SnapsToDevicePixels="True"
|
||||
BorderThickness="1"
|
||||
BorderBrush="#FF000000"
|
||||
Background="#FFFFFFFF">
|
||||
<Border Margin="1"
|
||||
SnapsToDevicePixels="True"
|
||||
Background="{StaticResource BrushChessboard}">
|
||||
<Rectangle x:Name="PART_Preview"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
SnapsToDevicePixels="True" />
|
||||
</Border>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type controls:ColorSelector}" BasedOn="{StaticResource StyleColorSelector}" />
|
||||
|
||||
</styles:CachedResourceDictionary>
|
||||
@ -7,9 +7,9 @@
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
|
||||
</styles:CachedResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style x:Key="StyleFormular"
|
||||
<Style x:Key="StyleForm"
|
||||
BasedOn="{StaticResource StyleFrameworkElement}"
|
||||
TargetType="{x:Type controls:Formular}">
|
||||
TargetType="{x:Type controls:Form}">
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="LabelWidth" Value="112" />
|
||||
@ -17,7 +17,7 @@
|
||||
<Setter Property="RowSpacing" Value="8" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleLabelFormular"
|
||||
<Style x:Key="StyleLabelForm"
|
||||
TargetType="Label">
|
||||
<Setter Property="Foreground" Value="{StaticResource BrushForeground}" />
|
||||
<Setter Property="FontSize" Value="{StaticResource FontSizeDefault}" />
|
||||
@ -44,7 +44,7 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleTextBlockFormular"
|
||||
<Style x:Key="StyleTextBlockForm"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{StaticResource BrushForeground}" />
|
||||
<Setter Property="FontSize" Value="{StaticResource FontSizeDefault}" />
|
||||
@ -53,7 +53,7 @@
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleListBoxItemFormular"
|
||||
<Style x:Key="StyleListBoxItemForm"
|
||||
TargetType="ListBoxItem">
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
@ -77,7 +77,7 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleListBoxFormular"
|
||||
<Style x:Key="StyleListBoxForm"
|
||||
TargetType="ListBox">
|
||||
<Setter Property="Focusable" Value="False" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
|
||||
@ -92,7 +92,7 @@
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource StyleListBoxItemFormular}" />
|
||||
<Setter Property="ItemContainerStyle" Value="{StaticResource StyleListBoxItemForm}" />
|
||||
</Style>
|
||||
|
||||
</styles:CachedResourceDictionary>
|
||||
93
KeyboardAudioVisualizer/Styles/GradientEditor.xaml
Normal file
93
KeyboardAudioVisualizer/Styles/GradientEditor.xaml
Normal file
@ -0,0 +1,93 @@
|
||||
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
|
||||
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles">
|
||||
|
||||
<styles:CachedResourceDictionary.MergedDictionaries>
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/ColorSelector.xaml" />
|
||||
</styles:CachedResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style x:Key="StyleGradientStop"
|
||||
TargetType="ContentControl">
|
||||
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="Width" Value="12" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="BorderBrush" Value="#FFFFFFFF" />
|
||||
|
||||
<Setter Property="ContentTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate DataType="{x:Type GradientStop}">
|
||||
<Grid>
|
||||
<Path Stretch="Fill"
|
||||
Data="M 0.5,0 L 0,0.25 L 0,1 L 1,1 L 1,0.25 Z"
|
||||
StrokeThickness="0"
|
||||
Fill="{StaticResource BrushChessboardSmall}" />
|
||||
<Path Stretch="Fill"
|
||||
Data="M 0.5,0 L 0,0.25 L 0,1 L 1,1 L 1,0.25 Z"
|
||||
Stroke="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType=ContentControl}}"
|
||||
StrokeThickness="{Binding BorderThickness, RelativeSource={RelativeSource AncestorType=ContentControl}}"
|
||||
Fill="{Binding Background, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding (controls:GradientEditor.IsSelected), RelativeSource={RelativeSource Self}}" Value="True">
|
||||
<Setter Property="BorderBrush" Value="#FF808080" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StyleGradientEditor"
|
||||
TargetType="{x:Type controls:GradientEditor}">
|
||||
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Height" Value="60" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="GradientStopStyle" Value="{StaticResource StyleGradientStop}" />
|
||||
|
||||
<Setter Property="ColorSelectorTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate DataType="{x:Type GradientStop}">
|
||||
<GroupBox>
|
||||
<controls:ColorSelector Foreground="#FFFFFFFF" SelectedColor="{Binding Color}" />
|
||||
</GroupBox>
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type controls:GradientEditor}">
|
||||
<Border BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Background="{TemplateBinding Background}">
|
||||
|
||||
<DockPanel>
|
||||
<Border DockPanel.Dock="Bottom"
|
||||
Height="16">
|
||||
<Canvas x:Name="PART_Stops"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="Transparent" />
|
||||
</Border>
|
||||
|
||||
<Border Background="{StaticResource BrushChessboard}">
|
||||
<Canvas x:Name="PART_Gradient"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="Transparent" />
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type controls:GradientEditor}" BasedOn="{StaticResource StyleGradientEditor}" />
|
||||
|
||||
</styles:CachedResourceDictionary>
|
||||
@ -13,14 +13,14 @@
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:BeatVisualizationProviderConfiguration}">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
</Grid.Resources>
|
||||
|
||||
<controls:Formular LabelWidth="240">
|
||||
<Label controls:Formular.IsLabel="True" Content="No configuration available ..." />
|
||||
</controls:Formular>
|
||||
<controls:Form LabelWidth="240">
|
||||
<Label controls:Form.IsLabel="True" Content="No configuration available ..." />
|
||||
</controls:Form>
|
||||
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@ -14,9 +14,9 @@
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:FrequencyBarsVisualizationProviderConfiguration}">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
|
||||
<ObjectDataProvider x:Key="SpectrumModes" MethodName="GetValues" ObjectType="{x:Type system:Enum}">
|
||||
<ObjectDataProvider.MethodParameters>
|
||||
@ -39,62 +39,62 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:Formular Grid.Column="0">
|
||||
<Label controls:Formular.IsLabel="True" Content="Spectrum:" />
|
||||
<ComboBox controls:Formular.Fill="True"
|
||||
<controls:Form Grid.Column="0">
|
||||
<Label controls:Form.IsLabel="True" Content="Spectrum:" />
|
||||
<ComboBox controls:Form.Fill="True"
|
||||
ItemsSource="{Binding Source={StaticResource SpectrumModes}}"
|
||||
SelectedItem="{Binding SpectrumMode}"
|
||||
ToolTip="Defines how the spectrum is grouped together.
 - Linear: Each bar represents the same range of frequencies.
 - Logarithmic: The higher the frequencies get the wider the range of grouped frequencies.
 - Gamma: Uses a configurable Gamma-Value to group the frequencies." />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Value:" />
|
||||
<ComboBox controls:Formular.Fill="True"
|
||||
<Label controls:Form.IsLabel="True" Content="Value:" />
|
||||
<ComboBox controls:Form.Fill="True"
|
||||
ItemsSource="{Binding Source={StaticResource ValueModes}}"
|
||||
SelectedItem="{Binding ValueMode}"
|
||||
ToolTip="Defines how the value of a bar is calculated.
 - Sum: Sums the power of all frequencies grouped in the bar using all available data.
 - Max: Uses the maximum value in each group making sure peaks are caught well.
 - Average: Uses the average of all frequencies grouped in the bar. " />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Bars:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="96" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight"
|
||||
<Label controls:Form.IsLabel="True" Content="Bars:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="1" Maximum="96" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight"
|
||||
Value="{Binding Bars}"
|
||||
ToolTip="The number of bars used to represent the spectrum.." />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
|
||||
<controls:Formular Grid.Column="2">
|
||||
<Label controls:Formular.IsLabel="True" Content="Min Freq.:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="0" Maximum="22100" IsSnapToTickEnabled="True" TickFrequency="10" TickPlacement="None"
|
||||
<controls:Form Grid.Column="2">
|
||||
<Label controls:Form.IsLabel="True" Content="Min Freq.:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="0" Maximum="22100" IsSnapToTickEnabled="True" TickFrequency="10" TickPlacement="None"
|
||||
Value="{Binding MinFrequency}"
|
||||
attached:SliderValue.Unit="Hz"
|
||||
ToolTip="The minimum frequency used in the graph." />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Max Freq.:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="0" Maximum="22100" IsSnapToTickEnabled="True" TickFrequency="10" TickPlacement="None"
|
||||
<Label controls:Form.IsLabel="True" Content="Max Freq.:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="0" Maximum="22100" IsSnapToTickEnabled="True" TickFrequency="10" TickPlacement="None"
|
||||
Value="{Binding MaxFrequency}"
|
||||
attached:SliderValue.Unit="Hz"
|
||||
ToolTip="The maximum frequency used in the graph." />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Gamma:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="6" IsSnapToTickEnabled="True" TickFrequency="0.25" TickPlacement="BottomRight"
|
||||
<Label controls:Form.IsLabel="True" Content="Gamma:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="1" Maximum="6" IsSnapToTickEnabled="True" TickFrequency="0.25" TickPlacement="BottomRight"
|
||||
IsEnabled="{Binding SpectrumMode, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static visualizationProvider:SpectrumMode.Gamma}}"
|
||||
Value="{Binding Gamma}"
|
||||
ToolTip="Only used if 'Gamma' is selected as spectrum!
Higher values cause more compression of high frequencies." />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
|
||||
<controls:Formular Grid.Column="4">
|
||||
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Reference:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="240" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="None"
|
||||
<controls:Form Grid.Column="4">
|
||||
<Label controls:Form.IsLabel="True" controls:Form.LineBreaks="1" Content="Reference:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="1" Maximum="240" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="None"
|
||||
Value="{Binding ReferenceLevel}"
|
||||
attached:SliderValue.Unit="dB"
|
||||
ToolTip="The reference value used to calculate the power of each bar.
(You can read this as 'scaling')" />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Smoothing:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
|
||||
<Label controls:Form.IsLabel="True" controls:Form.LineBreaks="1" Content="Smoothing:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
|
||||
Value="{Binding Smoothing}"
|
||||
ToolTip="Smooths the graph to prevent flickering.
Low values will cause a hectic fast plot, high values a slow one without peaks." />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Emphasize:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="0" Maximum="2" IsSnapToTickEnabled="True" TickFrequency="0.05" TickPlacement="BottomRight"
|
||||
<Label controls:Form.IsLabel="True" controls:Form.LineBreaks="1" Content="Emphasize:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="0" Maximum="2" IsSnapToTickEnabled="True" TickFrequency="0.05" TickPlacement="BottomRight"
|
||||
Value="{Binding EmphasisePeaks}"
|
||||
ToolTip="Emphasizes peaks. The higher the value, the bigger the difference between a 'loud-bar' and a 'quite-bar'." />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:LevelVisualizationProviderConfiguration}">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
|
||||
<ObjectDataProvider x:Key="ConversionModes" MethodName="GetValues" ObjectType="{x:Type system:Enum}">
|
||||
<ObjectDataProvider.MethodParameters>
|
||||
@ -32,27 +32,27 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:Formular Grid.Column="0">
|
||||
<Label controls:Formular.IsLabel="True" Content="Calculation:" />
|
||||
<ComboBox controls:Formular.Fill="True"
|
||||
<controls:Form Grid.Column="0">
|
||||
<Label controls:Form.IsLabel="True" Content="Calculation:" />
|
||||
<ComboBox controls:Form.Fill="True"
|
||||
ItemsSource="{Binding Source={StaticResource ConversionModes}}"
|
||||
SelectedItem="{Binding ConversionMode}"
|
||||
ToolTip="Defines how the RMS of the audio is plotted.
Exponential has the widest range of peaks while linear has the least." />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
|
||||
<controls:Formular Grid.Column="2">
|
||||
<Label controls:Formular.IsLabel="True" Content="Scale:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="20" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
|
||||
<controls:Form Grid.Column="2">
|
||||
<Label controls:Form.IsLabel="True" Content="Scale:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="1" Maximum="40" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
|
||||
Value="{Binding Scale}"
|
||||
ToolTip="Scales the whole graph." />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
|
||||
<controls:Formular Grid.Column="4">
|
||||
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Smoothing:" />
|
||||
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
|
||||
<controls:Form Grid.Column="4">
|
||||
<Label controls:Form.IsLabel="True" controls:Form.LineBreaks="1" Content="Smoothing:" />
|
||||
<Slider controls:Form.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
|
||||
Value="{Binding Smoothing}"
|
||||
ToolTip="Smooths the plot to prevent flickering.
Low values will cause a hectic fast plot, high values a slow one without peaks." />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
@ -15,12 +15,22 @@ namespace KeyboardAudioVisualizer.UI
|
||||
|
||||
public double UpdateRate
|
||||
{
|
||||
get => 1.0 / RGBSurface.Instance.UpdateFrequency;
|
||||
get => 1.0 / ApplicationManager.Instance.UpdateTrigger.UpdateFrequency;
|
||||
set
|
||||
{
|
||||
double val = MathHelper.Clamp(value, 1, 40);
|
||||
double val = MathHelper.Clamp(value, 1, 60);
|
||||
ApplicationManager.Instance.Settings.UpdateRate = val;
|
||||
RGBSurface.Instance.UpdateFrequency = 1.0 / val;
|
||||
ApplicationManager.Instance.UpdateTrigger.UpdateFrequency = 1.0 / val;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableAudioPrescale
|
||||
{
|
||||
get => ApplicationManager.Instance.Settings.EnableAudioPrescale;
|
||||
set
|
||||
{
|
||||
ApplicationManager.Instance.Settings.EnableAudioPrescale = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,14 +10,15 @@
|
||||
xmlns:keyboardAudioVisualizer="clr-namespace:KeyboardAudioVisualizer"
|
||||
xmlns:converter="clr-namespace:KeyboardAudioVisualizer.Converter"
|
||||
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
|
||||
xmlns:helper="clr-namespace:KeyboardAudioVisualizer.Helper"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:attached="clr-namespace:KeyboardAudioVisualizer.Attached"
|
||||
xmlns:helper="clr-namespace:KeyboardAudioVisualizer.Helper"
|
||||
mc:Ignorable="d"
|
||||
Title="Keyboard Audio-Visualizer # Configuration"
|
||||
Icon="pack://application:,,,/KeyboardAudioVisualizer;component/Resources/Icon.ico"
|
||||
IconCommand="{Binding OpenHomepageCommand}"
|
||||
Width="1280" Height="720">
|
||||
Width="1280" Height="720"
|
||||
Closed="ConfigurationWindow_OnClosed">
|
||||
|
||||
<controls:BlurredDecorationWindow.Resources>
|
||||
<styles:CachedResourceDictionary>
|
||||
@ -56,21 +57,26 @@
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Primary], Converter={StaticResource VisualizationToLastChildFillConverter}}">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<controls:Formular>
|
||||
<controls:Formular.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
</controls:Formular.Resources>
|
||||
<controls:GradientEditor Gradient="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Settings[(helper:VisualizationIndex)Primary].Gradient}"
|
||||
ToolTip="Defines the gradient that's drawed on the device. Usage:
 Left click inside the preview to add a new stop.
 Left-click stop to change the color or move it.
 Right-click stop to remove it.
" />
|
||||
</GroupBox>
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Visualization: " />
|
||||
<ComboBox controls:Formular.Fill="True" SelectedIndex="0"
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<controls:Form>
|
||||
<controls:Form.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
</controls:Form.Resources>
|
||||
|
||||
<Label controls:Form.IsLabel="True" Content="Visualization: " />
|
||||
<ComboBox controls:Form.Fill="True" SelectedIndex="0"
|
||||
ItemTemplate="{StaticResource DataTemplateVisualizationSelection}"
|
||||
ItemsSource="{Binding Source={StaticResource DataProviderVisualizationTypes},
|
||||
Converter={StaticResource VisualizationProviderSelectableConverter}, ConverterParameter={x:Static core:RGBDeviceType.Keyboard}}"
|
||||
SelectedItem="{Binding SelectedPrimaryVisualization}"
|
||||
ToolTip="The visualization shown on the device.
 - Frequency Bars: Shows vertical bars representing the frequencies of the song.
 - Level: Shows two horizontal bars representing the loudness of the song (left and right).
 - Beat: Shows a flash to the beat of the song (this doesn't work too well right now :()" />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
@ -78,7 +84,7 @@
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Primary]}" />
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Primary]}" Tag="0" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
@ -88,20 +94,25 @@
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Secondary], Converter={StaticResource VisualizationToLastChildFillConverter}}">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<controls:Formular>
|
||||
<controls:Formular.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
</controls:Formular.Resources>
|
||||
<controls:GradientEditor Gradient="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Settings[(helper:VisualizationIndex)Secondary].Gradient}"
|
||||
CanAddOrDeleteStops="False" />
|
||||
</GroupBox>
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Visualization: " />
|
||||
<ComboBox controls:Formular.Fill="True" SelectedIndex="0"
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<controls:Form>
|
||||
<controls:Form.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
</controls:Form.Resources>
|
||||
|
||||
<Label controls:Form.IsLabel="True" Content="Visualization: " />
|
||||
<ComboBox controls:Form.Fill="True" SelectedIndex="0"
|
||||
ItemTemplate="{StaticResource DataTemplateVisualizationSelection}"
|
||||
ItemsSource="{Binding Source={StaticResource DataProviderVisualizationTypes},
|
||||
Converter={StaticResource VisualizationProviderSelectableConverter}, ConverterParameter={x:Static core:RGBDeviceType.Mouse}}"
|
||||
SelectedItem="{Binding SelectedSecondaryVisualization}" />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
@ -109,7 +120,7 @@
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Secondary]}" />
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Secondary]}" Tag="1" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
@ -119,20 +130,24 @@
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Tertiary], Converter={StaticResource VisualizationToLastChildFillConverter}}">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<controls:Formular>
|
||||
<controls:Formular.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
</controls:Formular.Resources>
|
||||
<controls:GradientEditor Gradient="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Settings[(helper:VisualizationIndex)Tertiary].Gradient}" />
|
||||
</GroupBox>
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Visualization: " />
|
||||
<ComboBox controls:Formular.Fill="True" SelectedIndex="0"
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<controls:Form>
|
||||
<controls:Form.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
</controls:Form.Resources>
|
||||
|
||||
<Label controls:Form.IsLabel="True" Content="Visualization: " />
|
||||
<ComboBox controls:Form.Fill="True" SelectedIndex="0"
|
||||
ItemTemplate="{StaticResource DataTemplateVisualizationSelection}"
|
||||
ItemsSource="{Binding Source={StaticResource DataProviderVisualizationTypes},
|
||||
Converter={StaticResource VisualizationProviderSelectableConverter}, ConverterParameter={x:Static core:RGBDeviceType.Mousepad}}"
|
||||
SelectedItem="{Binding SelectedTertiaryVisualization}" />
|
||||
</controls:Formular>
|
||||
</controls:Form>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
@ -140,7 +155,7 @@
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Tertiary]}" />
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Tertiary]}" Tag="2" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
@ -148,55 +163,70 @@
|
||||
|
||||
<TabItem Header="Settings">
|
||||
<AdornerDecorator>
|
||||
<GroupBox VerticalAlignment="Top">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
|
||||
</Grid.Resources>
|
||||
<DockPanel LastChildFill="False">
|
||||
<DockPanel.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
</DockPanel.Resources>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<controls:Form>
|
||||
<Label controls:Form.IsLabel="True" Content="Version" />
|
||||
<TextBlock Text="{Binding Version}" />
|
||||
|
||||
<controls:Formular Grid.Column="0">
|
||||
<Label controls:Formular.IsLabel="True" Content="Version:" />
|
||||
<TextBlock Text="{Binding Version}" />
|
||||
<Label controls:Form.IsLabel="True" Content="Update-Rate" />
|
||||
<Slider Minimum="1" Maximum="60" controls:Form.Fill="True" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight"
|
||||
Value="{Binding UpdateRate}"
|
||||
attached:SliderValue.Unit="FPS"
|
||||
ToolTip="Defines how fast the data is updated.
Low values can reduce CPU-usage but will cause stuttering.
Values above 40 will only affect the internal calculations and wont make the keyboard update faster.
It's not recommended to select a value > 40." />
|
||||
|
||||
<Label controls:Formular.IsLabel="True" Content="Update-Rate" />
|
||||
<Slider Minimum="1" Maximum="40" controls:Formular.Fill="True" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight"
|
||||
Value="{Binding UpdateRate}"
|
||||
attached:SliderValue.Unit="FPS"
|
||||
ToolTip="Defines how fast the data is updated.
Low values can reduce CPU-usage but will cause stuttering." />
|
||||
<Label controls:Form.IsLabel="True" Content="Fix Volume" />
|
||||
<CheckBox VerticalAlignment="Center"
|
||||
IsChecked="{Binding EnableAudioPrescale}"
|
||||
ToolTip="Scales the audio signal inverse to the OS-master-volume.
This might (depending on the system) lead to decrased performance
 -> only activate it if you need it." />
|
||||
|
||||
<Label controls:Formular.LineBreaks="1" controls:Formular.IsLabel="True" Content="Devices:" />
|
||||
</controls:Formular>
|
||||
</Grid>
|
||||
</controls:Form>
|
||||
</GroupBox>
|
||||
|
||||
<!-- TODO DarthAffe 05.08.2017: Fix the formular to support that use-case -->
|
||||
<ItemsControl VerticalAlignment="Top" HorizontalAlignment="Left" Margin="120,-22,0,0" ItemsSource="{Binding Source={x:Static core:RGBSurface.Instance}, Path=Devices}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Style="{StaticResource StyleTextBlockFormular}">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="> {0} {1} ({2})">
|
||||
<Binding Path="DeviceInfo.Manufacturer" />
|
||||
<Binding Path="DeviceInfo.Model" />
|
||||
<Binding Path="DeviceInfo.DeviceType" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Border HorizontalAlignment="Left" Width="111">
|
||||
<Label HorizontalAlignment="Right"
|
||||
Content="Background" />
|
||||
</Border>
|
||||
|
||||
<controls:GradientEditor Margin="120,-18,0,0"
|
||||
Gradient="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Settings.Background}"
|
||||
ToolTip="Defines the gradient used as the background. Use transparency to create some kind of blur. Usage:
 Left click inside the preview to add a new stop.
 Left-click stop to change the color or move it.
 Right-click stop to remove it.
" />
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Border HorizontalAlignment="Left" Width="111">
|
||||
<Label HorizontalAlignment="Right"
|
||||
Content="Devices" />
|
||||
</Border>
|
||||
|
||||
<ItemsControl VerticalAlignment="Top" HorizontalAlignment="Left" Margin="120,-18,0,0" ItemsSource="{Binding Source={x:Static core:RGBSurface.Instance}, Path=Devices}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Style="{StaticResource StyleTextBlockForm}">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="> {0} {1} ({2})">
|
||||
<Binding Path="DeviceInfo.Manufacturer" />
|
||||
<Binding Path="DeviceInfo.Model" />
|
||||
<Binding Path="DeviceInfo.DeviceType" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
using KeyboardAudioVisualizer.Controls;
|
||||
using System;
|
||||
using KeyboardAudioVisualizer.Controls;
|
||||
|
||||
namespace KeyboardAudioVisualizer.UI
|
||||
{
|
||||
public partial class ConfigurationWindow : BlurredDecorationWindow
|
||||
{
|
||||
public ConfigurationWindow() => InitializeComponent();
|
||||
|
||||
//DarthAffe 07.02.2018: This prevents the applicaiton from not shutting down and crashing afterwards if 'close' is selected in the taskbar-context-menu
|
||||
private void ConfigurationWindow_OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
ApplicationManager.Instance.ExitCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,9 @@
|
||||
</Style>
|
||||
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:BeatVisualizationProvider}">
|
||||
<visualization:BeatVisualizer Style="{StaticResource StyleBeatVisualizer}" VisualizationProvider="{Binding}" />
|
||||
<visualization:BeatVisualizer Style="{StaticResource StyleBeatVisualizer}"
|
||||
VisualizationProvider="{Binding}"
|
||||
VisualizationIndex="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
|
||||
</DataTemplate>
|
||||
|
||||
</styles:CachedResourceDictionary>
|
||||
|
||||
@ -4,14 +4,20 @@ using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
{
|
||||
public class BeatVisualizer : Control
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private LinearGradient _gradient;
|
||||
|
||||
#endregion
|
||||
|
||||
#region DependencyProperties
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
@ -24,6 +30,15 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
set => SetValue(VisualizationProviderProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VisualizationIndexProperty = DependencyProperty.Register(
|
||||
"VisualizationIndex", typeof(VisualizationIndex?), typeof(BeatVisualizer), new PropertyMetadata(null, VisualizationIndexChanged));
|
||||
|
||||
public VisualizationIndex? VisualizationIndex
|
||||
{
|
||||
get => (VisualizationIndex?)GetValue(VisualizationIndexProperty);
|
||||
set => SetValue(VisualizationIndexProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
|
||||
"Brush", typeof(Brush), typeof(BeatVisualizer), new PropertyMetadata(default(Brush)));
|
||||
|
||||
@ -52,7 +67,7 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
RGBSurface.Instance.Updated += args => Dispatcher.BeginInvoke(new Action(Update), DispatcherPriority.Normal);
|
||||
|
||||
//TODO DarthAffe 12.08.2017: Create brush from config
|
||||
Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -75,6 +90,37 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
}
|
||||
}
|
||||
|
||||
private static void VisualizationIndexChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is BeatVisualizer visualizer)) return;
|
||||
visualizer.UpdateGradient();
|
||||
}
|
||||
|
||||
private void UpdateGradient()
|
||||
{
|
||||
void GradientChanged(object sender, EventArgs args) => UpdateColor();
|
||||
if (_gradient != null)
|
||||
_gradient.GradientChanged -= GradientChanged;
|
||||
|
||||
_gradient = VisualizationIndex.HasValue ? ApplicationManager.Instance.Settings[VisualizationIndex.Value].Gradient : null;
|
||||
if (_gradient != null)
|
||||
_gradient.GradientChanged += GradientChanged;
|
||||
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
private void UpdateColor()
|
||||
{
|
||||
if (_gradient == null) return;
|
||||
|
||||
GradientStopCollection gradientStops = new GradientStopCollection();
|
||||
foreach (RGB.NET.Brushes.Gradients.GradientStop stop in _gradient.GradientStops)
|
||||
gradientStops.Add(new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromArgb(stop.Color.GetA(), stop.Color.GetR(), stop.Color.GetG(), stop.Color.GetB()), stop.Offset));
|
||||
|
||||
Brush = new LinearGradientBrush(gradientStops, new System.Windows.Point(0, 0.5), new System.Windows.Point(1, 0.5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,8 +31,11 @@
|
||||
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:FrequencyBarsVisualizationProvider}">
|
||||
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<visualization:FrequencyBarsVisualizer Style="{StaticResource StyleFrequencyBarsVisualizer}" VisualizationProvider="{Binding}" />
|
||||
<visualization:EqualizerVisualizer Style="{StaticResource StyleEqualizerVisualizer}" Equalizer="{Binding Equalizer}" />
|
||||
<visualization:FrequencyBarsVisualizer Style="{StaticResource StyleFrequencyBarsVisualizer}"
|
||||
VisualizationProvider="{Binding}"
|
||||
VisualizationIndex="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
|
||||
<visualization:EqualizerVisualizer Style="{StaticResource StyleEqualizerVisualizer}"
|
||||
Equalizer="{Binding Equalizer}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using Color = System.Windows.Media.Color;
|
||||
@ -27,12 +28,22 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
get => (IVisualizationProvider)GetValue(VisualizationProviderProperty);
|
||||
set => SetValue(VisualizationProviderProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VisualizationIndexProperty = DependencyProperty.Register(
|
||||
"VisualizationIndex", typeof(VisualizationIndex?), typeof(FrequencyBarsVisualizer), new PropertyMetadata(null, VisualizationIndexChanged));
|
||||
|
||||
public VisualizationIndex? VisualizationIndex
|
||||
{
|
||||
get => (VisualizationIndex?)GetValue(VisualizationIndexProperty);
|
||||
set => SetValue(VisualizationIndexProperty, value);
|
||||
}
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
private IGradient _gradient;
|
||||
private LinearGradient _gradient;
|
||||
private Panel _panel;
|
||||
private Rectangle[] _bars = new Rectangle[0];
|
||||
|
||||
@ -44,9 +55,6 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
{
|
||||
RGBSurface.Instance.Updated += args => Dispatcher.BeginInvoke(new Action(Update), DispatcherPriority.Normal);
|
||||
SizeChanged += (sender, args) => UpdateSizes();
|
||||
|
||||
//TODO DarthAffe 12.08.2017: Get gradient from config
|
||||
_gradient = new RainbowGradient(300, -14);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -65,8 +73,7 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
private static void VisualizationProviderChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
FrequencyBarsVisualizer visualizer = dependencyObject as FrequencyBarsVisualizer;
|
||||
if (visualizer == null) return;
|
||||
if (!(dependencyObject is FrequencyBarsVisualizer visualizer)) return;
|
||||
|
||||
void ConfigurationOnPropertyChanged(object sender, PropertyChangedEventArgs args) => visualizer.ConfigurationChanged(args.PropertyName);
|
||||
|
||||
@ -77,6 +84,26 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
newVisualizationProvider.Configuration.PropertyChanged += ConfigurationOnPropertyChanged;
|
||||
}
|
||||
|
||||
private static void VisualizationIndexChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is FrequencyBarsVisualizer visualizer)) return;
|
||||
visualizer.UpdateGradient();
|
||||
}
|
||||
|
||||
private void UpdateGradient()
|
||||
{
|
||||
void GradientChanged(object sender, EventArgs args) => UpdateColors();
|
||||
if (_gradient != null)
|
||||
_gradient.GradientChanged -= GradientChanged;
|
||||
|
||||
_gradient = VisualizationIndex.HasValue ? ApplicationManager.Instance.Settings[VisualizationIndex.Value].Gradient : null;
|
||||
if (_gradient != null)
|
||||
_gradient.GradientChanged += GradientChanged;
|
||||
|
||||
UpdateColors();
|
||||
}
|
||||
|
||||
private void ConfigurationChanged(string changedPropertyName)
|
||||
{
|
||||
if ((changedPropertyName == null) || (changedPropertyName == nameof(FrequencyBarsVisualizationProviderConfiguration.Bars)))
|
||||
@ -119,10 +146,12 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
|
||||
private void UpdateColors()
|
||||
{
|
||||
if (_gradient == null) return;
|
||||
|
||||
for (int i = 0; i < _bars.Length; i++)
|
||||
{
|
||||
RGB.NET.Core.Color color = _gradient.GetColor((double)i / _bars.Length);
|
||||
_bars[i].Fill = new SolidColorBrush(Color.FromRgb(color.R, color.G, color.B));
|
||||
_bars[i].Fill = new SolidColorBrush(Color.FromRgb(color.GetR(), color.GetG(), color.GetB()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -63,7 +63,9 @@
|
||||
</Style>
|
||||
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:LevelVisualizationProvider}">
|
||||
<visualization:LevelVisualizer Style="{StaticResource StyleLevelVisualizer}" VisualizationProvider="{Binding}" />
|
||||
<visualization:LevelVisualizer Style="{StaticResource StyleLevelVisualizer}"
|
||||
VisualizationProvider="{Binding}"
|
||||
VisualizationIndex="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
|
||||
</DataTemplate>
|
||||
|
||||
</styles:CachedResourceDictionary>
|
||||
|
||||
@ -1,17 +1,27 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using GradientStop = RGB.NET.Brushes.Gradients.GradientStop;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
{
|
||||
public class LevelVisualizer : Control
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private LinearGradient _gradient;
|
||||
|
||||
#endregion
|
||||
|
||||
#region DependencyProperties
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
@ -24,6 +34,15 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
set => SetValue(VisualizationProviderProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VisualizationIndexProperty = DependencyProperty.Register(
|
||||
"VisualizationIndex", typeof(VisualizationIndex?), typeof(LevelVisualizer), new PropertyMetadata(null, VisualizationIndexChanged));
|
||||
|
||||
public VisualizationIndex? VisualizationIndex
|
||||
{
|
||||
get => (VisualizationIndex?)GetValue(VisualizationIndexProperty);
|
||||
set => SetValue(VisualizationIndexProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BrushLeftProperty = DependencyProperty.Register(
|
||||
"BrushLeft", typeof(Brush), typeof(LevelVisualizer), new PropertyMetadata(default(Brush)));
|
||||
|
||||
@ -68,10 +87,6 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
public LevelVisualizer()
|
||||
{
|
||||
RGBSurface.Instance.Updated += args => Dispatcher.BeginInvoke(new Action(Update), DispatcherPriority.Normal);
|
||||
|
||||
//TODO DarthAffe 12.08.2017: Create brush from config
|
||||
BrushLeft = new LinearGradientBrush(Color.FromRgb(255, 0, 0), Color.FromRgb(0, 0, 255), new Point(0, 0.5), new Point(1, 0.5));
|
||||
BrushRight = new LinearGradientBrush(Color.FromRgb(0, 0, 255), Color.FromRgb(255, 0, 0), new Point(0, 0.5), new Point(1, 0.5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -92,6 +107,38 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
SizeRight = horizontalSizeRight;
|
||||
}
|
||||
|
||||
private void SetBrushes()
|
||||
{
|
||||
if (_gradient == null) return;
|
||||
|
||||
GradientStopCollection gradientStops = new GradientStopCollection();
|
||||
foreach (GradientStop stop in _gradient.GradientStops)
|
||||
gradientStops.Add(new System.Windows.Media.GradientStop(Color.FromArgb(stop.Color.GetA(), stop.Color.GetR(), stop.Color.GetG(), stop.Color.GetB()), stop.Offset));
|
||||
|
||||
BrushLeft = new LinearGradientBrush(gradientStops, new Point(1, 0.5), new Point(0, 0.5));
|
||||
BrushRight = new LinearGradientBrush(gradientStops, new Point(0, 0.5), new Point(1, 0.5));
|
||||
}
|
||||
|
||||
private static void VisualizationIndexChanged(DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is LevelVisualizer visualizer)) return;
|
||||
visualizer.UpdateGradient();
|
||||
}
|
||||
|
||||
private void UpdateGradient()
|
||||
{
|
||||
void GradientChanged(object sender, EventArgs args) => SetBrushes();
|
||||
if (_gradient != null)
|
||||
_gradient.GradientChanged -= GradientChanged;
|
||||
|
||||
_gradient = VisualizationIndex.HasValue ? ApplicationManager.Instance.Settings[VisualizationIndex.Value].Gradient : null;
|
||||
if (_gradient != null)
|
||||
_gradient.GradientChanged += GradientChanged;
|
||||
|
||||
SetBrushes();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CSCore" version="1.2.1.1" targetFramework="net461" />
|
||||
<package id="CSCore" version="1.2.1.2" targetFramework="net461" />
|
||||
<package id="Hardcodet.NotifyIcon.Wpf" version="1.0.8" targetFramework="net461" />
|
||||
<package id="MathNet.Numerics" version="3.20.0" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
<package id="RGB.NET.Brushes" version="1.0.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Core" version="1.0.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.CoolerMaster" version="1.0.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Corsair" version="1.0.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Logitech" version="1.0.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Novation" version="1.0.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Groups" version="1.0.0" targetFramework="net461" />
|
||||
<package id="Sanford.Multimedia.Midi" version="6.4.1" targetFramework="net461" />
|
||||
<package id="System.ValueTuple" version="4.4.0" targetFramework="net461" />
|
||||
<package id="HidSharp" version="2.0.5" targetFramework="net461" />
|
||||
<package id="MathNet.Numerics" version="4.7.0" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
|
||||
<package id="RGB.NET.Brushes" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Core" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Decorators" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Asus" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.CoolerMaster" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Corsair" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Logitech" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Novation" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.Razer" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Devices.SteelSeries" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Groups" version="0.1.31" targetFramework="net461" />
|
||||
<package id="RGB.NET.Resources.Asus" version="0.3.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Resources.CoolerMaster" version="0.2.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Resources.Corsair" version="0.3.0.234" targetFramework="net461" />
|
||||
<package id="RGB.NET.Resources.Logitech" version="0.3.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Resources.Novation" version="0.1.0" targetFramework="net461" />
|
||||
<package id="RGB.NET.Resources.Razer" version="0.3.2.4" targetFramework="net461" />
|
||||
<package id="Sanford.Multimedia.Midi" version="6.6.0" targetFramework="net461" />
|
||||
<package id="Sanford.Multimedia.Midi.Standard" version="6.6.0" targetFramework="net461" />
|
||||
<package id="System.Management" version="4.5.0" targetFramework="net461" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
|
||||
</packages>
|
||||
12
NuGet.Config
Normal file
12
NuGet.Config
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<packageSources>
|
||||
<add key="RGB.NET" value="http://nuget.arge.be/v3/index.json" />
|
||||
</packageSources>
|
||||
|
||||
<activePackageSource>
|
||||
<add key="All" value="(Aggregate source)" />
|
||||
</activePackageSource>
|
||||
|
||||
</configuration>
|
||||
@ -1,3 +1,7 @@
|
||||
This software is no longer actively developed.
|
||||
|
||||
Consider checking out [Artemis](https://github.com/Artemis-RGB/Artemis) for a even more feature rich replacement.
|
||||
|
||||
# KeyboardAudioVisualizer
|
||||
It's colorful - I like it!
|
||||
|
||||
@ -36,7 +40,7 @@ It's colorful - I like it!
|
||||
- **Gamma:** The correction value used for gamma-grouping (disabled if any other grouping is selected). High values lead to a stronger compression of high frequencies. _(default: 2)_
|
||||
- **Reference:** The reference value used to calculate the power of each bar. Adjust this to your audio volume. Low volume -> low reference, high volume -> higher reference. _(default: 90)_
|
||||
- **Smoothing:** Smooths the graph to prevent flickering. Low values will cause a hectic fast plot, high values a slow one without peaks. _(default: 3)_
|
||||
- **Emphasize:** Emphasizes peaks. The higher the value, the bigger the difference between a "loud-bar" and a "quite-bar". _(default: 0.5)_
|
||||
- **Emphasize:** Emphasizes peaks. The higher the value, the bigger the difference between a "loud-bar" and a "quiet-bar". _(default: 0.5)_
|
||||
|
||||
**Equalizer**
|
||||
Allows to finetune the graph by slective increasing/decresing the value.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user