1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

WIP on new audio layers

This commit is contained in:
SpoinkyNL 2017-01-08 23:55:21 +01:00
parent 52afde89ec
commit 1fa6063706
16 changed files with 513 additions and 312 deletions

View File

@ -151,6 +151,10 @@
<HintPath>..\packages\Colore.5.1.0\lib\net35\Corale.Colore.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="CSCore, Version=1.1.5992.18249, Culture=neutral, PublicKeyToken=5a08f2b6f4415dea, processorArchitecture=MSIL">
<HintPath>..\packages\CSCore.1.1.0\lib\net35-client\CSCore.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="CUE.NET, Version=1.1.0.2, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CUE.NET.1.1.0.2\lib\net45\CUE.NET.dll</HintPath>
<Private>True</Private>
@ -211,10 +215,6 @@
<HintPath>..\packages\MoonSharp.2.0.0.0\lib\net40-client\MoonSharp.Interpreter.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NAudio, Version=1.7.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.1.7.3\lib\net35\NAudio.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
@ -489,9 +489,12 @@
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCapture.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\AudioCaptureManager.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\FftEventArgs.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\SampleAggregator.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\BaseSpectrumProvider.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\ISpectrumProvider.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\LineSpectrum.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioCapturing\SpectrumBase.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" />
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs">
<DependentUpon>AudioPropertiesView.xaml</DependentUpon>

View File

@ -99,6 +99,11 @@ namespace Artemis.Modules.Abstract
ProfileModel = profileModel;
ProfileModel?.Activate(_luaManager);
if (ProfileModel != null)
{
Settings.LastProfile = ProfileModel.Name;
Settings.Save();
}
RaiseProfileChangedEvent(new ProfileChangedEventArgs(ProfileModel));
}

View File

@ -54,18 +54,21 @@ namespace Artemis.Modules.Games.RocketLeague
{
Updater.GetPointers();
_pointer = SettingsProvider.Load<OffsetSettings>().RocketLeague;
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
if (tempProcess == null)
return;
_memory = new Memory(tempProcess);
base.Enable();
}
public override void Update()
{
if (_memory == null)
{
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
if (tempProcess == null)
return;
_memory = new Memory(tempProcess);
}
if (ProfileModel == null || DataModel == null || _memory == null)
return;

View File

@ -72,19 +72,17 @@ namespace Artemis.Modules.Games.WoW
_process = null;
}
public override void Enable()
{
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
if (tempProcess == null)
return;
_process = new ProcessSharp(tempProcess, MemoryType.Remote);
base.Enable();
}
public override void Update()
{
if (_process == null)
{
var tempProcess = MemoryHelpers.GetProcessIfRunning(ProcessName);
if (tempProcess == null)
return;
_process = new ProcessSharp(tempProcess, MemoryType.Remote);
}
if (ProfileModel == null || DataModel == null || _process == null)
return;

View File

@ -0,0 +1,135 @@
using System;
using System.Timers;
using CSCore;
using CSCore.CoreAudioAPI;
using CSCore.DSP;
using CSCore.SoundIn;
using CSCore.Streams;
using Ninject.Extensions.Logging;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public class AudioCapture
{
private const FftSize FftSize = CSCore.DSP.FftSize.Fft4096;
private WasapiLoopbackCapture _soundIn;
private GainSource _source;
private BasicSpectrumProvider _spectrumProvider;
private GainSource _volume;
private Timer _timer;
public AudioCapture(ILogger logger, MMDevice device)
{
Logger = logger;
Device = device;
_timer = new Timer(1000);
_timer.Elapsed += TimerOnElapsed;
}
private void TimerOnElapsed(object sender, ElapsedEventArgs e)
{
// If MayStop is true for longer than a second, this will stop the audio capture
if (MayStop)
{
Stop();
MayStop = false;
}
else
MayStop = true;
}
public bool MayStop { get; set; }
public ILogger Logger { get; }
public float Volume
{
get { return _volume.Volume; }
set { _volume.Volume = value; }
}
public MMDevice Device { get; }
public bool Running { get; set; }
public LineSpectrum GetLineSpectrum(int barCount, int volume, ScalingStrategy scalingStrategy)
{
return new LineSpectrum(FftSize)
{
SpectrumProvider = _spectrumProvider,
UseAverage = true,
BarCount = barCount,
IsXLogScale = true,
ScalingStrategy = scalingStrategy
};
}
public void Start()
{
if (Running)
return;
try
{
_soundIn = new WasapiLoopbackCapture();
_soundIn.Initialize();
// Not sure if this null check is needed but doesnt hurt
if (Device != null)
_soundIn.Device = Device;
var soundInSource = new SoundInSource(_soundIn);
_source = soundInSource.ToSampleSource().AppendSource(x => new GainSource(x), out _volume);
// create a spectrum provider which provides fft data based on some input
_spectrumProvider = new BasicSpectrumProvider(_source.WaveFormat.Channels, _source.WaveFormat.SampleRate,
FftSize);
// the SingleBlockNotificationStream is used to intercept the played samples
var notificationSource = new SingleBlockNotificationStream(_source);
// pass the intercepted samples as input data to the spectrumprovider (which will calculate a fft based on them)
notificationSource.SingleBlockRead += (s, a) => _spectrumProvider.Add(a.Left, a.Right);
var waveSource = notificationSource.ToWaveSource(16);
// We need to read from our source otherwise SingleBlockRead is never called and our spectrum provider is not populated
var buffer = new byte[waveSource.WaveFormat.BytesPerSecond / 2];
soundInSource.DataAvailable += (s, aEvent) =>
{
while (waveSource.Read(buffer, 0, buffer.Length) > 0)
{
}
};
_soundIn.Start();
_timer.Start();
Running = true;
MayStop = false;
}
catch (Exception e)
{
Logger.Warn(e, "Failed to start WASAPI audio capture");
}
}
public void Stop()
{
if (!Running)
return;
try
{
_timer.Stop();
_soundIn.Stop();
_soundIn.Dispose();
_source.Dispose();
_soundIn = null;
_source = null;
Running = false;
}
catch (Exception e)
{
Logger.Warn(e, "Failed to stop WASAPI audio capture");
}
}
}
}

