Skip to content
This repository was archived by the owner on Aug 6, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion KeyboardAudioVisualizer/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected override void OnStartup(StartupEventArgs e)

ApplicationManager.Instance.Settings = settings;

AudioVisualizationFactory.Initialize();
AudioVisualizationFactory.Initialize(settings.CaptureDevice);
ApplicationManager.Instance.InitializeDevices();
}
catch (Exception ex)
Expand Down
14 changes: 11 additions & 3 deletions KeyboardAudioVisualizer/AudioCapture/CSCoreAudioInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ public class CSCoreAudioInput : IAudioInput

#region Methods

public void Initialize()
public void Initialize(MMDevice captureDevice)
{
MMDevice captureDevice = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Console);
//BLARG 01.14.2020: Don't need the default when we're given an Audio Enpoint
//MMDevice captureDevice = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Console);
WaveFormat deviceFormat = captureDevice.DeviceFormat;
_audioEndpointVolume = AudioEndpointVolume.FromDevice(captureDevice);

Expand All @@ -42,6 +43,8 @@ public void Initialize()
if (_capture == null)
throw new NullReferenceException("Failed to initialize WasapiLoopbackCapture");

//BLARG: Actually setting the Device
_capture.Device = captureDevice;
_capture.Initialize();

_soundInSource = new SoundInSource(_capture) { FillWithZeros = false };
Expand All @@ -63,10 +66,15 @@ public void Initialize()
_capture.Start();
}

//BLARG 01.14.2020: Added the rest of the disposables since we'll be calling this method a lot more
public void Dispose()
{
_capture?.Stop();
//_capture?.Stop(); //Don't need this, Dispose() takes care of it
_capture?.Dispose();
_soundInSource?.Dispose();
_source?.Dispose();
_stream?.Dispose();
_audioEndpointVolume?.Dispose();
}

private void StreamOnSingleBlockRead(object sender, SingleBlockReadEventArgs singleBlockReadEventArgs)
Expand Down
5 changes: 3 additions & 2 deletions KeyboardAudioVisualizer/AudioCapture/IAudioInput.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using CSCore.CoreAudioAPI;
using System;

namespace KeyboardAudioVisualizer.AudioCapture
{
Expand All @@ -11,6 +12,6 @@ public interface IAudioInput : IDisposable

event AudioData DataAvailable;

void Initialize();
void Initialize(MMDevice captureDevice);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CSCore.CoreAudioAPI;
using KeyboardAudioVisualizer.AudioCapture;
using KeyboardAudioVisualizer.AudioProcessing.Equalizer;
using KeyboardAudioVisualizer.AudioProcessing.Spectrum;
Expand Down Expand Up @@ -40,18 +41,18 @@ public void Update()
processor.Update();
}

public static void Initialize()
public static void Initialize(MMDevice captureDevice)
{
if (Instance != null) return;

Instance = new AudioVisualizationFactory();
Instance.InitializeInstance();
Instance.InitializeInstance(captureDevice);
}

private void InitializeInstance()
private void InitializeInstance(MMDevice captureDevice)
{
_audioInput = new CSCoreAudioInput();
_audioInput.Initialize();
_audioInput.Initialize(captureDevice);

_audioBuffer = new AudioBuffer(4096); // Working with ~93ms -
_audioInput.DataAvailable += (left, right) => _audioBuffer.Put(left, right);
Expand All @@ -62,6 +63,13 @@ private void InitializeInstance()
processor.Initialize();
}

//BLARG 01.14.2020: Added a method to change the Audio device without 1. Restarting the application 2. Crashing the Application 3. The Visualization Stopping
public void ChangeAudioDevice(MMDevice newDevice)
{
_audioInput.Dispose();
_audioInput.Initialize(newDevice);
}

private T GetAudioProcessor<T>() => (T)_processors.FirstOrDefault(x => x.GetType() == typeof(T));

public IVisualizationProvider CreateVisualizationProvider(VisualizationIndex visualizationIndex, VisualizationType visualizationType)
Expand Down
11 changes: 11 additions & 0 deletions KeyboardAudioVisualizer/Configuration/Settings.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using CSCore.CoreAudioAPI;
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
using KeyboardAudioVisualizer.Helper;
using RGB.NET.Brushes.Gradients;
using RGB.NET.Core;
using Newtonsoft.Json;

namespace KeyboardAudioVisualizer.Configuration
{
Expand Down Expand Up @@ -37,6 +39,15 @@ public VisualizationSettings this[VisualizationIndex visualizationIndex]
}
}

//BLARG: 01.14.2020 Creating some Audio devices used in the AudioVisualizationFactory and the ConfigurationWindow.xaml
//JsonIgnore because MMDevices don't seem to play well with Json deserialization
[JsonIgnore]
private static MMDeviceEnumerator DeviceEnumerator = new MMDeviceEnumerator();
[JsonIgnore]
public MMDeviceCollection DeviceCollection { get; set; } = DeviceEnumerator.EnumAudioEndpoints(DataFlow.Render, DeviceState.Active);
[JsonIgnore]
public MMDevice CaptureDevice { get; set; } = DeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console);

#endregion
}

