mirror of
https://github.com/DarthAffe/KeyboardAudioVisualizer.git
synced 2025-12-12 15:18:30 +00:00
Compare commits
42 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 | |||
| 51213e31c2 | |||
| b2e81cdbaf | |||
| f1cad012c3 | |||
| a8c34ada40 | |||
| e35e70d0bb | |||
| c72e8497ab | |||
| 0ccc1f3dbb | |||
| 4dc9377e75 | |||
| 07e4221877 | |||
| 9d4aa2728c | |||
| 44c0cc59fa | |||
| 9b84bfcba3 | |||
| adf3fc5fd3 |
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>
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
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
|
||||
{
|
||||
@ -12,7 +18,7 @@ namespace KeyboardAudioVisualizer
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string PATH_SETTINGS = "Settings.xml";
|
||||
private const string PATH_SETTINGS = "Settings.json";
|
||||
|
||||
#endregion
|
||||
|
||||
@ -22,10 +28,6 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
@ -34,18 +36,38 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
try
|
||||
{
|
||||
ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(int.MaxValue));
|
||||
|
||||
_taskbarIcon = (TaskbarIcon)FindResource("TaskbarIcon");
|
||||
_taskbarIcon.DoubleClickCommand = ApplicationManager.Instance.OpenConfigurationCommand;
|
||||
|
||||
Settings settings = SerializationHelper.LoadObjectFromFile<Settings>(PATH_SETTINGS);
|
||||
//Settings settings = SerializationHelper.LoadObjectFromFile<Settings>(PATH_SETTINGS);
|
||||
Settings settings = null;
|
||||
try { settings = JsonConvert.DeserializeObject<Settings>(File.ReadAllText(PATH_SETTINGS), new ColorSerializer()); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
/* File doesn't exist or is corrupt - just create a new one. */
|
||||
}
|
||||
|
||||
if (settings == null)
|
||||
settings = ConfigurationMigrator.MigrateOldConfig();
|
||||
|
||||
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;
|
||||
|
||||
AudioProcessor.Initialize();
|
||||
AudioVisualizationFactory.Initialize();
|
||||
ApplicationManager.Instance.InitializeDevices();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -62,7 +84,8 @@ namespace KeyboardAudioVisualizer
|
||||
{
|
||||
base.OnExit(e);
|
||||
|
||||
SerializationHelper.SaveObjectToFile(ApplicationManager.Instance.Settings, PATH_SETTINGS);
|
||||
File.WriteAllText(PATH_SETTINGS, JsonConvert.SerializeObject(ApplicationManager.Instance.Settings, new ColorSerializer()));
|
||||
ConfigurationMigrator.CleanupOldConfigs();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
using System.Windows;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using KeyboardAudioVisualizer.AudioProcessing;
|
||||
using KeyboardAudioVisualizer.Brushes;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Configuration;
|
||||
using KeyboardAudioVisualizer.Decorators;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using KeyboardAudioVisualizer.UI;
|
||||
using RGB.NET.Brushes;
|
||||
@ -10,12 +12,20 @@ using RGB.NET.Core;
|
||||
using RGB.NET.Devices.CoolerMaster;
|
||||
using RGB.NET.Devices.Corsair;
|
||||
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>;
|
||||
|
||||
namespace KeyboardAudioVisualizer
|
||||
{
|
||||
public class ApplicationManager
|
||||
{
|
||||
#region Constants
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public static ApplicationManager Instance { get; } = new ApplicationManager();
|
||||
@ -24,6 +34,12 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
public Settings Settings { get; set; }
|
||||
|
||||
public ObservableDictionary<VisualizationIndex, IVisualizationProvider> Visualizations { get; } = new ObservableDictionary<VisualizationIndex, IVisualizationProvider>();
|
||||
|
||||
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
|
||||
@ -48,78 +64,133 @@ namespace KeyboardAudioVisualizer
|
||||
{
|
||||
RGBSurface surface = RGBSurface.Instance;
|
||||
|
||||
surface.UpdateFrequency = 1 / 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);
|
||||
|
||||
//TODO DarthAffe 03.08.2017: Changeable, Settings etc.
|
||||
foreach (IRGBDevice device in surface.Devices)
|
||||
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)>();
|
||||
List<(ILedGroup, GetDecoratorFunc)> tertiaryGroups = new List<(ILedGroup, GetDecoratorFunc)>();
|
||||
foreach (IRGBDevice device in RGBSurface.Instance.Devices)
|
||||
switch (device.DeviceInfo.DeviceType)
|
||||
{
|
||||
case RGBDeviceType.Keyboard:
|
||||
//TODO DarthAffe 05.08.2017: Lighbar-support has to be better in RGB.NET
|
||||
if (device[new CorsairLedId(device, CorsairLedIds.Lightbar1)] != null)
|
||||
case RGBDeviceType.Keypad:
|
||||
case RGBDeviceType.LedMatrix:
|
||||
ListLedGroup primary = new ListLedGroup(device);
|
||||
|
||||
LightbarSpecialPart lightbar = device.GetSpecialDevicePart<LightbarSpecialPart>();
|
||||
if (lightbar != null)
|
||||
{
|
||||
ILedGroup lightbarLeft = new ListLedGroup(new CorsairLedId(device, CorsairLedIds.Lightbar1), new CorsairLedId(device, CorsairLedIds.Lightbar2),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar3), new CorsairLedId(device, CorsairLedIds.Lightbar4),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar5), new CorsairLedId(device, CorsairLedIds.Lightbar6),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar7), new CorsairLedId(device, CorsairLedIds.Lightbar8),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar9));
|
||||
ILedGroup lightbarCenter = new ListLedGroup(new CorsairLedId(device, CorsairLedIds.Lightbar10));
|
||||
ILedGroup lightbarRight = new ListLedGroup(new CorsairLedId(device, CorsairLedIds.Lightbar11), new CorsairLedId(device, CorsairLedIds.Lightbar12),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar13), new CorsairLedId(device, CorsairLedIds.Lightbar14),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar15), new CorsairLedId(device, CorsairLedIds.Lightbar16),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar17), new CorsairLedId(device, CorsairLedIds.Lightbar18),
|
||||
new CorsairLedId(device, CorsairLedIds.Lightbar19));
|
||||
ListLedGroup primary = new ListLedGroup(device);
|
||||
primary.RemoveLeds(lightbarLeft.GetLeds());
|
||||
primary.RemoveLeds(lightbarCenter.GetLeds());
|
||||
primary.RemoveLeds(lightbarRight.GetLeds());
|
||||
primary.RemoveLeds(lightbar.Leds);
|
||||
|
||||
IGradient keyboardLevelGradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)), new GradientStop(1, new Color(255, 0, 0)));
|
||||
lightbarLeft.Brush = new LevelBarBrush(AudioProcessor.Instance.TertiaryVisualizationProvider, keyboardLevelGradient, LevelBarDirection.Left, 0);
|
||||
lightbarRight.Brush = new LevelBarBrush(AudioProcessor.Instance.TertiaryVisualizationProvider, keyboardLevelGradient, LevelBarDirection.Right, 1);
|
||||
lightbarCenter.Brush = new BeatBrush(AudioProcessor.Instance.SecondaryVisualizationProvider, new Color(255, 255, 255));
|
||||
ILedGroup lightbarLeft = new ListLedGroup(lightbar.Left);
|
||||
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)));
|
||||
|
||||
primary.Brush = new FrequencyBarsBrush(AudioProcessor.Instance.PrimaryVisualizationProvider, new RainbowGradient(300, -14));
|
||||
ILedGroup lightbarRight = new ListLedGroup(lightbar.Right);
|
||||
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 LinearGradientBrush(secondaryGradient);
|
||||
secondaryGroups.Add((lightbarCenter, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer)));
|
||||
}
|
||||
else
|
||||
new ListLedGroup(device).Brush = new FrequencyBarsBrush(AudioProcessor.Instance.PrimaryVisualizationProvider, new RainbowGradient(300, -14));
|
||||
//new ListLedGroup(device).Brush = new BeatBrush(AudioProcessor.Instance.PrimaryVisualizationProvider, new Color(255, 255, 255));
|
||||
|
||||
//{
|
||||
// ILedGroup left1 = new RectangleLedGroup(new Rectangle(device.Location.X, device.Location.Y, device.Size.Width / 2.0, device.Size.Height));
|
||||
// ILedGroup right1 = new RectangleLedGroup(new Rectangle(device.Location.X + (device.Size.Width / 2.0), device.Location.Y, device.Size.Width / 2.0, device.Size.Height));
|
||||
|
||||
// IGradient levelGradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)), new GradientStop(1, new Color(255, 0, 0)));
|
||||
// left1.Brush = new LevelBarBrush(AudioProcessor.Instance.TertiaryVisualizationProvider, levelGradient, LevelBarDirection.Left, 0);
|
||||
// right1.Brush = new LevelBarBrush(AudioProcessor.Instance.TertiaryVisualizationProvider, levelGradient, LevelBarDirection.Right, 1);
|
||||
//}
|
||||
primary.Brush = new LinearGradientBrush(primaryGradient);
|
||||
primaryGroups.Add((primary, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer, LevelBarDirection.Horizontal, 0, primaryGradient)));
|
||||
break;
|
||||
|
||||
case RGBDeviceType.Mousepad:
|
||||
case RGBDeviceType.LedStripe:
|
||||
case RGBDeviceType.HeadsetStand:
|
||||
ILedGroup left = new RectangleLedGroup(new Rectangle(device.Location.X, device.Location.Y, device.Size.Width / 2.0, device.Size.Height));
|
||||
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));
|
||||
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)));
|
||||
|
||||
IGradient mousepadLevelGradient = new LinearGradient(new GradientStop(0, new Color(0, 0, 255)), new GradientStop(1, new Color(255, 0, 0)));
|
||||
left.Brush = new LevelBarBrush(AudioProcessor.Instance.TertiaryVisualizationProvider, mousepadLevelGradient, LevelBarDirection.Top, 0);
|
||||
right.Brush = new LevelBarBrush(AudioProcessor.Instance.TertiaryVisualizationProvider, mousepadLevelGradient, LevelBarDirection.Top, 1);
|
||||
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), 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 BeatBrush(AudioProcessor.Instance.SecondaryVisualizationProvider, new Color(255, 255, 255));
|
||||
deviceGroup.Brush = new LinearGradientBrush(secondaryGradient);
|
||||
secondaryGroups.Add((deviceGroup, (visualizationType, visualizer) => CreateDecorator(visualizationType, visualizer)));
|
||||
break;
|
||||
}
|
||||
|
||||
surface.Updating += args => AudioProcessor.Instance.Update();
|
||||
_groups[VisualizationIndex.Primary] = primaryGroups;
|
||||
_groups[VisualizationIndex.Secondary] = secondaryGroups;
|
||||
_groups[VisualizationIndex.Tertiary] = tertiaryGroups;
|
||||
|
||||
ApplyVisualization(VisualizationIndex.Primary, Settings[VisualizationIndex.Primary].SelectedVisualization);
|
||||
ApplyVisualization(VisualizationIndex.Secondary, Settings[VisualizationIndex.Secondary].SelectedVisualization);
|
||||
ApplyVisualization(VisualizationIndex.Tertiary, Settings[VisualizationIndex.Tertiary].SelectedVisualization);
|
||||
|
||||
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)
|
||||
{
|
||||
IVisualizationProvider visualizer = AudioVisualizationFactory.Instance.CreateVisualizationProvider(visualizationIndex, visualizationType);
|
||||
Visualizations[visualizationIndex] = visualizer;
|
||||
|
||||
foreach ((ILedGroup group, GetDecoratorFunc getDecoratorFunc) in _groups[visualizationIndex])
|
||||
{
|
||||
group.Brush.RemoveAllDecorators();
|
||||
|
||||
if (visualizer != null)
|
||||
{
|
||||
IBrushDecorator decorator = getDecoratorFunc(visualizationType, visualizer);
|
||||
if (decorator != null)
|
||||
group.Brush.AddDecorator(decorator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, gradient);
|
||||
|
||||
if (visualizationType == VisualizationType.Beat)
|
||||
return new BeatDecorator(visualizationProvider);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OpenConfiguration()
|
||||
@ -130,8 +201,8 @@ namespace KeyboardAudioVisualizer
|
||||
|
||||
private void Exit()
|
||||
{
|
||||
RGBSurface.Instance.Dispose();
|
||||
AudioProcessor.Instance.Dispose();
|
||||
try { AudioVisualizationFactory.Instance?.Dispose(); } catch { }
|
||||
try { RGBSurface.Instance?.Dispose(); } catch { }
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
111
KeyboardAudioVisualizer/Attached/SliderValue.cs
Normal file
111
KeyboardAudioVisualizer/Attached/SliderValue.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Attached
|
||||
{
|
||||
public static class SliderValue
|
||||
{
|
||||
#region Properties & Fields
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
public static readonly DependencyProperty UnitProperty = DependencyProperty.RegisterAttached(
|
||||
"Unit", typeof(string), typeof(SliderValue), new PropertyMetadata(default(string)));
|
||||
|
||||
public static void SetUnit(DependencyObject element, string value) => element.SetValue(UnitProperty, value);
|
||||
public static string GetUnit(DependencyObject element) => (string)element.GetValue(UnitProperty);
|
||||
|
||||
public static readonly DependencyProperty IsShownProperty = DependencyProperty.RegisterAttached(
|
||||
"IsShown", typeof(bool), typeof(SliderValue), new PropertyMetadata(default(bool), IsShownChanged));
|
||||
|
||||
public static void SetIsShown(DependencyObject element, bool value) => element.SetValue(IsShownProperty, value);
|
||||
public static bool GetIsShown(DependencyObject element) => (bool)element.GetValue(IsShownProperty);
|
||||
|
||||
public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.RegisterAttached(
|
||||
"BorderBrush", typeof(Brush), typeof(SliderValue), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public static void SetBorderBrush(DependencyObject element, Brush value) => element.SetValue(BorderBrushProperty, value);
|
||||
public static Brush GetBorderBrush(DependencyObject element) => (Brush)element.GetValue(BorderBrushProperty);
|
||||
|
||||
public static readonly DependencyProperty BackgroundProperty = DependencyProperty.RegisterAttached(
|
||||
"Background", typeof(Brush), typeof(SliderValue), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public static void SetBackground(DependencyObject element, Brush value) => element.SetValue(BackgroundProperty, value);
|
||||
public static Brush GetBackground(DependencyObject element) => (Brush)element.GetValue(BackgroundProperty);
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.RegisterAttached(
|
||||
"Foreground", typeof(Brush), typeof(SliderValue), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public static void SetForeground(DependencyObject element, Brush value) => element.SetValue(ForegroundProperty, value);
|
||||
public static Brush GetForeground(DependencyObject element) => (Brush)element.GetValue(ForegroundProperty);
|
||||
|
||||
public static readonly DependencyProperty FontProperty = DependencyProperty.RegisterAttached(
|
||||
"Font", typeof(FontFamily), typeof(SliderValue), new PropertyMetadata(default(FontFamily)));
|
||||
|
||||
public static void SetFont(DependencyObject element, FontFamily value) => element.SetValue(FontProperty, value);
|
||||
public static FontFamily GetFont(DependencyObject element) => (FontFamily)element.GetValue(FontProperty);
|
||||
|
||||
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.RegisterAttached(
|
||||
"FontSize", typeof(double), typeof(SliderValue), new PropertyMetadata(default(double)));
|
||||
|
||||
public static void SetFontSize(DependencyObject element, double value) => element.SetValue(FontSizeProperty, value);
|
||||
public static double GetFontSize(DependencyObject element) => (double)element.GetValue(FontSizeProperty);
|
||||
|
||||
// ReSharper enable InconsistentNaming
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private static void IsShownChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
||||
{
|
||||
if (!(dependencyObject is Slider slider)) return;
|
||||
|
||||
if (dependencyPropertyChangedEventArgs.NewValue as bool? == true)
|
||||
{
|
||||
slider.MouseEnter += SliderOnMouseEnter;
|
||||
slider.MouseLeave += SliderOnMouseLeave;
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.MouseEnter -= SliderOnMouseEnter;
|
||||
slider.MouseLeave -= SliderOnMouseLeave;
|
||||
RemoveAdorner(slider);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SliderOnMouseEnter(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
if (!(sender is Slider slider)) return;
|
||||
AdornerLayer.GetAdornerLayer(slider)?.Add(new SliderValueAdorner(slider, GetUnit(slider))
|
||||
{
|
||||
BorderBrush = GetBorderBrush(slider),
|
||||
Background = GetBackground(slider),
|
||||
Foreground = GetForeground(slider),
|
||||
Font = GetFont(slider),
|
||||
FontSize = GetFontSize(slider)
|
||||
});
|
||||
}
|
||||
|
||||
private static void SliderOnMouseLeave(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
if (!(sender is Slider slider)) return;
|
||||
RemoveAdorner(slider);
|
||||
}
|
||||
|
||||
private static void RemoveAdorner(Slider slider)
|
||||
{
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(slider);
|
||||
Adorner adorner = adornerLayer?.GetAdorners(slider)?.FirstOrDefault(x => x is SliderValueAdorner);
|
||||
if (adorner != null)
|
||||
{
|
||||
adornerLayer.Remove(adorner);
|
||||
(adorner as SliderValueAdorner)?.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
99
KeyboardAudioVisualizer/Attached/SliderValueAdorner.cs
Normal file
99
KeyboardAudioVisualizer/Attached/SliderValueAdorner.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Attached
|
||||
{
|
||||
public class SliderValueAdorner : System.Windows.Documents.Adorner
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly string _unit;
|
||||
private readonly Slider _slider;
|
||||
private readonly Thumb _thumb;
|
||||
private readonly RepeatButton _decreaseRepeatButton;
|
||||
|
||||
public Brush BorderBrush { get; set; } = Brushes.Black;
|
||||
public Brush Background { get; set; } = Brushes.Black;
|
||||
public Brush Foreground { get; set; } = Brushes.White;
|
||||
public FontFamily Font { get; set; } = new FontFamily("Verdana");
|
||||
public double FontSize { get; set; } = 14;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public SliderValueAdorner(UIElement adornedElement, string unit)
|
||||
: base(adornedElement)
|
||||
{
|
||||
this._unit = unit;
|
||||
|
||||
_slider = (Slider)adornedElement;
|
||||
Track track = (Track)_slider.Template.FindName("PART_Track", _slider);
|
||||
|
||||
_thumb = track.Thumb;
|
||||
_decreaseRepeatButton = track.DecreaseRepeatButton;
|
||||
_decreaseRepeatButton.SizeChanged += OnButtonSizeChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
_decreaseRepeatButton.SizeChanged -= OnButtonSizeChanged;
|
||||
}
|
||||
|
||||
private void OnButtonSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) => InvalidateVisual();
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
double offset = _decreaseRepeatButton.ActualWidth + (_thumb.ActualWidth / 2.0);
|
||||
|
||||
FormattedText text = new FormattedText(GetText(), CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface(Font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), FontSize, Foreground);
|
||||
Geometry border = CreateBorder(offset, text.Width, text.Height);
|
||||
|
||||
drawingContext.DrawGeometry(Background, new Pen(BorderBrush, 1), border);
|
||||
drawingContext.DrawText(text, new Point(offset - (text.Width / 2.0), -26));
|
||||
}
|
||||
|
||||
private string GetText()
|
||||
{
|
||||
string valueText = _slider.Value.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(_unit))
|
||||
valueText += " " + _unit;
|
||||
|
||||
return valueText;
|
||||
}
|
||||
|
||||
private Geometry CreateBorder(double offset, double width, double height)
|
||||
{
|
||||
double halfWidth = width / 2.0;
|
||||
|
||||
PathGeometry borderGeometry = new PathGeometry();
|
||||
PathFigure border = new PathFigure
|
||||
{
|
||||
StartPoint = new Point(offset, 0),
|
||||
IsClosed = true,
|
||||
IsFilled = true
|
||||
};
|
||||
|
||||
border.Segments.Add(new LineSegment(new Point(offset + 4, -6), true));
|
||||
border.Segments.Add(new LineSegment(new Point(offset + 4 + halfWidth, -6), true));
|
||||
border.Segments.Add(new LineSegment(new Point(offset + 4 + halfWidth, -10 - height), true));
|
||||
border.Segments.Add(new LineSegment(new Point(offset - 4 - halfWidth, -10 - height), true));
|
||||
border.Segments.Add(new LineSegment(new Point(offset - 4 - halfWidth, -6), true));
|
||||
border.Segments.Add(new LineSegment(new Point(offset - 4, -6), true));
|
||||
|
||||
borderGeometry.Figures.Add(border);
|
||||
|
||||
return borderGeometry;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
22
KeyboardAudioVisualizer/Attributes/DisplayNameAttribute.cs
Normal file
22
KeyboardAudioVisualizer/Attributes/DisplayNameAttribute.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Attributes
|
||||
{
|
||||
public class DisplayNameAttribute : Attribute
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public DisplayNameAttribute(string displayName)
|
||||
{
|
||||
this.DisplayName = displayName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
23
KeyboardAudioVisualizer/Attributes/VisualizerForAttribute.cs
Normal file
23
KeyboardAudioVisualizer/Attributes/VisualizerForAttribute.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Attributes
|
||||
{
|
||||
public class VisualizerForAttribute : Attribute
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public RGBDeviceType VisualizerFor { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public VisualizerForAttribute(RGBDeviceType visualizerFor)
|
||||
{
|
||||
this.VisualizerFor = visualizerFor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
{
|
||||
public abstract class AbstractAudioProcessor : IAudioProcessor
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public abstract void Initialize();
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public virtual void Dispose() { }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
using System;
|
||||
using KeyboardAudioVisualizer.AudioCapture;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Equalizer;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Spectrum;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
{
|
||||
public class AudioProcessor : IDisposable
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public static AudioProcessor Instance { get; private set; }
|
||||
|
||||
private AudioBuffer _audioBuffer;
|
||||
private IAudioInput _audioInput;
|
||||
private ISpectrumProvider _spectrumProvider;
|
||||
|
||||
public IVisualizationProvider PrimaryVisualizationProvider { get; private set; }
|
||||
public IVisualizationProvider SecondaryVisualizationProvider { get; private set; }
|
||||
public IVisualizationProvider TertiaryVisualizationProvider { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
private AudioProcessor() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Update()
|
||||
{
|
||||
_spectrumProvider.Update();
|
||||
|
||||
PrimaryVisualizationProvider?.Update();
|
||||
SecondaryVisualizationProvider?.Update();
|
||||
TertiaryVisualizationProvider?.Update();
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (Instance != null) return;
|
||||
|
||||
Instance = new AudioProcessor();
|
||||
Instance.InitializeInstance();
|
||||
}
|
||||
|
||||
private void InitializeInstance()
|
||||
{
|
||||
_audioInput = new CSCoreAudioInput();
|
||||
_audioInput.Initialize();
|
||||
|
||||
_audioBuffer = new AudioBuffer(4096); // Working with ~93ms -
|
||||
_audioInput.DataAvailable += (data, offset, count) => _audioBuffer.Put(data, offset, count);
|
||||
|
||||
_spectrumProvider = new FourierSpectrumProvider(_audioBuffer);
|
||||
_spectrumProvider.Initialize();
|
||||
|
||||
//TODO DarthAffe 13.08.2017: Refactore Settings-stuff to work with multiple providers
|
||||
|
||||
MultiBandEqualizer equalizer = new MultiBandEqualizer();
|
||||
ApplicationManager.Instance.Settings.EqualizerConfiguration.LoadInto(equalizer);
|
||||
equalizer.PropertyChanged += (sender, args) => ApplicationManager.Instance.Settings.EqualizerConfiguration.SaveFrom(equalizer);
|
||||
|
||||
PrimaryVisualizationProvider = new FrequencyBarsVisualizationProvider(ApplicationManager.Instance.Settings.FrequencyBarsVisualizationProviderConfiguration, _spectrumProvider) { Equalizer = equalizer };
|
||||
//PrimaryVisualizationProvider = new BeatVisualizationProvider(new BeatVisualizationProviderConfiguration(), _spectrumProvider);
|
||||
PrimaryVisualizationProvider.Initialize();
|
||||
|
||||
SecondaryVisualizationProvider = new BeatVisualizationProvider(ApplicationManager.Instance.Settings.BeatVisualizationProviderConfiguration, _spectrumProvider);
|
||||
SecondaryVisualizationProvider.Initialize();
|
||||
|
||||
TertiaryVisualizationProvider = new LevelVisualizationProvider(ApplicationManager.Instance.Settings.LevelVisualizationProviderConfiguration, _audioBuffer);
|
||||
TertiaryVisualizationProvider.Initialize();
|
||||
}
|
||||
|
||||
public void Dispose() => _audioInput.Dispose();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using KeyboardAudioVisualizer.AudioCapture;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Equalizer;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Spectrum;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
{
|
||||
public class AudioVisualizationFactory : IDisposable
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public static AudioVisualizationFactory Instance { get; private set; }
|
||||
|
||||
private IAudioInput _audioInput;
|
||||
private AudioBuffer _audioBuffer;
|
||||
private readonly List<IAudioProcessor> _processors = new List<IAudioProcessor>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
private AudioVisualizationFactory() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (Instance != null) return;
|
||||
|
||||
Instance = new AudioVisualizationFactory();
|
||||
Instance.InitializeInstance();
|
||||
}
|
||||
|
||||
private void InitializeInstance()
|
||||
{
|
||||
_audioInput = new CSCoreAudioInput();
|
||||
_audioInput.Initialize();
|
||||
|
||||
_audioBuffer = new AudioBuffer(4096); // Working with ~93ms -
|
||||
_audioInput.DataAvailable += (left, right) => _audioBuffer.Put(left, right);
|
||||
|
||||
_processors.Add(new FourierSpectrumProvider(_audioBuffer));
|
||||
|
||||
foreach (IAudioProcessor processor in _processors)
|
||||
processor.Initialize();
|
||||
}
|
||||
|
||||
private T GetAudioProcessor<T>() => (T)_processors.FirstOrDefault(x => x.GetType() == typeof(T));
|
||||
|
||||
public IVisualizationProvider CreateVisualizationProvider(VisualizationIndex visualizationIndex, VisualizationType visualizationType)
|
||||
{
|
||||
IVisualizationProvider visualizationProvider = default;
|
||||
switch (visualizationType)
|
||||
{
|
||||
case VisualizationType.FrequencyBars:
|
||||
MultiBandEqualizer equalizer = new MultiBandEqualizer();
|
||||
ApplicationManager.Instance.Settings[visualizationIndex].EqualizerConfiguration.LoadInto(equalizer);
|
||||
equalizer.PropertyChanged += (sender, args) => ApplicationManager.Instance.Settings[visualizationIndex].EqualizerConfiguration.SaveFrom(equalizer);
|
||||
visualizationProvider = new FrequencyBarsVisualizationProvider(ApplicationManager.Instance.Settings[visualizationIndex].GetConfiguration<FrequencyBarsVisualizationProviderConfiguration>(visualizationType), GetAudioProcessor<FourierSpectrumProvider>()) { Equalizer = equalizer };
|
||||
break;
|
||||
|
||||
case VisualizationType.Level:
|
||||
visualizationProvider = new LevelVisualizationProvider(ApplicationManager.Instance.Settings[visualizationIndex].GetConfiguration<LevelVisualizationProviderConfiguration>(visualizationType), _audioBuffer);
|
||||
break;
|
||||
|
||||
case VisualizationType.Beat:
|
||||
visualizationProvider = new BeatVisualizationProvider(ApplicationManager.Instance.Settings[visualizationIndex].GetConfiguration<BeatVisualizationProviderConfiguration>(visualizationType), GetAudioProcessor<FourierSpectrumProvider>());
|
||||
break;
|
||||
}
|
||||
|
||||
visualizationProvider?.Initialize();
|
||||
return visualizationProvider;
|
||||
}
|
||||
|
||||
public void Dispose() => _audioInput.Dispose();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,11 @@
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
using System;
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing
|
||||
{
|
||||
public interface IAudioProcessor
|
||||
public interface IAudioProcessor : IDisposable
|
||||
{
|
||||
bool IsActive { get; set; }
|
||||
|
||||
void Initialize();
|
||||
void Update();
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ using MathNet.Numerics.IntegralTransforms;
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing.Spectrum
|
||||
{
|
||||
public class FourierSpectrumProvider : ISpectrumProvider
|
||||
public class FourierSpectrumProvider : AbstractAudioProcessor, ISpectrumProvider
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
@ -31,7 +31,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Spectrum
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Initialize()
|
||||
public override void Initialize()
|
||||
{
|
||||
_hamming = Window.Hamming(_audioBuffer.Size);
|
||||
_sampleData = new float[_audioBuffer.Size];
|
||||
@ -40,7 +40,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.Spectrum
|
||||
_spectrum = new float[_usableDataLength];
|
||||
}
|
||||
|
||||
public void Update()
|
||||
public override void Update()
|
||||
{
|
||||
_audioBuffer.CopyMixInto(ref _sampleData, 0);
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Equalizer;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Spectrum;
|
||||
using KeyboardAudioVisualizer.Configuration;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
{
|
||||
@ -79,7 +78,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
#endregion
|
||||
|
||||
public class FrequencyBarsVisualizationProvider : IVisualizationProvider
|
||||
public class FrequencyBarsVisualizationProvider : AbstractAudioProcessor, IVisualizationProvider
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
@ -109,7 +108,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Initialize() => RecalculateConfigValues(null);
|
||||
public override void Initialize() => RecalculateConfigValues(null);
|
||||
|
||||
private void RecalculateConfigValues(string changedPropertyName)
|
||||
{
|
||||
@ -123,7 +122,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
_emphasiseFactor = (0.75 * (1 + _configuration.EmphasisePeaks));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
public override void Update()
|
||||
{
|
||||
ISpectrum spectrum = GetSpectrum();
|
||||
if (spectrum == null) return;
|
||||
|
||||
@ -2,9 +2,12 @@
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
{
|
||||
public interface IVisualizationProvider : IAudioProcessor
|
||||
public interface IVisualizationProvider
|
||||
{
|
||||
IConfiguration Configuration { get; }
|
||||
float[] VisualizationData { get; }
|
||||
|
||||
void Initialize();
|
||||
void Update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Spectrum;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.Spectrum;
|
||||
using KeyboardAudioVisualizer.Configuration;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
|
||||
@ -15,48 +13,14 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
#endregion
|
||||
|
||||
// Port of https://github.com/kctess5/Processing-Beat-Detection
|
||||
public class BeatVisualizationProvider : IVisualizationProvider
|
||||
public class BeatVisualizationProvider : AbstractAudioProcessor, IVisualizationProvider
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
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];
|
||||
@ -75,183 +39,32 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Initialize()
|
||||
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 void Update()
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
#endregion
|
||||
|
||||
public class LevelVisualizationProvider : IVisualizationProvider
|
||||
public class LevelVisualizationProvider : AbstractAudioProcessor, IVisualizationProvider
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
@ -78,11 +78,11 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Initialize()
|
||||
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);
|
||||
}
|
||||
@ -112,7 +112,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
public override void Update()
|
||||
{
|
||||
_audioBuffer.CopyLeftInto(ref _sampleDataLeft, 0);
|
||||
_audioBuffer.CopyRightInto(ref _sampleDataRight, 0);
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
using KeyboardAudioVisualizer.Attributes;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
|
||||
{
|
||||
public enum VisualizationType
|
||||
{
|
||||
None,
|
||||
|
||||
[VisualizerFor(RGBDeviceType.Keyboard | RGBDeviceType.LedMatrix)]
|
||||
[DisplayName("Frequency Bars")]
|
||||
FrequencyBars,
|
||||
|
||||
[VisualizerFor(RGBDeviceType.Keyboard | RGBDeviceType.LedMatrix | RGBDeviceType.LedStripe | RGBDeviceType.Mousepad)]
|
||||
Level,
|
||||
|
||||
Beat,
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Brushes
|
||||
{
|
||||
public class BeatBrush : AbstractBrush
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly IVisualizationProvider _visualizationProvider;
|
||||
private readonly Color _color;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public BeatBrush(IVisualizationProvider visualizationProvider, Color color)
|
||||
{
|
||||
this._visualizationProvider = visualizationProvider;
|
||||
this._color = color;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget)
|
||||
{
|
||||
Color color = new Color(_color);
|
||||
color.APercent *= _visualizationProvider.VisualizationData[0];
|
||||
return color;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using RGB.NET.Brushes;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Brushes
|
||||
{
|
||||
public class LevelBarBrush : LinearGradientBrush
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly IVisualizationProvider _visualizationProvider;
|
||||
public LevelBarDirection Direction { get; set; }
|
||||
public int DataIndex { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public LevelBarBrush(IVisualizationProvider visualizationProvider, IGradient gradient, LevelBarDirection direction, int dataIndex)
|
||||
: base(gradient)
|
||||
{
|
||||
this._visualizationProvider = visualizationProvider;
|
||||
this.Direction = direction;
|
||||
this.DataIndex = dataIndex;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget)
|
||||
{
|
||||
double offset = CalculateOffset(rectangle, renderTarget);
|
||||
return offset < _visualizationProvider.VisualizationData[DataIndex] ? Gradient.GetColor(offset) : Color.Transparent;
|
||||
}
|
||||
|
||||
private double CalculateOffset(Rectangle rectangle, BrushRenderTarget renderTarget)
|
||||
{
|
||||
switch (Direction)
|
||||
{
|
||||
case LevelBarDirection.Left:
|
||||
return (rectangle.Size.Width - renderTarget.Rectangle.Center.X) / rectangle.Size.Width;
|
||||
|
||||
case LevelBarDirection.Right:
|
||||
return renderTarget.Rectangle.Center.X / rectangle.Size.Width;
|
||||
|
||||
case LevelBarDirection.Top:
|
||||
return (rectangle.Size.Height - renderTarget.Rectangle.Center.Y) / rectangle.Size.Height;
|
||||
|
||||
case LevelBarDirection.Bottom:
|
||||
return renderTarget.Rectangle.Center.Y / rectangle.Size.Height;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Data
|
||||
|
||||
public enum LevelBarDirection
|
||||
{
|
||||
Left, Right, Top, Bottom
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,6 @@
|
||||
|
||||
namespace KeyboardAudioVisualizer.Configuration
|
||||
{
|
||||
// DarthAffe 05.08.2017: Marker interface
|
||||
public interface IConfiguration : INotifyPropertyChanged { }
|
||||
public interface IConfiguration : INotifyPropertyChanged
|
||||
{ }
|
||||
}
|
||||
|
||||
@ -1,24 +1,121 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using System;
|
||||
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 General
|
||||
#region Constants
|
||||
|
||||
public double UpdateRate { get; set; } = 40.0;
|
||||
public const int CURRENT_VERSION = 1;
|
||||
|
||||
#endregion
|
||||
|
||||
#region AudioProcessing
|
||||
#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]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Visualizations.TryGetValue(visualizationIndex, out VisualizationSettings settings))
|
||||
Visualizations[visualizationIndex] = (settings = new VisualizationSettings(visualizationIndex));
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class VisualizationSettings
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public VisualizationType SelectedVisualization { get; set; }
|
||||
|
||||
public LinearGradient Gradient { get; set; }
|
||||
|
||||
public EqualizerConfiguration EqualizerConfiguration { get; set; } = new EqualizerConfiguration();
|
||||
|
||||
public FrequencyBarsVisualizationProviderConfiguration FrequencyBarsVisualizationProviderConfiguration { get; set; } = new FrequencyBarsVisualizationProviderConfiguration();
|
||||
public FrequencyBarsVisualizationProviderConfiguration FrequencyBarsConfiguration { get; set; } = new FrequencyBarsVisualizationProviderConfiguration();
|
||||
public LevelVisualizationProviderConfiguration LevelConfiguration { get; set; } = new LevelVisualizationProviderConfiguration();
|
||||
public BeatVisualizationProviderConfiguration BeatConfiguration { get; set; } = new BeatVisualizationProviderConfiguration();
|
||||
|
||||
public LevelVisualizationProviderConfiguration LevelVisualizationProviderConfiguration { get; set; } = new LevelVisualizationProviderConfiguration();
|
||||
public IConfiguration this[VisualizationType visualizationType]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (visualizationType)
|
||||
{
|
||||
case VisualizationType.None:
|
||||
return null;
|
||||
|
||||
public BeatVisualizationProviderConfiguration BeatVisualizationProviderConfiguration { get; set; } = new BeatVisualizationProviderConfiguration();
|
||||
case VisualizationType.FrequencyBars:
|
||||
return FrequencyBarsConfiguration;
|
||||
|
||||
case VisualizationType.Level:
|
||||
return LevelConfiguration;
|
||||
|
||||
case VisualizationType.Beat:
|
||||
return BeatConfiguration;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(visualizationType), visualizationType, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public VisualizationSettings(VisualizationIndex visualizationIndex)
|
||||
{
|
||||
switch (visualizationIndex)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public T GetConfiguration<T>(VisualizationType visualizationType)
|
||||
where T : IConfiguration, new() => (T)this[visualizationType];
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using KeyboardAudioVisualizer.Attributes;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using VisualizationType = KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider.VisualizationType;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Converter
|
||||
{
|
||||
[ValueConversion(typeof(VisualizationType), typeof(string))]
|
||||
public class VisualizationProviderDisplayNameConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is VisualizationType visualizationType)) return null;
|
||||
return visualizationType.GetAttribute<DisplayNameAttribute>()?.DisplayName ?? visualizationType.ToString();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotSupportedException();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.UI.Visualization;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Converter
|
||||
{
|
||||
[ValueConversion(typeof(IVisualizationProvider), typeof(bool))]
|
||||
public class VisualizationToLastChildFillConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value is FrequencyBarsVisualizationProvider;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotSupportedException();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
using KeyboardAudioVisualizer.Attributes;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Core;
|
||||
using VisualizationType = KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider.VisualizationType;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Converter
|
||||
{
|
||||
[ValueConversion(typeof(IEnumerable<VisualizationType>), typeof(IEnumerable<VisualizationType>))]
|
||||
public class VisualizationTypeSelectableConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is IEnumerable<VisualizationType> visualizationProviders) || !(parameter is RGBDeviceType targetDevice)) return new List<VisualizationType>();
|
||||
return visualizationProviders.Where(x => x.GetAttribute<VisualizerForAttribute>()?.VisualizerFor.HasFlag(targetDevice) ?? true).ToList();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotSupportedException();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
31
KeyboardAudioVisualizer/Decorators/BeatDecorator.cs
Normal file
31
KeyboardAudioVisualizer/Decorators/BeatDecorator.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Decorators
|
||||
{
|
||||
public class BeatDecorator : AbstractUpdateAwareDecorator, IBrushDecorator
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly IVisualizationProvider _visualizationProvider;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public BeatDecorator(IVisualizationProvider visualizationProvider)
|
||||
{
|
||||
this._visualizationProvider = visualizationProvider;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void Update(double deltaTime) => _visualizationProvider.Update();
|
||||
|
||||
#endregion
|
||||
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetA(color.A * _visualizationProvider.VisualizationData[0]);
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,12 @@
|
||||
using System;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using RGB.NET.Brushes;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
using Color = RGB.NET.Core.Color;
|
||||
using Rectangle = RGB.NET.Core.Rectangle;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Brushes
|
||||
namespace KeyboardAudioVisualizer.Decorators
|
||||
{
|
||||
public class FrequencyBarsBrush : LinearGradientBrush
|
||||
public class FrequencyBarsDecorator : AbstractUpdateAwareDecorator, IBrushDecorator
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
@ -18,8 +16,7 @@ namespace KeyboardAudioVisualizer.Brushes
|
||||
|
||||
#region Constructors
|
||||
|
||||
public FrequencyBarsBrush(IVisualizationProvider visualizationProvider, IGradient gradient)
|
||||
: base(gradient)
|
||||
public FrequencyBarsDecorator(IVisualizationProvider visualizationProvider)
|
||||
{
|
||||
this._visualizationProvider = visualizationProvider;
|
||||
}
|
||||
@ -28,13 +25,15 @@ namespace KeyboardAudioVisualizer.Brushes
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget)
|
||||
protected override void Update(double deltaTime) => _visualizationProvider.Update();
|
||||
|
||||
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)
|
||||
{
|
||||
int barSampleIndex = (int)Math.Floor(_visualizationProvider.VisualizationData.Length * (renderTarget.Point.X / (rectangle.Location.X + rectangle.Size.Width)));
|
||||
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);
|
||||
|
||||
return curBarHeight <= verticalPos ? base.GetColorAtPoint(rectangle, renderTarget) : Color.Transparent;
|
||||
return curBarHeight > verticalPos ? color.SetA(0) : color;
|
||||
}
|
||||
|
||||
#endregion
|
||||
105
KeyboardAudioVisualizer/Decorators/LevelBarDecorator.cs
Normal file
105
KeyboardAudioVisualizer/Decorators/LevelBarDecorator.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using RGB.NET.Brushes.Gradients;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Decorators
|
||||
{
|
||||
public class LevelBarDecorator : AbstractUpdateAwareDecorator, IBrushDecorator
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
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, LinearGradient gradient)
|
||||
{
|
||||
this._visualizationProvider = visualizationProvider;
|
||||
this.Direction = direction;
|
||||
this.DataIndex = dataIndex;
|
||||
this.Gradient = gradient;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void Update(double deltaTime) => _visualizationProvider.Update();
|
||||
|
||||
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])
|
||||
return color.SetA(0);
|
||||
else
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset *= 2;
|
||||
if (offset >= _visualizationProvider.VisualizationData[1])
|
||||
return color.SetA(0);
|
||||
else
|
||||
return Gradient.GetColor(offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset >= _visualizationProvider.VisualizationData[DataIndex])
|
||||
return color.SetA(0);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
private double CalculateOffset(Rectangle rectangle, BrushRenderTarget renderTarget)
|
||||
{
|
||||
switch (Direction)
|
||||
{
|
||||
case LevelBarDirection.Left:
|
||||
return (rectangle.Size.Width - renderTarget.Rectangle.Center.X) / rectangle.Size.Width;
|
||||
|
||||
case LevelBarDirection.Right:
|
||||
return renderTarget.Rectangle.Center.X / rectangle.Size.Width;
|
||||
|
||||
case LevelBarDirection.Top:
|
||||
return (rectangle.Size.Height - renderTarget.Rectangle.Center.Y) / rectangle.Size.Height;
|
||||
|
||||
case LevelBarDirection.Bottom:
|
||||
return renderTarget.Rectangle.Center.Y / rectangle.Size.Height;
|
||||
|
||||
case LevelBarDirection.Horizontal:
|
||||
return (renderTarget.Rectangle.Center.X / rectangle.Size.Width) - 0.5;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Data
|
||||
|
||||
public enum LevelBarDirection
|
||||
{
|
||||
Left, Right, Top, Bottom,
|
||||
|
||||
//HACK DarthAffe 12.09.2017: Just a bad workaround ...
|
||||
Horizontal
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
15
KeyboardAudioVisualizer/Helper/EnumExtension.cs
Normal file
15
KeyboardAudioVisualizer/Helper/EnumExtension.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Helper
|
||||
{
|
||||
public static class EnumExtension
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public static T GetAttribute<T>(this Enum e)
|
||||
where T : Attribute => e.GetType().GetMember(e.ToString()).FirstOrDefault()?.GetCustomAttributes(typeof(T), false).FirstOrDefault() as T;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,8 @@ namespace KeyboardAudioVisualizer.Helper
|
||||
{
|
||||
if (ex == null) return string.Empty;
|
||||
|
||||
message += ex.Message;
|
||||
|
||||
if (ex.InnerException != null)
|
||||
message += "\r\nInnerException: " + GetFullMessage(ex.InnerException);
|
||||
|
||||
|
||||
309
KeyboardAudioVisualizer/Helper/ObservableDictionary.cs
Normal file
309
KeyboardAudioVisualizer/Helper/ObservableDictionary.cs
Normal file
@ -0,0 +1,309 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
|
||||
// Taken from https://codereview.stackexchange.com/questions/116562/custom-implementation-of-observabledictionary
|
||||
namespace KeyboardAudioVisualizer.Helper
|
||||
{
|
||||
public class ObservableDictionary<TKey, TValue> : AbstractBindable, IDictionary<TKey, TValue>, INotifyCollectionChanged
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string INDEXER_NAME = "Item[]";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly IList<TValue> _values;
|
||||
private readonly IDictionary<TKey, int> _indexMap;
|
||||
|
||||
private readonly SimpleMonitor _monitor = new SimpleMonitor();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public ObservableDictionary()
|
||||
{
|
||||
_values = new List<TValue>();
|
||||
_indexMap = new Dictionary<TKey, int>();
|
||||
}
|
||||
|
||||
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
_values = new List<TValue>();
|
||||
_indexMap = new Dictionary<TKey, int>();
|
||||
|
||||
int idx = 0;
|
||||
foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
|
||||
{
|
||||
_indexMap.Add(kvp.Key, idx);
|
||||
_values.Add(kvp.Value);
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableDictionary(int capacity)
|
||||
{
|
||||
_values = new List<TValue>(capacity);
|
||||
_indexMap = new Dictionary<TKey, int>(capacity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Virtual Add/Remove/Change Control Methods
|
||||
|
||||
protected virtual void AddItem(TKey key, TValue value)
|
||||
{
|
||||
CheckReentrancy();
|
||||
|
||||
int index = _values.Count;
|
||||
_indexMap.Add(key, index);
|
||||
_values.Add(value);
|
||||
|
||||
OnPropertyChanged(nameof(Count));
|
||||
OnPropertyChanged(nameof(Keys));
|
||||
OnPropertyChanged(nameof(Values));
|
||||
OnPropertyChanged(INDEXER_NAME);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Add, key, value, index);
|
||||
}
|
||||
|
||||
protected virtual bool RemoveItem(TKey key)
|
||||
{
|
||||
CheckReentrancy();
|
||||
|
||||
int index = _indexMap[key];
|
||||
TValue value = _values[index];
|
||||
|
||||
if (_indexMap.Remove(key))
|
||||
{
|
||||
_values.RemoveAt(index);
|
||||
|
||||
List<TKey> keys = _indexMap.Keys.ToList();
|
||||
|
||||
foreach (TKey existingKey in keys)
|
||||
{
|
||||
if (_indexMap[existingKey] > index)
|
||||
_indexMap[existingKey]--;
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(Count));
|
||||
OnPropertyChanged(nameof(Keys));
|
||||
OnPropertyChanged(nameof(Values));
|
||||
OnPropertyChanged(INDEXER_NAME);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Remove, key, value, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool RemoveItem(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
CheckReentrancy();
|
||||
|
||||
if (_indexMap.ContainsKey(item.Key) && _values[_indexMap[item.Key]].Equals(item.Value))
|
||||
{
|
||||
int index = _indexMap[item.Key];
|
||||
TValue value = _values[index];
|
||||
|
||||
_indexMap.Remove(item.Key);
|
||||
_values.RemoveAt(index);
|
||||
|
||||
List<TKey> keys = _indexMap.Keys.ToList();
|
||||
|
||||
foreach (TKey existingKey in keys)
|
||||
{
|
||||
if (_indexMap[existingKey] > index)
|
||||
_indexMap[existingKey]--;
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(Count));
|
||||
OnPropertyChanged(nameof(Keys));
|
||||
OnPropertyChanged(nameof(Values));
|
||||
OnPropertyChanged(INDEXER_NAME);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Remove, item.Key, item.Value, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void RemoveAllItems()
|
||||
{
|
||||
|
||||
CheckReentrancy();
|
||||
_values.Clear();
|
||||
_indexMap.Clear();
|
||||
|
||||
OnPropertyChanged(nameof(Count));
|
||||
OnPropertyChanged(nameof(Keys));
|
||||
OnPropertyChanged(nameof(Values));
|
||||
OnPropertyChanged(INDEXER_NAME);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Reset);
|
||||
}
|
||||
|
||||
protected virtual void ChangeItem(TKey key, TValue newValue)
|
||||
{
|
||||
|
||||
CheckReentrancy();
|
||||
|
||||
if (!_indexMap.ContainsKey(key))
|
||||
AddItem(key, newValue);
|
||||
else
|
||||
{
|
||||
int index = _indexMap[key];
|
||||
TValue oldValue = _values[index];
|
||||
_values[index] = newValue;
|
||||
|
||||
OnPropertyChanged(nameof(Values));
|
||||
OnPropertyChanged(INDEXER_NAME);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Replace, key, oldValue, newValue, index);
|
||||
}
|
||||
}
|
||||
|
||||
protected IDisposable BlockReentrancy()
|
||||
{
|
||||
_monitor.Enter();
|
||||
return (IDisposable)_monitor;
|
||||
}
|
||||
|
||||
protected void CheckReentrancy()
|
||||
{
|
||||
// ISSUE: reference to a compiler-generated field
|
||||
// ISSUE: reference to a compiler-generated field
|
||||
if (_monitor.Busy && CollectionChanged != null && CollectionChanged.GetInvocationList().Length > 1)
|
||||
throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed");
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDictionary<TKey,TValue> Members
|
||||
|
||||
public void Add(TKey key, TValue value) => AddItem(key, value);
|
||||
|
||||
public bool ContainsKey(TKey key) => _indexMap.ContainsKey(key);
|
||||
|
||||
public bool Remove(TKey key) => RemoveItem(key);
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
if (_indexMap.TryGetValue(key, out int index))
|
||||
{
|
||||
value = _values[index];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ICollection<TKey> Keys => _indexMap.Keys;
|
||||
|
||||
public ICollection<TValue> Values => _values;
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = _indexMap[key];
|
||||
return _values[index];
|
||||
}
|
||||
set => ChangeItem(key, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICollection<KeyValuePair<TKey,TValue>> Members
|
||||
|
||||
public void Clear() => RemoveAllItems();
|
||||
|
||||
public int Count => _indexMap.Count;
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) => _indexMap.ContainsKey(item.Key) && _values[_indexMap[item.Key]].Equals(item.Value);
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
foreach (KeyValuePair<TKey, int> kvp in _indexMap)
|
||||
{
|
||||
array[arrayIndex] = new KeyValuePair<TKey, TValue>(kvp.Key, _values[kvp.Value]);
|
||||
arrayIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) => RemoveItem(item);
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<TKey, int> kvp in _indexMap)
|
||||
{
|
||||
KeyValuePair<TKey, TValue> pair = new KeyValuePair<TKey, TValue>(kvp.Key, _values[kvp.Value]);
|
||||
yield return pair;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable Members
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
#endregion
|
||||
|
||||
#region INotifyCollectionChanged Members
|
||||
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
NotifyCollectionChangedEventHandler handler = CollectionChanged;
|
||||
|
||||
using (BlockReentrancy())
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected void OnCollectionChanged(NotifyCollectionChangedAction action) => OnCollectionChanged(new NotifyCollectionChangedEventArgs(action));
|
||||
|
||||
protected void OnCollectionChanged(NotifyCollectionChangedAction action, TKey key, TValue value, int index) => OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, new KeyValuePair<TKey, TValue>(key, value), index));
|
||||
|
||||
protected void OnCollectionChanged(NotifyCollectionChangedAction action, TKey key, TValue oldValue, TValue newValue, int index)
|
||||
{
|
||||
KeyValuePair<TKey, TValue> newPair = new KeyValuePair<TKey, TValue>(key, newValue);
|
||||
KeyValuePair<TKey, TValue> oldPair = new KeyValuePair<TKey, TValue>(key, oldValue);
|
||||
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newPair, oldPair, index));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private class SimpleMonitor : IDisposable
|
||||
{
|
||||
private int _busyCount;
|
||||
|
||||
public bool Busy => _busyCount > 0;
|
||||
|
||||
public void Enter() => _busyCount = _busyCount + 1;
|
||||
|
||||
public void Dispose() => _busyCount = _busyCount - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
9
KeyboardAudioVisualizer/Helper/VisualizationIndex.cs
Normal file
9
KeyboardAudioVisualizer/Helper/VisualizationIndex.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace KeyboardAudioVisualizer.Helper
|
||||
{
|
||||
public enum VisualizationIndex
|
||||
{
|
||||
Primary,
|
||||
Secondary,
|
||||
Tertiary
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@ -34,47 +35,75 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<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="RGB.NET.Brushes">
|
||||
<HintPath>..\packages\RGB.NET.Brushes.1.0.0\lib\net45\RGB.NET.Brushes.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<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.Core">
|
||||
<HintPath>..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.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.Devices.CoolerMaster">
|
||||
<HintPath>..\packages\RGB.NET.Devices.CoolerMaster.1.0.0\lib\net45\RGB.NET.Devices.CoolerMaster.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.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.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.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.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.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.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.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.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="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" />
|
||||
@ -97,15 +126,20 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Attached\SliderValue.cs" />
|
||||
<Compile Include="Attached\SliderValueAdorner.cs" />
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ApplicationManager.cs" />
|
||||
<Compile Include="Attributes\DisplayNameAttribute.cs" />
|
||||
<Compile Include="Attributes\VisualizerForAttribute.cs" />
|
||||
<Compile Include="AudioCapture\AudioBuffer.cs" />
|
||||
<Compile Include="AudioCapture\CSCoreAudioInput.cs" />
|
||||
<Compile Include="AudioCapture\IAudioInput.cs" />
|
||||
<Compile Include="AudioProcessing\AudioProcessor.cs" />
|
||||
<Compile Include="AudioProcessing\AbstractAudioProcessor.cs" />
|
||||
<Compile Include="AudioProcessing\AudioVisualizationFactory.cs" />
|
||||
<Compile Include="AudioProcessing\Equalizer\EqualizerBand.cs" />
|
||||
<Compile Include="AudioProcessing\Equalizer\IEqualizer.cs" />
|
||||
<Compile Include="AudioProcessing\Equalizer\MultiBandEqualizer.cs" />
|
||||
@ -123,13 +157,20 @@
|
||||
<Compile Include="AudioProcessing\VisualizationProvider\IVisualizationProvider.cs" />
|
||||
<Compile Include="AudioProcessing\VisualizationProvider\LevelVisualizationProvider.cs" />
|
||||
<Compile Include="AudioProcessing\Spectrum\RawSpectrumProvider.cs" />
|
||||
<Compile Include="Brushes\BeatBrush.cs" />
|
||||
<Compile Include="Brushes\FrequencyBarsBrush.cs" />
|
||||
<Compile Include="Brushes\LevelBarBrush.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" />
|
||||
<Compile Include="Decorators\BeatDecorator.cs" />
|
||||
<Compile Include="Decorators\FrequencyBarsDecorator.cs" />
|
||||
<Compile Include="Decorators\LevelBarDecorator.cs" />
|
||||
<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" />
|
||||
@ -137,12 +178,19 @@
|
||||
<Compile Include="Converter\OffsetToPosXConverter.cs" />
|
||||
<Compile Include="Converter\ValueToPosYConverter.cs" />
|
||||
<Compile Include="Helper\ActionCommand.cs" />
|
||||
<Compile Include="Helper\EnumExtension.cs" />
|
||||
<Compile Include="Helper\ExceptionExtension.cs" />
|
||||
<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">
|
||||
<DependentUpon>ConfigurationWindow.xaml</DependentUpon>
|
||||
@ -154,7 +202,7 @@
|
||||
<Compile Include="UI\Visualization\LevelVisualizer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Helper\SerializationHelper.cs" />
|
||||
<Compile Include="Legacy\SerializationHelper.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@ -173,7 +221,6 @@
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<None Include="NuGet.Config" />
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
@ -199,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>
|
||||
@ -211,6 +262,14 @@
|
||||
<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>
|
||||
</Page>
|
||||
<Page Include="Styles\ImageButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -227,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>
|
||||
@ -275,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>
|
||||
@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>
|
||||
56
KeyboardAudioVisualizer/Legacy/ConfigurationMigrator.cs
Normal file
56
KeyboardAudioVisualizer/Legacy/ConfigurationMigrator.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System.IO;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Legacy
|
||||
{
|
||||
public static class ConfigurationMigrator
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string PATH_V1_SETTINGS = "Settings.xml";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static Configuration.Settings MigrateOldConfig()
|
||||
{
|
||||
if (!File.Exists(PATH_V1_SETTINGS)) return null;
|
||||
|
||||
try
|
||||
{
|
||||
Settings oldSettings = SerializationHelper.LoadObjectFromFile<Settings>(PATH_V1_SETTINGS);
|
||||
Configuration.Settings settings = new Configuration.Settings { UpdateRate = oldSettings.UpdateRate };
|
||||
|
||||
settings[VisualizationIndex.Primary].SelectedVisualization = VisualizationType.FrequencyBars;
|
||||
settings[VisualizationIndex.Primary].FrequencyBarsConfiguration = oldSettings.FrequencyBarsVisualizationProviderConfiguration;
|
||||
settings[VisualizationIndex.Primary].EqualizerConfiguration = oldSettings.EqualizerConfiguration;
|
||||
|
||||
settings[VisualizationIndex.Secondary].SelectedVisualization = VisualizationType.Beat;
|
||||
settings[VisualizationIndex.Secondary].BeatConfiguration = oldSettings.BeatVisualizationProviderConfiguration;
|
||||
|
||||
settings[VisualizationIndex.Tertiary].SelectedVisualization = VisualizationType.Level;
|
||||
settings[VisualizationIndex.Tertiary].LevelConfiguration = oldSettings.LevelVisualizationProviderConfiguration;
|
||||
|
||||
return settings;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CleanupOldConfigs()
|
||||
{
|
||||
if (File.Exists(PATH_V1_SETTINGS))
|
||||
File.Delete(PATH_V1_SETTINGS);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Helper
|
||||
namespace KeyboardAudioVisualizer.Legacy
|
||||
{
|
||||
public static class SerializationHelper
|
||||
{
|
||||
26
KeyboardAudioVisualizer/Legacy/Settings.cs
Normal file
26
KeyboardAudioVisualizer/Legacy/Settings.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Configuration;
|
||||
|
||||
namespace KeyboardAudioVisualizer.Legacy
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
#region General
|
||||
|
||||
public double UpdateRate { get; set; } = 40.0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region AudioProcessing
|
||||
|
||||
public EqualizerConfiguration EqualizerConfiguration { get; set; } = new EqualizerConfiguration();
|
||||
|
||||
public FrequencyBarsVisualizationProviderConfiguration FrequencyBarsVisualizationProviderConfiguration { get; set; } = new FrequencyBarsVisualizationProviderConfiguration();
|
||||
|
||||
public LevelVisualizationProviderConfiguration LevelVisualizationProviderConfiguration { get; set; } = new LevelVisualizationProviderConfiguration();
|
||||
|
||||
public BeatVisualizationProviderConfiguration BeatVisualizationProviderConfiguration { get; set; } = new BeatVisualizationProviderConfiguration();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
@ -12,7 +10,7 @@ using System.Windows;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("KeyboardAudioVisualizer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyCopyright("Copyright © Wyrez 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@ -51,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.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("1.3.1.1")]
|
||||
[assembly: AssemblyFileVersion("1.3.1.1")]
|
||||
|
||||
@ -8,11 +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" />
|
||||
@ -21,11 +24,12 @@
|
||||
<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}" />
|
||||
<Style TargetType="Button" BasedOn="{StaticResource StyleButton}" />
|
||||
<Style TargetType="Slider" BasedOn="{StaticResource StyleSlider}" />
|
||||
|
||||
</styles:CachedResourceDictionary>
|
||||
|
||||
|
||||
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>
|
||||
31
KeyboardAudioVisualizer/Styles/Slider.xaml
Normal file
31
KeyboardAudioVisualizer/Styles/Slider.xaml
Normal file
@ -0,0 +1,31 @@
|
||||
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
|
||||
xmlns:attached="clr-namespace:KeyboardAudioVisualizer.Attached">
|
||||
|
||||
<styles:CachedResourceDictionary.MergedDictionaries>
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
|
||||
</styles:CachedResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style x:Key="StyleSlider"
|
||||
BasedOn="{StaticResource {x:Type Slider}}"
|
||||
TargetType="Slider">
|
||||
|
||||
<!-- ReSharper disable Xaml.RedundantStyledValue - -->
|
||||
<Setter Property="attached:SliderValue.IsShown" Value="True" />
|
||||
<Setter Property="attached:SliderValue.Background" Value="{StaticResource BrushTooltipBackground}" />
|
||||
<Setter Property="attached:SliderValue.BorderBrush" Value="{StaticResource BrushTooltipBorder}" />
|
||||
<Setter Property="attached:SliderValue.Foreground" Value="{StaticResource BrushTooltipForeground}" />
|
||||
<Setter Property="attached:SliderValue.FontSize" Value="{StaticResource FontSizeTooltip}" />
|
||||
<Setter Property="attached:SliderValue.Font" Value="pack://application:,,,/Resources/#Cinzel" />
|
||||
<!-- ReSharper restore Xaml.RedundantStyledValue -->
|
||||
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Opacity" Value="0.2" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
</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>
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
|
||||
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
|
||||
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:attached="clr-namespace:KeyboardAudioVisualizer.Attached">
|
||||
|
||||
<styles:CachedResourceDictionary.MergedDictionaries>
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
|
||||
@ -13,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>
|
||||
@ -38,50 +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}"/>
|
||||
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}"/>
|
||||
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"
|
||||
Value="{Binding Bars}" />
|
||||
</controls:Formular>
|
||||
<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: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"
|
||||
Value="{Binding MinFrequency}" />
|
||||
<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"
|
||||
Value="{Binding MaxFrequency}" />
|
||||
<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}" />
|
||||
</controls:Formular>
|
||||
Value="{Binding Gamma}"
|
||||
ToolTip="Only used if 'Gamma' is selected as spectrum!
Higher values cause more compression of high frequencies." />
|
||||
</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"
|
||||
Value="{Binding ReferenceLevel}" />
|
||||
<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"
|
||||
Value="{Binding Smoothing}" />
|
||||
<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"
|
||||
Value="{Binding EmphasisePeaks}" />
|
||||
</controls:Formular>
|
||||
<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: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,24 +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}"/>
|
||||
</controls:Formular>
|
||||
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: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"
|
||||
Value="{Binding Scale}" />
|
||||
</controls:Formular>
|
||||
<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: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"
|
||||
Value="{Binding Smoothing}" />
|
||||
</controls:Formular>
|
||||
<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:Form>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
|
||||
using KeyboardAudioVisualizer.Helper;
|
||||
using RGB.NET.Core;
|
||||
|
||||
@ -14,16 +15,56 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
public VisualizationType SelectedPrimaryVisualization
|
||||
{
|
||||
get => ApplicationManager.Instance.Settings[VisualizationIndex.Primary].SelectedVisualization;
|
||||
set
|
||||
{
|
||||
ApplicationManager.Instance.Settings[VisualizationIndex.Primary].SelectedVisualization = value;
|
||||
ApplicationManager.Instance.ApplyVisualization(VisualizationIndex.Primary, value);
|
||||
}
|
||||
}
|
||||
|
||||
public VisualizationType SelectedSecondaryVisualization
|
||||
{
|
||||
get => ApplicationManager.Instance.Settings[VisualizationIndex.Secondary].SelectedVisualization;
|
||||
set
|
||||
{
|
||||
ApplicationManager.Instance.Settings[VisualizationIndex.Secondary].SelectedVisualization = value;
|
||||
ApplicationManager.Instance.ApplyVisualization(VisualizationIndex.Secondary, value);
|
||||
}
|
||||
}
|
||||
|
||||
public VisualizationType SelectedTertiaryVisualization
|
||||
{
|
||||
get => ApplicationManager.Instance.Settings[VisualizationIndex.Tertiary].SelectedVisualization;
|
||||
set
|
||||
{
|
||||
ApplicationManager.Instance.Settings[VisualizationIndex.Tertiary].SelectedVisualization = value;
|
||||
ApplicationManager.Instance.ApplyVisualization(VisualizationIndex.Tertiary, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Commands
|
||||
|
||||
@ -7,12 +7,18 @@
|
||||
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
|
||||
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
|
||||
xmlns:core="clr-namespace:RGB.NET.Core;assembly=RGB.NET.Core"
|
||||
xmlns:audioProcessing="clr-namespace:KeyboardAudioVisualizer.AudioProcessing"
|
||||
xmlns:keyboardAudioVisualizer="clr-namespace:KeyboardAudioVisualizer"
|
||||
xmlns:converter="clr-namespace:KeyboardAudioVisualizer.Converter"
|
||||
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
|
||||
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>
|
||||
@ -25,6 +31,20 @@
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Configuration/BeatConfiguration.xaml" />
|
||||
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Visualization/BeatVisualization.xaml" />
|
||||
</styles:CachedResourceDictionary.MergedDictionaries>
|
||||
|
||||
<converter:VisualizationTypeSelectableConverter x:Key="VisualizationProviderSelectableConverter" />
|
||||
<converter:VisualizationProviderDisplayNameConverter x:Key="VisualizationProviderDisplayNameConverter" />
|
||||
<converter:VisualizationToLastChildFillConverter x:Key="VisualizationToLastChildFillConverter" />
|
||||
|
||||
<DataTemplate x:Key="DataTemplateVisualizationSelection" DataType="{x:Type visualizationProvider:VisualizationType}">
|
||||
<TextBlock Text="{Binding Converter={StaticResource VisualizationProviderDisplayNameConverter}}" />
|
||||
</DataTemplate>
|
||||
|
||||
<ObjectDataProvider x:Key="DataProviderVisualizationTypes" ObjectType="{x:Type sys:Enum}" MethodName="GetValues">
|
||||
<ObjectDataProvider.MethodParameters>
|
||||
<x:Type TypeName="visualizationProvider:VisualizationType" />
|
||||
</ObjectDataProvider.MethodParameters>
|
||||
</ObjectDataProvider>
|
||||
</styles:CachedResourceDictionary>
|
||||
</controls:BlurredDecorationWindow.Resources>
|
||||
|
||||
@ -34,140 +54,180 @@
|
||||
|
||||
<TabControl Style="{StaticResource StyleTabControlNavigation}">
|
||||
<TabItem Header="Keyboard">
|
||||
<DockPanel>
|
||||
<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>
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Primary], Converter={StaticResource VisualizationToLastChildFillConverter}}">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<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">
|
||||
<ComboBox.Items>
|
||||
<ComboBoxItem>Frequency Bars</ComboBoxItem>
|
||||
</ComboBox.Items>
|
||||
</ComboBox>
|
||||
</controls:Formular>
|
||||
</GroupBox>
|
||||
<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>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=PrimaryVisualizationProvider.Configuration}" />
|
||||
</GroupBox>
|
||||
<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:Form>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0">
|
||||
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=PrimaryVisualizationProvider}" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Primary].Configuration}" />
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Primary]}" Tag="0" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Mouse/Headset">
|
||||
<DockPanel LastChildFill="False">
|
||||
<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>
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Secondary], Converter={StaticResource VisualizationToLastChildFillConverter}}">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<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">
|
||||
<ComboBox.Items>
|
||||
<ComboBoxItem>Beat-Detection</ComboBoxItem>
|
||||
</ComboBox.Items>
|
||||
</ComboBox>
|
||||
</controls:Formular>
|
||||
</GroupBox>
|
||||
<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>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=SecondaryVisualizationProvider.Configuration}" />
|
||||
</GroupBox>
|
||||
<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:Form>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=SecondaryVisualizationProvider}" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Secondary].Configuration}" />
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Secondary]}" Tag="1" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Lightbar/Mousepad">
|
||||
<DockPanel LastChildFill="False">
|
||||
<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>
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Tertiary], Converter={StaticResource VisualizationToLastChildFillConverter}}">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<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">
|
||||
<ComboBox.Items>
|
||||
<ComboBoxItem>Level</ComboBoxItem>
|
||||
</ComboBox.Items>
|
||||
</ComboBox>
|
||||
</controls:Formular>
|
||||
</GroupBox>
|
||||
<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>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=TertiaryVisualizationProvider.Configuration}" />
|
||||
</GroupBox>
|
||||
<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:Form>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=TertiaryVisualizationProvider}" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Tertiary].Configuration}" />
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
|
||||
<ContentControl Content="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance}, Path=Visualizations[(helper:VisualizationIndex)Tertiary]}" Tag="2" />
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Settings">
|
||||
<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>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<AdornerDecorator>
|
||||
<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>
|
||||
|
||||
<controls:Formular Grid.Column="0">
|
||||
<Label controls:Formular.IsLabel="True" Content="Version:" />
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<controls:Form>
|
||||
<Label controls:Form.IsLabel="True" Content="Version" />
|
||||
<TextBlock Text="{Binding Version}" />
|
||||
|
||||
<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}" />
|
||||
<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.LineBreaks="1" controls:Formular.IsLabel="True" Content="Devices:" />
|
||||
</controls:Formular>
|
||||
</Grid>
|
||||
<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." />
|
||||
|
||||
<!-- 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>
|
||||
</controls:Form>
|
||||
</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
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,8 @@
|
||||
Margin="0,-4,0,0" Orientation="Horizontal">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Equalizer"
|
||||
Foreground="{StaticResource BrushForeground}"
|
||||
IsChecked="{Binding Path=Equalizer.IsEnabled, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
IsChecked="{Binding Path=Equalizer.IsEnabled, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
ToolTip="Enables the Equalizer.
The Equalier Allows to finetune the graph by slective increasing/decresing the value.
You can add new pivots by rightclicking on the visualization-window.
Existing pivots can be deleted by rightclicking on them or moved by leftclicking and dragging around." />
|
||||
|
||||
<Button VerticalAlignment="Center" Margin="12,0,0,0"
|
||||
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Equalizer.IsEnabled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=True}"
|
||||
|
||||
@ -30,9 +30,12 @@
|
||||
</Style>
|
||||
|
||||
<DataTemplate DataType="{x:Type visualizationProvider:FrequencyBarsVisualizationProvider}">
|
||||
<Grid>
|
||||
<visualization:FrequencyBarsVisualizer Style="{StaticResource StyleFrequencyBarsVisualizer}" VisualizationProvider="{Binding}" />
|
||||
<visualization:EqualizerVisualizer Style="{StaticResource StyleEqualizerVisualizer}" Equalizer="{Binding Equalizer}" />
|
||||
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<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)))
|
||||
@ -88,6 +115,8 @@ namespace KeyboardAudioVisualizer.UI.Visualization
|
||||
if (_panel == null) return;
|
||||
|
||||
_panel.Children.Clear();
|
||||
if (VisualizationProvider == null) return;
|
||||
|
||||
_bars = new Rectangle[((FrequencyBarsVisualizationProviderConfiguration)VisualizationProvider.Configuration).Bars];
|
||||
|
||||
for (int i = 0; i < _bars.Length; i++)
|
||||
@ -117,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,13 +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="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.Groups" version="1.0.0" 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>
|
||||
57
README.md
57
README.md
@ -1,2 +1,59 @@
|
||||
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!
|
||||
|
||||
**Example-Video:**
|
||||
[](https://www.youtube.com/watch?v=mby2NYN0V1o)
|
||||
|
||||
## Visualizations
|
||||
#### Keyboard
|
||||
- **"Frequency Bars"** - Simple spectrum visualizer.
|
||||
- **"Level"** - Shows the overall volume.
|
||||
- **"Beat detection"** - Pulses to the beat of the music. (This isn't working really well right now, depending on the music. But in general not satisfying, sorry.)
|
||||
#### Mouse/Headset
|
||||
- **"Beat detection"** - Pulses to the beat of the music. (This isn't working really well right now, depending on the music. But in general not satisfying, sorry.)
|
||||
#### Mousepad/Lightbar (K95 Platinum)
|
||||
- **"Level"** - Shows the overall volume.
|
||||
- **"Beat detection"** - Pulses to the beat of the music. (This isn't working really well right now, depending on the music. But in general not satisfying, sorry.)
|
||||
|
||||
## Supported devices
|
||||
- All Corsair RGB-devices.
|
||||
- Logitech G910 and G610 with physical EU layout. (Untested but should work)
|
||||
- (In theory every device with SDK support could be include, open an issue if you want to help with increasing the range of supported devices!)
|
||||
|
||||
## Settings
|
||||
#### Frequency Bars
|
||||
- **Spectrum:** The way the spectrum is grouped together. Values are: _(default: Logarithmic)_
|
||||
- **_Linear_**: Each bar represents the same range of frequencies. Most of the time this doesn't look good since low frequencies are underrepresented.
|
||||
- **_Logarithmic_**: The higher the frequencies get the wider the range of grouped frequencies. This is close to the way humans perceive sound and therfore most of the time looks quite good as long as the range of used frequencies is big enough.
|
||||
- **_Gamma_**: While Gamma-correction is known from image-processing it still applies quite well to audio-data, grouping not as extreme as logarithmic but still better than linear. The used Gamma-value can be configured.
|
||||
- **Value:** The way the value of a frequency bar is determined. Values are: _(default: Sum)_
|
||||
- **_Sum_**: Sums the power of all frequencies grouped in the bar using all available data. Combining this with logarithmic grouping gives the most realistic representation.
|
||||
- **_Max_**: Uses the maximum value in each group making sure peaks are caught well. This works quite good with gamma-grouping.
|
||||
- **_Average_**: Uses the average of all frequencies grouped in the bar. This smooths out the whole graph quite a lot.
|
||||
- **Bars:** The number of bars used to represent the spectrum. _(default: 48)_
|
||||
- **Min Freq.:** The minimum frequency used in the graph. This value shouldn't be modified. _(default: 60)_
|
||||
- **Max Freq.:** The maximum frequency used in the graph. This value can be lowered to increase the value of lower frequencies. Using high values might lead to death bars if the audio is mastered with an low-pass filter cutting high frequencies. _(default: 15000)_
|
||||
- **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 "quiet-bar". _(default: 0.5)_
|
||||
|
||||
**Equalizer**
|
||||
Allows to finetune the graph by slective increasing/decresing the value.
|
||||
You can add new pivots by rightclicking on the visualization-window.
|
||||
Existing pivots can be deleted by rightclicking on them or moved by leftclicking and dragging around.
|
||||
|
||||
|
||||
#### Beat detection
|
||||
_No configuration right now_
|
||||
|
||||
#### Level
|
||||
- **Calculation:** Defines how the RMS of the audio is plotted. Values are _Linear_, _Logarithmic_ and _Exponential_. The used range of the plott increases in that order (exponential has the widest range of peaks). _(default: Logarithmic)_
|
||||
|
||||
- **Scale:** Scales the whole graph. Use this to to fit your audio volume. _(default: 3)_
|
||||
|
||||
- **Smoothing:** Smooths the plot to prevent flickering. Low values will cause a hectic fast plot, high values a slow one without peaks. _(default: 8)_
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user