View File

@ -1,133 +1,33 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using NAudio.CoreAudioApi;
using NAudio.Dsp;
using NAudio.Wave;
using CSCore.CoreAudioAPI;
using Ninject.Extensions.Logging;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public class AudioCaptureManager
{
private readonly SampleAggregator _sampleAggregator = new SampleAggregator(1024);
private readonly WasapiLoopbackCapture _waveIn;
private Complex[] _fft;
private DateTime _lastAudioUpdate;
private DateTime _lastRequest;
private readonly List<AudioCapture> _audioCaptures;
public AudioCaptureManager(ILogger logger)
{
Logger = logger;
Device = new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
_audioCaptures = new List<AudioCapture>();
}
_sampleAggregator.FftCalculated += FftCalculated;
_sampleAggregator.PerformFFT = true;
public AudioCapture GetAudioCapture(MMDevice device)
{
// Return existing audio capture if found
var audioCapture = _audioCaptures.FirstOrDefault(a => a.Device == device);
if (audioCapture != null)
return audioCapture;
// Start listening for sound data
_waveIn = new WasapiLoopbackCapture();
_waveIn.DataAvailable += OnDataAvailable;
// Else create a new one and return that
var newAudioCapture = new AudioCapture(Logger, device);
_audioCaptures.Add(newAudioCapture);
return newAudioCapture;
}
public ILogger Logger { get; set; }
public MMDevice Device { get; set; }
public bool Running { get; set; }
public void Start()
{
if (Running)
return;
try
{
_waveIn.StartRecording();
Running = true;
}
catch (Exception e)
{
Logger.Warn(e, "Failed to start WASAPI audio capture");
}
}
public void Stop()
{
if (!Running)
return;
try
{
_waveIn.StopRecording();
Running = false;
}
catch (Exception e)
{
Logger.Warn(e, "Failed to start WASAPI audio capture");
}
}
private void FftCalculated(object sender, FftEventArgs e)
{
_fft = e.Result;
}
private void OnDataAvailable(object sender, WaveInEventArgs e)
{
if (DateTime.Now - _lastAudioUpdate < TimeSpan.FromMilliseconds(40))
return;
if (DateTime.Now - _lastRequest > TimeSpan.FromSeconds(5))
{
Stop();
return;
}
_lastAudioUpdate = DateTime.Now;
var buffer = e.Buffer;
var bytesRecorded = e.BytesRecorded;
var bufferIncrement = _waveIn.WaveFormat.BlockAlign;
for (var index = 0; index < bytesRecorded; index += bufferIncrement)
{
var sample32 = BitConverter.ToSingle(buffer, index);
_sampleAggregator.Add(sample32);
}
}
public List<byte> GetSpectrumData(int lines)
{
_lastRequest = DateTime.Now;
if (!Running)
Start();
var spectrumData = new List<byte>();
if (_fft == null)
return spectrumData;
int x;
var b0 = 0;
for (x = 0; x < lines; x++)
{
float peak = 0;
var b1 = (int) Math.Pow(2, x*10.0/(lines - 1));
if (b1 > 1023)
b1 = 1023;
if (b1 <= b0)
b1 = b0 + 1;
for (; b0 < b1; b0++)
if (peak < _fft[1 + b0].X)
peak = _fft[1 + b0].X;
var y = (int) (Math.Sqrt(peak)*3*255 - 4);
if (y > 255)
y = 255;
if (y < 0)
y = 0;
spectrumData.Add((byte) y);
}
return spectrumData;
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using CSCore.DSP;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
/// <summary>
/// BasicSpectrumProvider
/// </summary>
public class BasicSpectrumProvider : FftProvider, ISpectrumProvider
{
private readonly List<object> _contexts = new List<object>();
private readonly int _sampleRate;
public BasicSpectrumProvider(int channels, int sampleRate, FftSize fftSize)
: base(channels, fftSize)
{
if (sampleRate <= 0)
throw new ArgumentOutOfRangeException("sampleRate");
_sampleRate = sampleRate;
}
public int GetFftBandIndex(float frequency)
{
var fftSize = (int) FftSize;
var f = _sampleRate / 2.0;
// ReSharper disable once PossibleLossOfFraction
return (int) (frequency / f * (fftSize / 2));
}
public bool GetFftData(float[] fftResultBuffer, object context)
{
if (_contexts.Contains(context))
return false;
_contexts.Add(context);
GetFftData(fftResultBuffer);
return true;
}
public override void Add(float[] samples, int count)
{
base.Add(samples, count);
if (count > 0)
_contexts.Clear();
}
public override void Add(float left, float right)
{
base.Add(left, right);
_contexts.Clear();
}
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Diagnostics;
using NAudio.Dsp;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public class FftEventArgs : EventArgs
{
[DebuggerStepThrough]
public FftEventArgs(Complex[] result)
{
Result = result;
}
public Complex[] Result { get; private set; }
}
}

View File

@ -0,0 +1,8 @@
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public interface ISpectrumProvider
{
bool GetFftData(float[] fftBuffer, object context);
int GetFftBandIndex(float frequency);
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using Artemis.Profiles.Layers.Models;
using CSCore.DSP;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public class LineSpectrum : SpectrumBase
{
private int _barCount;
public LineSpectrum(FftSize fftSize)
{
FftSize = fftSize;
}
public int BarCount
{
get { return _barCount; }
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("value");
_barCount = value;
SpectrumResolution = value;
UpdateFrequencyMapping();
}
}
public void SetupLayersVertical(double height, List<LayerModel> audioLayers)
{
var fftBuffer = new float[(int)FftSize];
// get the fft result from the spectrum provider
if (!SpectrumProvider.GetFftData(fftBuffer, this))
return;
var spectrumPoints = CalculateSpectrumPoints(height, fftBuffer);
foreach (var p in spectrumPoints)
audioLayers[p.SpectrumPointIndex].Height = p.Value;
}
public void SetupLayersHorizontal(double width, List<LayerModel> audioLayers)
{
var fftBuffer = new float[(int)FftSize];
// get the fft result from the spectrum provider
if (!SpectrumProvider.GetFftData(fftBuffer, this))
return;
var spectrumPoints = CalculateSpectrumPoints(width, fftBuffer);
foreach (var p in spectrumPoints)
audioLayers[p.SpectrumPointIndex].Width = p.Value;
}
}
}

View File

@ -1,52 +0,0 @@
using System;
using NAudio.Dsp;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public class SampleAggregator
{
private readonly FftEventArgs fftArgs;
// This Complex is NAudio's own!
private readonly Complex[] fftBuffer;
private readonly int fftLength;
private readonly int m;
private int fftPos;
public SampleAggregator(int fftLength)
{
if (!IsPowerOfTwo(fftLength))
throw new ArgumentException("FFT Length must be a power of two");
m = (int) Math.Log(fftLength, 2.0);
this.fftLength = fftLength;
fftBuffer = new Complex[fftLength];
fftArgs = new FftEventArgs(fftBuffer);
}
public bool PerformFFT { get; set; }
// FFT
public event EventHandler<FftEventArgs> FftCalculated;
private bool IsPowerOfTwo(int x)
{
return (x & (x - 1)) == 0;
}
public void Add(float value)
{
if (PerformFFT && FftCalculated != null)
{
// Remember the window function! There are many others as well.
fftBuffer[fftPos].X = (float) (value * FastFourierTransform.HammingWindow(fftPos, fftLength));
fftBuffer[fftPos].Y = 0; // This is always zero with audio.
fftPos++;
if (fftPos >= fftLength)
{
fftPos = 0;
FastFourierTransform.FFT(true, m, fftBuffer);
FftCalculated(this, fftArgs);
}
}
}
}
}

