1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-01 10:13:30 +00:00

Added audio visualization animations for #178

This commit is contained in:
SpoinkyNL 2016-12-01 18:18:19 +01:00
parent 2482bdb7bd
commit 0a0cfa3442
3 changed files with 81 additions and 34 deletions

View File

@ -34,24 +34,45 @@
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Animation -->
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10" FontSize="13.333" Text="Animation:"
VerticalAlignment="Center"
Height="18" />
<ComboBox Grid.Row="0" Grid.Column="1" Margin="10,10,10,0" x:Name="LayerAnimations" VerticalAlignment="Top"
Height="22">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Animation Speed -->
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10" FontSize="13.333" Text="Animation speed:"
VerticalAlignment="Center" Height="18" />
<Slider Grid.Row="0" Grid.Column="3" VerticalAlignment="Center"
TickPlacement="None" TickFrequency="0.05"
Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3"
SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" />
<!-- Volume sensitivity --> <!-- Volume sensitivity -->
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Volume sensitivity:" <TextBlock Grid.Row="1" Grid.Column="0" Margin="10,13,10,10" FontSize="13.333" Text="Volume sensitivity:"
Height="18" VerticalAlignment="Top" /> Height="18" VerticalAlignment="Top" />
<Slider x:Name="Scale" Grid.Row="0" Grid.Column="1" VerticalAlignment="Top" <Slider x:Name="Scale" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top"
Value="{Binding Path=LayerModel.Properties.Sensitivity, Mode=TwoWay}" Margin="10,12,10,2" Height="24" Value="{Binding Path=LayerModel.Properties.Sensitivity, Mode=TwoWay}" Margin="10,12,10,2" Height="24"
TickPlacement="BottomRight" TickFrequency="1" Minimum="1" Maximum="10" SmallChange="1" TickPlacement="BottomRight" TickFrequency="1" Minimum="1" Maximum="10" SmallChange="1"
IsSnapToTickEnabled="True" /> IsSnapToTickEnabled="True" />
<!-- Fade-out speed --> <!-- Fade-out speed -->
<TextBlock Grid.Row="0" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Fade-out speed:" <TextBlock Grid.Row="1" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Fade-out speed:"
VerticalAlignment="Top" Height="18" /> VerticalAlignment="Top" Height="18" />
<Slider x:Name="RotationSpeed" Grid.Row="0" Grid.Column="3" VerticalAlignment="Top" <Slider Grid.Row="1" Grid.Column="3" VerticalAlignment="Top"
Value="{Binding Path=LayerModel.Properties.FadeSpeed, Mode=TwoWay}" Margin="10,12,10,2" Value="{Binding Path=LayerModel.Properties.FadeSpeed, Mode=TwoWay}" Margin="10,12,10,2"
Height="24" TickPlacement="BottomRight" TickFrequency="0.1" Minimum="0.1" Maximum="1" SmallChange="0.1" Height="24" TickPlacement="BottomRight" TickFrequency="0.1" Minimum="0.1" Maximum="1" SmallChange="0.1"
IsSnapToTickEnabled="True" /> IsSnapToTickEnabled="True" />
<!-- Colors --> <!-- Colors -->
<StackPanel Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush"> <StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" x:Name="ShowBrush">
<TextBlock Margin="10,13,10,0" FontSize="13.333" Text="Color(s):" <TextBlock Margin="10,13,10,0" FontSize="13.333" Text="Color(s):"
VerticalAlignment="Top" Height="18" Width="130" /> VerticalAlignment="Top" Height="18" Width="130" />
<Border Margin="10" BorderBrush="{StaticResource ControlBorderBrush}" <Border Margin="10" BorderBrush="{StaticResource ControlBorderBrush}"
@ -62,9 +83,9 @@
</StackPanel> </StackPanel>
<!-- Bar direction --> <!-- Bar direction -->
<TextBlock Grid.Row="1" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Bar direction:" <TextBlock Grid.Row="2" Grid.Column="2" Margin="10,13,10,10" FontSize="13.333" Text="Bar direction:"
VerticalAlignment="Top" Height="18" /> VerticalAlignment="Top" Height="18" />
<ComboBox Grid.Row="1" Grid.Column="3" ItemsSource="{Binding Source={StaticResource DirectionEnumValues}}" <ComboBox Grid.Row="2" Grid.Column="3" ItemsSource="{Binding Source={StaticResource DirectionEnumValues}}"
Margin="10,10,10,0" SelectedItem="{Binding Path=LayerModel.Properties.Direction}" Margin="10,10,10,0" SelectedItem="{Binding Path=LayerModel.Properties.Direction}"
VerticalAlignment="Top" Height="22"> VerticalAlignment="Top" Height="22">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>

