From 1b2c18cd2a22f1993b8ee0f97c84db03ef83ec4e Mon Sep 17 00:00:00 2001 From: BLARGoMATIC Date: Tue, 14 Jan 2020 21:33:08 -0700 Subject: [PATCH 1/2] Added Audio Device Setting Added the ability to change which audio device the visualizer listens to --- KeyboardAudioVisualizer/App.xaml.cs | 2 +- .../AudioCapture/CSCoreAudioInput.cs | 14 ++++++-- .../AudioCapture/IAudioInput.cs | 5 +-- .../AudioVisualizationFactory.cs | 16 ++++++--- .../Configuration/Settings.cs | 6 ++++ .../Converter/CaptureDeviceConverter.cs | 33 +++++++++++++++++++ .../KeyboardAudioVisualizer.csproj | 3 +- .../UI/ConfigurationViewModel.cs | 11 +++++++ .../UI/ConfigurationWindow.xaml | 18 ++++++++++ .../UI/ConfigurationWindow.xaml.cs | 16 +++++++++ 10 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 KeyboardAudioVisualizer/Converter/CaptureDeviceConverter.cs diff --git a/KeyboardAudioVisualizer/App.xaml.cs b/KeyboardAudioVisualizer/App.xaml.cs index 0b3fda0..c1109ae 100644 --- a/KeyboardAudioVisualizer/App.xaml.cs +++ b/KeyboardAudioVisualizer/App.xaml.cs @@ -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) diff --git a/KeyboardAudioVisualizer/AudioCapture/CSCoreAudioInput.cs b/KeyboardAudioVisualizer/AudioCapture/CSCoreAudioInput.cs index c17fd62..0642ba7 100644 --- a/KeyboardAudioVisualizer/AudioCapture/CSCoreAudioInput.cs +++ b/KeyboardAudioVisualizer/AudioCapture/CSCoreAudioInput.cs @@ -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); @@ -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 }; @@ -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) diff --git a/KeyboardAudioVisualizer/AudioCapture/IAudioInput.cs b/KeyboardAudioVisualizer/AudioCapture/IAudioInput.cs index 8fcda9b..7f55467 100644 --- a/KeyboardAudioVisualizer/AudioCapture/IAudioInput.cs +++ b/KeyboardAudioVisualizer/AudioCapture/IAudioInput.cs @@ -1,4 +1,5 @@ -using System; +using CSCore.CoreAudioAPI; +using System; namespace KeyboardAudioVisualizer.AudioCapture { @@ -11,6 +12,6 @@ public interface IAudioInput : IDisposable event AudioData DataAvailable; - void Initialize(); + void Initialize(MMDevice captureDevice); } } diff --git a/KeyboardAudioVisualizer/AudioProcessing/AudioVisualizationFactory.cs b/KeyboardAudioVisualizer/AudioProcessing/AudioVisualizationFactory.cs index b97c3d0..575d4c7 100644 --- a/KeyboardAudioVisualizer/AudioProcessing/AudioVisualizationFactory.cs +++ b/KeyboardAudioVisualizer/AudioProcessing/AudioVisualizationFactory.cs @@ -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; @@ -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); @@ -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)_processors.FirstOrDefault(x => x.GetType() == typeof(T)); public IVisualizationProvider CreateVisualizationProvider(VisualizationIndex visualizationIndex, VisualizationType visualizationType) diff --git a/KeyboardAudioVisualizer/Configuration/Settings.cs b/KeyboardAudioVisualizer/Configuration/Settings.cs index 554e618..adfe47a 100644 --- a/KeyboardAudioVisualizer/Configuration/Settings.cs +++ b/KeyboardAudioVisualizer/Configuration/Settings.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using CSCore.CoreAudioAPI; using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider; using KeyboardAudioVisualizer.Helper; using RGB.NET.Brushes.Gradients; @@ -37,6 +38,11 @@ public VisualizationSettings this[VisualizationIndex visualizationIndex] } } + //BLARG: 01.14.2020 Creating some Audio devices used in the AudioVisualizationFactory and the ConfigurationWindow.xaml + private static MMDeviceEnumerator DeviceEnumerator = new MMDeviceEnumerator(); + public MMDeviceCollection DeviceCollection { get; set; } = DeviceEnumerator.EnumAudioEndpoints(DataFlow.Render, DeviceState.Active); + public MMDevice CaptureDevice { get; set; } = DeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console); + #endregion } diff --git a/KeyboardAudioVisualizer/Converter/CaptureDeviceConverter.cs b/KeyboardAudioVisualizer/Converter/CaptureDeviceConverter.cs new file mode 100644 index 0000000..5852803 --- /dev/null +++ b/KeyboardAudioVisualizer/Converter/CaptureDeviceConverter.cs @@ -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), typeof(IEnumerable))] + 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; + } + } +} diff --git a/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj b/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj index 545f48f..d681ac9 100644 --- a/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj +++ b/KeyboardAudioVisualizer/KeyboardAudioVisualizer.csproj @@ -30,7 +30,7 @@ x86 pdbonly - true + false bin\Release\ TRACE prompt @@ -161,6 +161,7 @@ + diff --git a/KeyboardAudioVisualizer/UI/ConfigurationViewModel.cs b/KeyboardAudioVisualizer/UI/ConfigurationViewModel.cs index 4cbe0f7..d0a9100 100644 --- a/KeyboardAudioVisualizer/UI/ConfigurationViewModel.cs +++ b/KeyboardAudioVisualizer/UI/ConfigurationViewModel.cs @@ -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; @@ -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; diff --git a/KeyboardAudioVisualizer/UI/ConfigurationWindow.xaml b/KeyboardAudioVisualizer/UI/ConfigurationWindow.xaml index ba09b90..fac9814 100644 --- a/KeyboardAudioVisualizer/UI/ConfigurationWindow.xaml +++ b/KeyboardAudioVisualizer/UI/ConfigurationWindow.xaml @@ -35,6 +35,7 @@ + @@ -226,6 +227,23 @@ + + + +