View File

@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using CSCore;
using CSCore.DSP;
namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing
{
public class SpectrumBase
{
private const int ScaleFactorLinear = 9;
protected const int ScaleFactorSqr = 2;
protected const double MinDbValue = -90;
protected const double MaxDbValue = 0;
protected const double DbScale = MaxDbValue - MinDbValue;
private int _fftSize;
private bool _isXLogScale;
private int _maxFftIndex;
private int _maximumFrequency = 20000;
private int _maximumFrequencyIndex;
private int _minimumFrequency = 20; //Default spectrum from 20Hz to 20kHz
private int _minimumFrequencyIndex;
private int[] _spectrumIndexMax;
private int[] _spectrumLogScaleIndexMax;
private ISpectrumProvider _spectrumProvider;
protected int SpectrumResolution;
public int MaximumFrequency
{
get { return _maximumFrequency; }
set
{
if (value <= MinimumFrequency)
throw new ArgumentOutOfRangeException("value",
"Value must not be less or equal the MinimumFrequency.");
_maximumFrequency = value;
UpdateFrequencyMapping();
}
}
public int MinimumFrequency
{
get { return _minimumFrequency; }
set
{
if (value < 0)
throw new ArgumentOutOfRangeException("value");
_minimumFrequency = value;
UpdateFrequencyMapping();
}
}
[Browsable(false)]
public ISpectrumProvider SpectrumProvider
{
get { return _spectrumProvider; }
set
{
if (value == null)
throw new ArgumentNullException("value");
_spectrumProvider = value;
}
}
public bool IsXLogScale
{
get { return _isXLogScale; }
set
{
_isXLogScale = value;
UpdateFrequencyMapping();
}
}
public ScalingStrategy ScalingStrategy { get; set; }
public bool UseAverage { get; set; }
[Browsable(false)]
public FftSize FftSize
{
get { return (FftSize) _fftSize; }
protected set
{
if ((int) Math.Log((int) value, 2) % 1 != 0)
throw new ArgumentOutOfRangeException("value");
_fftSize = (int) value;
_maxFftIndex = _fftSize / 2 - 1;
}
}
protected virtual void UpdateFrequencyMapping()
{
_maximumFrequencyIndex = Math.Min(_spectrumProvider.GetFftBandIndex(MaximumFrequency) + 1, _maxFftIndex);
_minimumFrequencyIndex = Math.Min(_spectrumProvider.GetFftBandIndex(MinimumFrequency), _maxFftIndex);
var actualResolution = SpectrumResolution;
var indexCount = _maximumFrequencyIndex - _minimumFrequencyIndex;
var linearIndexBucketSize = Math.Round(indexCount / (double) actualResolution, 3);
_spectrumIndexMax = _spectrumIndexMax.CheckBuffer(actualResolution, true);
_spectrumLogScaleIndexMax = _spectrumLogScaleIndexMax.CheckBuffer(actualResolution, true);
var maxLog = Math.Log(actualResolution, actualResolution);
for (var i = 1; i < actualResolution; i++)
{
var logIndex =
(int) ((maxLog - Math.Log(actualResolution + 1 - i, actualResolution + 1)) * indexCount) +
_minimumFrequencyIndex;
_spectrumIndexMax[i - 1] = _minimumFrequencyIndex + (int) (i * linearIndexBucketSize);
_spectrumLogScaleIndexMax[i - 1] = logIndex;
}
if (actualResolution > 0)
_spectrumIndexMax[_spectrumIndexMax.Length - 1] =
_spectrumLogScaleIndexMax[_spectrumLogScaleIndexMax.Length - 1] = _maximumFrequencyIndex;
}
protected virtual SpectrumPointData[] CalculateSpectrumPoints(double maxValue, float[] fftBuffer)
{
var dataPoints = new List<SpectrumPointData>();
double value0 = 0, value = 0;
double lastValue = 0;
var actualMaxValue = maxValue;
var spectrumPointIndex = 0;
for (var i = _minimumFrequencyIndex; i <= _maximumFrequencyIndex; i++)
{
switch (ScalingStrategy)
{
case ScalingStrategy.Decibel:
value0 = (20 * Math.Log10(fftBuffer[i]) - MinDbValue) / DbScale * actualMaxValue;
break;
case ScalingStrategy.Linear:
value0 = fftBuffer[i] * ScaleFactorLinear * actualMaxValue;
break;
case ScalingStrategy.Sqrt:
value0 = Math.Sqrt(fftBuffer[i]) * ScaleFactorSqr * actualMaxValue;
break;
}
var recalc = true;
value = Math.Max(0, Math.Max(value0, value));
while (spectrumPointIndex <= _spectrumIndexMax.Length - 1 &&
i ==
(IsXLogScale
? _spectrumLogScaleIndexMax[spectrumPointIndex]
: _spectrumIndexMax[spectrumPointIndex]))
{
if (!recalc)
value = lastValue;
if (value > maxValue)
value = maxValue;
if (UseAverage && spectrumPointIndex > 0)
value = (lastValue + value) / 2.0;
dataPoints.Add(new SpectrumPointData {SpectrumPointIndex = spectrumPointIndex, Value = value});
lastValue = value;
value = 0.0;
spectrumPointIndex++;
recalc = false;
}
//value = 0;
}
return dataPoints.ToArray();
}
[DebuggerDisplay("{Value}")]
protected struct SpectrumPointData
{
public int SpectrumPointIndex;
public double Value;
}
}
}