Expand Down
33 changes: 33 additions & 0 deletions KeyboardAudioVisualizer/Converter/CaptureDeviceConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using CSCore.CoreAudioAPI;
/*BLARG 01.14.2020:
MMDevices don't really play nice with xaml on their own so they need some conversion.
Fortunately MMDevice.FriendlyName is fantastic.
Also when the ComboBox goes through all members of MMDeviceCollection they keep their order so we can handle the convertBack in the ConfigurationWindow.xaml.cs instead of here.
*/
namespace KeyboardAudioVisualizer.Converter
{
[ValueConversion(typeof(IEnumerable<MMDeviceCollection>), typeof(IEnumerable<MMDeviceCollection>))]
class CaptureDeviceConverter : IValueConverter
{
private MMDeviceCollection DeviceCollection = ApplicationManager.Instance.Settings.DeviceCollection;
private MMDevice CaptureDevice = ApplicationManager.Instance.Settings.CaptureDevice;

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is MMDeviceCollection) return (value as MMDeviceCollection).Select(x => x.FriendlyName);
else return (value as MMDevice).FriendlyName;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
}
3 changes: 2 additions & 1 deletion KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Optimize>false</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
Expand Down Expand Up @@ -161,6 +161,7 @@
<Compile Include="Configuration\ColorSerializer.cs" />
<Compile Include="Controls\ColorSelector.cs" />
<Compile Include="Controls\GradientEditor.cs" />
<Compile Include="Converter\CaptureDeviceConverter.cs" />
<Compile Include="Converter\VisualizationProviderDisplayNameConverter.cs" />
<Compile Include="Converter\VisualizationToLastChildFillConverter.cs" />
<Compile Include="Converter\VisualizationTypeSelectableConverter.cs" />
Expand Down
11 changes: 11 additions & 0 deletions KeyboardAudioVisualizer/UI/ConfigurationViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Reflection;
using CSCore.CoreAudioAPI;
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
using KeyboardAudioVisualizer.Helper;
using RGB.NET.Core;
Expand Down Expand Up @@ -35,6 +36,16 @@ public bool EnableAudioPrescale
}
}

//BLARG 01.14.2020: This makes the combobox actually display the selected device
public MMDevice SelectedCaptureDevice
{
get => ApplicationManager.Instance.Settings.CaptureDevice;
set
{
ApplicationManager.Instance.Settings.CaptureDevice = value;
}
}

public VisualizationType SelectedPrimaryVisualization
{
get => ApplicationManager.Instance.Settings[VisualizationIndex.Primary].SelectedVisualization;
Expand Down
18 changes: 18 additions & 0 deletions KeyboardAudioVisualizer/UI/ConfigurationWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<converter:VisualizationTypeSelectableConverter x:Key="VisualizationProviderSelectableConverter" />
<converter:VisualizationProviderDisplayNameConverter x:Key="VisualizationProviderDisplayNameConverter" />
<converter:VisualizationToLastChildFillConverter x:Key="VisualizationToLastChildFillConverter" />
<converter:CaptureDeviceConverter x:Key="CaptureDeviceConverter"/>

<DataTemplate x:Key="DataTemplateVisualizationSelection" DataType="{x:Type visualizationProvider:VisualizationType}">
<TextBlock Text="{Binding Converter={StaticResource VisualizationProviderDisplayNameConverter}}" />
Expand Down Expand Up @@ -226,6 +227,23 @@
</ItemsControl>
</StackPanel>
</GroupBox>
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
<controls:Form>
<controls:Form.Resources>
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="{x:Type Label}" />
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="{x:Type TextBlock}" />
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="{x:Type ListBox}" />
</controls:Form.Resources>

<Label controls:Form.IsLabel="True" Content="Audio Device: " />
<ComboBox controls:Form.Fill="True" Name="deviceBox" SelectionChanged="DeviceBox_SelectionChanged"
ItemsSource="{Binding Source={x:Static keyboardAudioVisualizer:ApplicationManager.Instance},
Path=Settings.DeviceCollection,
Converter={StaticResource CaptureDeviceConverter}}"
SelectedValue="{Binding SelectedCaptureDevice,Converter={StaticResource CaptureDeviceConverter}}"
Margin="5,0,0,0" />
</controls:Form>
</GroupBox>
</DockPanel>
</AdornerDecorator>
</TabItem>
Expand Down
16 changes: 16 additions & 0 deletions KeyboardAudioVisualizer/UI/ConfigurationWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using CSCore.CoreAudioAPI;
using KeyboardAudioVisualizer.AudioProcessing;
using KeyboardAudioVisualizer.Controls;

namespace KeyboardAudioVisualizer.UI
Expand All @@ -12,5 +14,19 @@ private void ConfigurationWindow_OnClosed(object sender, EventArgs e)
{
ApplicationManager.Instance.ExitCommand.Execute(null);
}

//BLARG 01.14.2020: ComboBoxes are magic
private void DeviceBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
//For some reason the SelectionChanged event happens when you first open the configuration window, so in order to avoid unnecessary device changes we wait for the window to be visible
if (deviceBox.IsVisible)
{
MMDevice captureDevice = ApplicationManager.Instance.Settings.DeviceCollection.ItemAt(deviceBox.SelectedIndex);

AudioVisualizationFactory.Instance.ChangeAudioDevice(captureDevice);

KeyboardAudioVisualizer.ApplicationManager.Instance.Settings.CaptureDevice = captureDevice;
}
}
}
}