View File

@ -1,17 +1,40 @@
using Artemis.Profiles.Layers.Abstract; using System.Linq;
using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
namespace Artemis.Profiles.Layers.Types.Audio namespace Artemis.Profiles.Layers.Types.Audio
{ {
public class AudioPropertiesViewModel : LayerPropertiesViewModel public class AudioPropertiesViewModel : LayerPropertiesViewModel
{ {
private ILayerAnimation _selectedLayerAnimation;
public AudioPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm) public AudioPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm)
{ {
LayerAnimations = new BindableCollection<ILayerAnimation>(editorVm.LayerAnimations);
SelectedLayerAnimation =
LayerAnimations.FirstOrDefault(l => l.Name == editorVm.ProposedLayer.LayerAnimation?.Name) ??
LayerAnimations.First(l => l.Name == "None");
}
public BindableCollection<ILayerAnimation> LayerAnimations { get; set; }
public ILayerAnimation SelectedLayerAnimation
{
get { return _selectedLayerAnimation; }
set
{
if (Equals(value, _selectedLayerAnimation)) return;
_selectedLayerAnimation = value;
NotifyOfPropertyChange(() => SelectedLayerAnimation);
}
} }
public override void ApplyProperties() public override void ApplyProperties()
{ {
LayerModel.Properties.Brush = Brush; LayerModel.Properties.Brush = Brush;
LayerModel.LayerAnimation = SelectedLayerAnimation;
} }
} }
} }

View File