View File

@ -21,4 +21,11 @@ namespace Artemis.Profiles.Layers.Types.Audio
[Description("Left to right")] LeftToRight,
[Description("Right to left")] RightToLeft
}
public enum ScalingStrategy
{
[Description("Decibel")] Decibel,
[Description("Linear")] Linear,
[Description("Square root")] Sqrt
}
}

View File

@ -24,16 +24,15 @@ namespace Artemis.Profiles.Layers.Types.Audio
private DateTime _lastUpdate;
private int _lines;
private string _previousSettings;
private LineSpectrum _lineSpectrum;
private AudioCapture _audioCapture;
public AudioType(IKernel kernel, AudioCaptureManager audioCaptureManager)
{
_kernel = kernel;
AudioCaptureManager = audioCaptureManager;
_audioCapture = audioCaptureManager.GetAudioCapture(null);
}
[JsonIgnore]
public AudioCaptureManager AudioCaptureManager { get; set; }
public string Name => "Keyboard - Audio visualization";
public bool ShowInEdtor => true;
public DrawType DrawType => DrawType.Keyboard;
@ -83,23 +82,25 @@ namespace Artemis.Profiles.Layers.Types.Audio
if (isPreview)
return;
// Start audio capture in case it wasn't running
_audioCapture.Start();
_audioCapture.MayStop = false;
lock (_audioLayers)
{
// Called every update but only runs every second
SetupLayers(layerModel);
var spectrumData = AudioCaptureManager.GetSpectrumData(_lines);
if (!spectrumData.Any())
return;
var settings = (AudioPropertiesModel) layerModel.Properties;
switch (settings.Direction)
{
case Direction.TopToBottom:
case Direction.BottomToTop:
ApplyVertical(spectrumData, settings);
_lineSpectrum.SetupLayersVertical(layerModel.Height, _audioLayers);
break;
case Direction.LeftToRight:
case Direction.RightToLeft:
ApplyHorizontal(spectrumData, settings);
_lineSpectrum.SetupLayersHorizontal(layerModel.Width, _audioLayers);
break;
}
}
@ -124,97 +125,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
return layerPropertiesViewModel;
return new AudioPropertiesViewModel(layerEditorViewModel);
}
private void ApplyVertical(List<byte> spectrumData, AudioPropertiesModel settings)
{
var index = 0;
foreach (var audioLayer in _audioLayers)
{
int height;
if (spectrumData.Count > index)
height = (int) Math.Round(spectrumData[index]/2.55);
else
height = 0;
// Apply Sensitivity setting
height = height*settings.Sensitivity;
var newHeight = settings.Height/100.0*height;
if (newHeight >= audioLayer.Properties.Height)
audioLayer.Properties.Height = newHeight;
else
audioLayer.Properties.Height = audioLayer.Properties.Height - settings.FadeSpeed;
if (audioLayer.Properties.Height < 0)
audioLayer.Properties.Height = 0;
// Reverse the direction if settings require it
if (settings.Direction == Direction.BottomToTop)
audioLayer.Properties.Y = settings.Y + (settings.Height - audioLayer.Properties.Height);
FakeUpdate(settings, audioLayer);
index++;
}
}
private void ApplyHorizontal(List<byte> spectrumData, AudioPropertiesModel settings)
{
var index = 0;
foreach (var audioLayer in _audioLayers)
{
int width;
if (spectrumData.Count > index)
width = (int) Math.Round(spectrumData[index]/2.55);
else
width = 0;
// Apply Sensitivity setting
width = width*settings.Sensitivity;
var newWidth = settings.Width/100.0*width;
if (newWidth >= audioLayer.Properties.Width)
audioLayer.Properties.Width = newWidth;
else
audioLayer.Properties.Width = audioLayer.Properties.Width - settings.FadeSpeed;
if (audioLayer.Properties.Width < 0)
audioLayer.Properties.Width = 0;
audioLayer.Properties.Brush = settings.Brush;
audioLayer.Properties.Contain = false;
// Reverse the direction if settings require it
if (settings.Direction == Direction.RightToLeft)
audioLayer.Properties.X = settings.X + (settings.Width - audioLayer.Properties.Width);
FakeUpdate(settings, audioLayer);
index++;
}
}
/// <summary>
/// Updates the layer manually faking the width and height for a properly working animation
/// </summary>
/// <param name="settings"></param>
/// <param name="audioLayer"></param>
private static void FakeUpdate(LayerPropertiesModel settings, LayerModel audioLayer)
{
// Call the regular update
audioLayer.LayerType?.Update(audioLayer, null);
// Store the original height and width
var oldHeight = audioLayer.Properties.Height;
var oldWidth = audioLayer.Properties.Width;
// Fake the height and width and update the animation
audioLayer.Properties.Width = settings.Width;
audioLayer.Properties.Height = settings.Height;
audioLayer.LastRender = DateTime.Now;
audioLayer.LayerAnimation?.Update(audioLayer, true);
// Restore the height and width
audioLayer.Properties.Height = oldHeight;
audioLayer.Properties.Width = oldWidth;
}
/// <summary>
/// Sets up the inner layers when the settings have changed
/// </summary>
@ -230,7 +141,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
var currentSettings = JsonConvert.SerializeObject(settings, Formatting.Indented);
var currentType = _audioLayers.FirstOrDefault()?.LayerAnimation?.GetType();
if (currentSettings == _previousSettings && (layerModel.LayerAnimation.GetType() == currentType))
if (currentSettings == _previousSettings && layerModel.LayerAnimation.GetType() == currentType)
return;
_previousSettings = JsonConvert.SerializeObject(settings, Formatting.Indented);
@ -249,6 +160,7 @@ namespace Artemis.Profiles.Layers.Types.Audio
default:
throw new ArgumentOutOfRangeException();
}
_lineSpectrum = _audioCapture.GetLineSpectrum(_audioLayers.Count, 5, ScalingStrategy.Decibel);
}
private void SetupVertical(LayerModel layerModel)

View File

@ -118,7 +118,7 @@ namespace Artemis.ViewModels.Profiles
var renderLayers = GetRenderLayers();
// Draw the current frame to the preview
var keyboardRect = _deviceManager.ActiveKeyboard.KeyboardRectangle(4);
var keyboardRect = _deviceManager.ActiveKeyboard.KeyboardRectangle();
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{

View File

@ -5,6 +5,7 @@
<package id="Caliburn.Micro.Core" version="3.0.2" targetFramework="net461" />
<package id="Castle.Core" version="3.3.3" targetFramework="net452" />
<package id="Colore" version="5.1.0" targetFramework="net461" />
<package id="CSCore" version="1.1.0" targetFramework="net461" />
<package id="CUE.NET" version="1.1.0.2" targetFramework="net461" />
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net461" />
<package id="DynamicExpresso.Core" version="1.3.3.4" targetFramework="net461" />
@ -15,7 +16,6 @@
<package id="MahApps.Metro.Resources" version="0.6.1.0" targetFramework="net452" />
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net461" />
<package id="MoonSharp" version="2.0.0.0" targetFramework="net461" />
<package id="NAudio" version="1.7.3" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" />
<package id="Ninject" version="3.2.2.0" targetFramework="net452" />
<package id="Ninject.Extensions.Conventions" version="3.2.0.0" targetFramework="net461" />