@ -6,7 +6,6 @@ using System.Windows.Media;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Modules.Effects.AudioVisualizer.Utilities; using Artemis.Modules.Effects.AudioVisualizer.Utilities;
using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Animations;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties; using Artemis.Properties;
@ -15,6 +14,7 @@ using Artemis.ViewModels.Profiles;
using NAudio.CoreAudioApi; using NAudio.CoreAudioApi;
using NAudio.Wave; using NAudio.Wave;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject;
using NLog; using NLog;
namespace Artemis.Profiles.Layers.Types.Audio namespace Artemis.Profiles.Layers.Types.Audio
@ -24,15 +24,17 @@ namespace Artemis.Profiles.Layers.Types.Audio
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly List<LayerModel> _audioLayers = new List<LayerModel>(); private readonly List<LayerModel> _audioLayers = new List<LayerModel>();
private readonly MMDevice _device; private readonly MMDevice _device;
private readonly IKernel _kernel;
private readonly SampleAggregator _sampleAggregator = new SampleAggregator(1024); private readonly SampleAggregator _sampleAggregator = new SampleAggregator(1024);
private readonly WasapiLoopbackCapture _waveIn; private readonly WasapiLoopbackCapture _waveIn;
private DateTime _lastAudioUpdate; private DateTime _lastAudioUpdate;
private DateTime _lastUpdate;
private int _lines; private int _lines;
private string _previousSettings; private string _previousSettings;
private DateTime _lastUpdate;
public AudioType() public AudioType(IKernel kernel)
{ {
_kernel = kernel;
_device = new MMDeviceEnumerator() _device = new MMDeviceEnumerator()
.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault(); .EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
@ -107,7 +109,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
lock (SpectrumData) lock (SpectrumData)
{ {
UpdateLayers(layerModel); SetupLayers(layerModel);
if (SpectrumData.Any()) if (SpectrumData.Any())
{ {
@ -223,6 +225,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
// Fake the height and width and update the animation // Fake the height and width and update the animation
audioLayer.Properties.Width = settings.Width; audioLayer.Properties.Width = settings.Width;
audioLayer.Properties.Height = settings.Height; audioLayer.Properties.Height = settings.Height;
audioLayer.LastRender = DateTime.Now;
audioLayer.LayerAnimation?.Update(audioLayer, true); audioLayer.LayerAnimation?.Update(audioLayer, true);
// Restore the height and width // Restore the height and width
@ -231,13 +234,11 @@ namespace Artemis.Profiles.Layers.Types.Audio
} }
/// <summary> /// <summary>
/// Updates the inner layers when the settings have changed /// Sets up the inner layers when the settings have changed
/// </summary> /// </summary>
/// <param name="layerModel"></param> /// <param name="layerModel"></param>
private void UpdateLayers(LayerModel layerModel) private void SetupLayers(LayerModel layerModel)
{ {
// TODO: Animation every frame before checking settings
// Checking on settings update is expensive, only do it every second // Checking on settings update is expensive, only do it every second
if (DateTime.Now - _lastUpdate < TimeSpan.FromSeconds(1)) if (DateTime.Now - _lastUpdate < TimeSpan.FromSeconds(1))
return; return;
@ -245,7 +246,9 @@ namespace Artemis.Profiles.Layers.Types.Audio
var settings = (AudioPropertiesModel) layerModel.Properties; var settings = (AudioPropertiesModel) layerModel.Properties;
var currentSettings = JsonConvert.SerializeObject(settings, Formatting.Indented); var currentSettings = JsonConvert.SerializeObject(settings, Formatting.Indented);
if (currentSettings == _previousSettings) var currentType = _audioLayers.FirstOrDefault()?.LayerAnimation?.GetType();
if (currentSettings == _previousSettings && (layerModel.LayerAnimation.GetType() == currentType))
return; return;
_previousSettings = JsonConvert.SerializeObject(settings, Formatting.Indented); _previousSettings = JsonConvert.SerializeObject(settings, Formatting.Indented);
@ -255,51 +258,51 @@ namespace Artemis.Profiles.Layers.Types.Audio
{ {
case Direction.TopToBottom: case Direction.TopToBottom:
case Direction.BottomToTop: case Direction.BottomToTop:
SetupVertical(settings); SetupVertical(layerModel);
break; break;
case Direction.LeftToRight: case Direction.LeftToRight:
case Direction.RightToLeft: case Direction.RightToLeft:
SetupHorizontal(settings); SetupHorizontal(layerModel);
break; break;
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
} }
private void SetupVertical(AudioPropertiesModel settings) private void SetupVertical(LayerModel layerModel)
{ {
_lines = (int) settings.Width; _lines = (int) layerModel.Properties.Width;
for (var i = 0; i < _lines; i++) for (var i = 0; i < _lines; i++)
{ {
var layer = LayerModel.CreateLayer(); var layer = LayerModel.CreateLayer();
layer.Properties.X = settings.X + i; layer.Properties.X = layerModel.Properties.X + i;
layer.Properties.Y = settings.Y; layer.Properties.Y = layerModel.Properties.Y;
layer.Properties.Width = 1; layer.Properties.Width = 1;
layer.Properties.Height = 0; layer.Properties.Height = 0;
// TODO: Setup animation layer.Properties.AnimationSpeed = layerModel.Properties.AnimationSpeed;
layer.LayerAnimation = new NoneAnimation(); layer.Properties.Brush = layerModel.Properties.Brush;
layer.Properties.Brush = settings.Brush;
layer.Properties.Contain = false; layer.Properties.Contain = false;
layer.LayerAnimation = (ILayerAnimation) _kernel.Get(layerModel.LayerAnimation.GetType());
_audioLayers.Add(layer); _audioLayers.Add(layer);
layer.Update(null, false, true); layer.Update(null, false, true);
} }
} }
private void SetupHorizontal(AudioPropertiesModel settings) private void SetupHorizontal(LayerModel layerModel)
{ {
_lines = (int) settings.Height; _lines = (int) layerModel.Properties.Height;
for (var i = 0; i < _lines; i++) for (var i = 0; i < _lines; i++)
{ {
var layer = LayerModel.CreateLayer(); var layer = LayerModel.CreateLayer();
layer.Properties.X = settings.X; layer.Properties.X = layerModel.Properties.X;
layer.Properties.Y = settings.Y + i; layer.Properties.Y = layerModel.Properties.Y + i;
layer.Properties.Width = 0; layer.Properties.Width = 0;
layer.Properties.Height = 1; layer.Properties.Height = 1;
// TODO: Setup animation layer.Properties.AnimationSpeed = layerModel.Properties.AnimationSpeed;
layer.LayerAnimation = new NoneAnimation(); layer.Properties.Brush = layerModel.Properties.Brush;
layer.Properties.Brush = settings.Brush;
layer.Properties.Contain = false; layer.Properties.Contain = false;
layer.LayerAnimation = (ILayerAnimation) _kernel.Get(layerModel.LayerAnimation.GetType());
_audioLayers.Add(layer); _audioLayers.Add(layer);
layer.Update(null, false, true); layer.Update(null, false, true);