This commit is contained in:
KP9lK 2025-05-13 21:55:57 +03:00
commit 12cdf95598
126 changed files with 5435 additions and 0 deletions

28
App.axaml Normal file
View File

@ -0,0 +1,28 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SoundTester.App"
xmlns:local="using:SoundTester"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme />
</Application.Styles>
<Application.Resources>
<ResourceDictionary x:Key="Light">
<Color x:Key="BaseHigh">#ffffff</Color>
<Color x:Key="BaseMedium">#666666</Color>
<Color x:Key="BaseLow">#2b2d30</Color>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Color x:Key="BaseHigh">#2b2d30</Color>
<Color x:Key="BaseMedium">#888888</Color>
<Color x:Key="BaseLow">#ffffff</Color>
</ResourceDictionary>
</Application.Resources>
</Application>

36
App.axaml.cs Normal file
View File

@ -0,0 +1,36 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using ReactiveUI;
using SoundTester.Helpers;
using SoundTester.ViewModels;
using SoundTester.Views;
using Splat;
namespace SoundTester;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
Bootstrapper.Configure();
Current.Resources.MergedDictionaries.Add((ResourceDictionary)Application.Current.Resources["Light"]);
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = Locator.Current.GetService<MainWindowViewModel>(),
};
}
base.OnFrameworkInitializationCompleted();
}
}

BIN
Assets/avalonia-logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

36
Helpers/Bootstrapper.cs Normal file
View File

@ -0,0 +1,36 @@
using System;
using System.ComponentModel.Design;
using Avalonia.ReactiveUI;
using Microsoft.Extensions.DependencyInjection;
using ReactiveUI;
using SoundTester.ViewModels;
using SoundTester.Views;
using SoundTesting;
using Splat;
using Splat.Microsoft.Extensions.DependencyInjection;
namespace SoundTester.Helpers;
public static class Bootstrapper
{
public static void Configure()
{
var services = new ServiceCollection();
services.AddSingleton<DevicesEnumerator>();
services.AddSingleton<MainWindowViewModel>();
services.UseMicrosoftDependencyResolver();
var provider = services.BuildServiceProvider();
Locator.CurrentMutable.InitializeSplat();
Locator.CurrentMutable.InitializeReactiveUI();
Locator.CurrentMutable.RegisterConstant<IServiceProvider>(provider);
Locator.CurrentMutable.Register<IViewFor<VoiceTrackerViewModel>>(() => new VoiceTrackerView());
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
}
}

View File

@ -0,0 +1,15 @@
using NAudio.CoreAudioApi;
using ReactiveUI;
namespace SoundTesting;
public class DevicesEnumerator : MMDeviceEnumerator
{
private DevicesUpdater _devicesUpdater = new DevicesUpdater();
public DevicesUpdater DevicesUpdater => _devicesUpdater;
public DevicesEnumerator()
{
this.RegisterEndpointNotificationCallback(_devicesUpdater);
}
}

65
Models/DevicesUpdater.cs Normal file
View File

@ -0,0 +1,65 @@
using System.Collections.ObjectModel;
using NAudio.CoreAudioApi;
using NAudio.CoreAudioApi.Interfaces;
namespace SoundTesting
{
public class
DevicesUpdater : IMMNotificationClient //Кастомный интерфейс уведомлений об изменении количества и состояния подключенных аудиоустройств
{
public ObservableCollection<string> InputDevices { get; set; } = new();
public ObservableCollection<string> OutputDevices { get; set; } = new();
public DevicesUpdater()
{
DeviceListUpdate();
}
private void DeviceListUpdate() //Обновление данных об устройствах
{
InputDevices?.Clear();
OutputDevices?.Clear();
MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
var inputs = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active);
foreach (var device in inputs)
{
InputDevices.Add( device.FriendlyName );
device.Dispose();
}
var outputs = enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);
foreach (var device in outputs)
{
OutputDevices.Add( device.FriendlyName );
device.Dispose();
}
enumerator.Dispose();
}
public void OnDeviceStateChanged(string deviceId, DeviceState newState) //Изменение состояния устройства
{
}
public void OnDeviceAdded(string deviceId) //Добавление устройства
{
DeviceListUpdate();
}
public void OnDeviceRemoved(string deviceId) //Удаление устройства
{
DeviceListUpdate();
}
public void OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId) //Изменение устройства по-умолчанию
{
DeviceListUpdate();
}
public void OnPropertyValueChanged(string deviceId, PropertyKey key) //Изменение свойства устройства
{
}
}
}

23
Program.cs Normal file
View File

@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.ReactiveUI;
using System;
namespace SoundTester;
sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI();
}

View File

@ -0,0 +1,60 @@
using System;
using System.Linq;
using Avalonia.Threading;
using NAudio.CoreAudioApi;
using NAudio.Wave;
using SoundTesting;
namespace SoundTester.Service;
public class VoiceTrackerService
{
private WasapiCapture _wasapiCapture;
private WasapiOut _wasapiOut;
private BufferedWaveProvider _bufferedWaveProvider;
private DevicesEnumerator _devicesEnumerator;
private float _volume = -96;
public delegate void DecibelLevelHandler(float level);
public event DecibelLevelHandler? DecibelLevelEvent;
public VoiceTrackerService(string deviceName)
{
var en = new MMDeviceEnumerator(); //Костыль
var inD = en.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).FirstOrDefault(x => x.FriendlyName == deviceName);
var outD = en.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
_wasapiCapture = new WasapiCapture(inD, false, 50);
_wasapiOut = new WasapiOut(outD, AudioClientShareMode.Shared, false, 50);
_wasapiCapture.DataAvailable += OnDataAvailable;
_bufferedWaveProvider = new BufferedWaveProvider(_wasapiCapture?.WaveFormat){ DiscardOnBufferOverflow = true };
_wasapiOut.Init(_bufferedWaveProvider);
}
public void Record()
{
_wasapiCapture.StartRecording();
_wasapiOut.Play();
}
private void OnDataAvailable(object sender, WaveInEventArgs e)
{
float[] samples = new float[e.BytesRecorded / 2];
for (int i = 0; i < e.BytesRecorded; i += 2)
{
short sample = BitConverter.ToInt16(e.Buffer, i);
samples[i / 2] = sample / 32768f;
}
float sum = 0;
for (int i = 0; i < samples.Length; i++)
{
sum += samples[i] * samples[i];
}
float rms = (float)Math.Sqrt(sum / samples.Length);
float res = rms > 0 ? 20 * (float)Math.Log10(rms) : -96;
DecibelLevelEvent?.Invoke(res);
_bufferedWaveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded); //Добавление данных для мониторинга микрофона
}
}

30
SoundTester.csproj Normal file
View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1"/>
<PackageReference Include="Avalonia.Desktop" Version="11.2.1"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.1"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.1"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageReference Include="NAudio" Version="2.2.1" />
<PackageReference Include="Splat.Microsoft.Extensions.DependencyInjection" Version="15.3.1" />
</ItemGroup>
</Project>

30
ViewLocator.cs Normal file
View File

@ -0,0 +1,30 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using SoundTester.ViewModels;
namespace SoundTester;
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}

View File

@ -0,0 +1,14 @@
namespace SoundTester.ViewModels;
public class MainWindowViewModel : ViewModelBase
{
public VoiceTrackerViewModel VoiceTracker { get; }
public OscillatorViewModel Oscillator { get; }
public PanningPickerViewModel PanningPicker { get; }
public MainWindowViewModel()
{
VoiceTracker = new VoiceTrackerViewModel();
Oscillator = new OscillatorViewModel();
PanningPicker = new PanningPickerViewModel();
}
}

View File

@ -0,0 +1,172 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using NAudio.CoreAudioApi;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using ReactiveUI;
namespace SoundTester.ViewModels;
public class OscillatorItemViewModel : ViewModelBase //Осциллятор (генератор волны)
{
private WasapiOut _waveOut;
private SignalGenerator _signalGenerator;
private ISampleProvider _sampleProvider;
private SignalGeneratorType _typeRef;
private int _deviceIndex;
private float _frequency = 20f;
private bool _sin = true;
private bool _square = false;
private bool _sawtooth = false;
private bool _triangle = false;
private bool _noise = false;
private bool _isPlaying = false;
private string _itemName;
private string _groupKey;
public int DeviceIndex
{
get => _deviceIndex;
set => this.RaiseAndSetIfChanged(ref _deviceIndex, value);
}
[Range(20, 20000)]
public float Frequency
{
get => _frequency;
set => this.RaiseAndSetIfChanged(ref _frequency, value);
}
public bool Sin
{
get => _sin;
set => this.RaiseAndSetIfChanged(ref _sin, value);
}
public bool Square
{
get => _square;
set => this.RaiseAndSetIfChanged(ref _square, value);
}
public bool Sawtooth
{
get => _sawtooth;
set => this.RaiseAndSetIfChanged(ref _sawtooth, value);
}
public bool Triangle
{
get => _triangle;
set => this.RaiseAndSetIfChanged(ref _triangle, value);
}
public bool Noise
{
get => _noise;
set => this.RaiseAndSetIfChanged(ref _noise, value);
}
public bool IsPlaying
{
get => _isPlaying;
set => this.RaiseAndSetIfChanged(ref _isPlaying, value);
}
public SignalGeneratorType SGType
{
get => SGTypeSelection();
set => this.RaiseAndSetIfChanged(ref _typeRef, value);
}
public string ItemName
{
get => _itemName;
set => this.RaiseAndSetIfChanged(ref _itemName, value);
}
private SignalGeneratorType SGTypeSelection() //Выбор типа волны в зависимости от булевых знаечний
{
if (Square)
return SignalGeneratorType.Square;
else if (Sawtooth)
return SignalGeneratorType.SawTooth;
else if (Triangle)
return SignalGeneratorType.Triangle;
else if (Noise)
return SignalGeneratorType.White;
return SignalGeneratorType.Sin;
}
public WasapiOut WaveOut
{
get => _waveOut;
set => this.RaiseAndSetIfChanged(ref _waveOut, value);
}
public SignalGenerator SignalGenerator1
{
get => _signalGenerator;
set => this.RaiseAndSetIfChanged(ref _signalGenerator, value);
}
public ISampleProvider SampleProvider
{
get => _sampleProvider;
set => this.RaiseAndSetIfChanged(ref _sampleProvider, value);
}
public string GroupKey
{
get => _groupKey;
set => this.RaiseAndSetIfChanged(ref _groupKey, value);
}
private void WaveOutInit(string audioDevice) //Инициализация осциллятора
{
var en = new MMDeviceEnumerator(); //костыль
var outD = en.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active).Where(x => x.FriendlyName == audioDevice).FirstOrDefault();
WaveOut?.Stop();
WaveOut?.Dispose();
WaveOut = new WasapiOut(outD,AudioClientShareMode.Shared, false, 50);
SignalGenerator1 = new SignalGenerator();
SignalGenerator1.Frequency = Frequency;
SignalGenerator1.Type = SGType;
SignalGenerator1.Gain = 0.5;
SampleProvider = SignalGenerator1.ToMono();
WaveOut.Init(SampleProvider);
}
public OscillatorItemViewModel() //Конструктор
{
}
public OscillatorItemViewModel(string audioDevice) //Конструктор
{
ItemName = audioDevice;
GroupKey = KeyGen();
this.WhenAnyValue(
x => x.Frequency,
x => x.Sin,
x => x.Square,
x => x.Sawtooth,
x => x.Triangle,
x => x.Noise)
.Subscribe(x =>
{
IsPlaying = false;
WaveOutInit(audioDevice);
});
}
private string KeyGen() //Генерация уникального ключа для группы радиокнопок
{
return Guid.NewGuid().ToString();
}
}

View File

@ -0,0 +1,203 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using ReactiveUI;
using SoundTesting;
using Splat;
namespace SoundTester.ViewModels;
public class OscillatorViewModel : ViewModelBase //Менеджер осцилляторов (генераторов волн)
{
private string _playButtonText = "Начать прослушивание";
private string _selectedDevice;
private int _selectedDeviceIndex;
private ObservableCollection<string> _devices;
private ObservableCollection<OscillatorItemViewModel> _items;
private bool _isPlaying = false;
private bool _isItemSelected = false;
private bool _isEnabled = false;
private bool _isEnabledByCount = false;
private OscillatorItemViewModel _selectedItem;
private DevicesEnumerator _devicesEnumerator;
public string SelectedDevice
{
get => _selectedDevice;
set => this.RaiseAndSetIfChanged(ref _selectedDevice, value);
}
public int SelectedDeviceIndex
{
get => _selectedDeviceIndex;
set => this.RaiseAndSetIfChanged(ref _selectedDeviceIndex, value);
}
public ObservableCollection<string> Devices
{
get => _devices;
set => this.RaiseAndSetIfChanged(ref _devices, value);
}
public string PlayButtonText
{
get => _playButtonText;
set => this.RaiseAndSetIfChanged(ref _playButtonText, value);
}
public bool IsPlaying
{
get => _isPlaying;
set => this.RaiseAndSetIfChanged(ref _isPlaying, value);
}
public ObservableCollection<OscillatorItemViewModel> Items
{
get => _items;
set => this.RaiseAndSetIfChanged(ref _items, value);
}
public bool IsItemSelected
{
get => _isItemSelected;
set => this.RaiseAndSetIfChanged(ref _isItemSelected, value);
}
public bool IsEnabled
{
get => _isEnabled;
set => this.RaiseAndSetIfChanged(ref _isEnabled, value);
}
public bool IsEnabledByCount
{
get => _isEnabledByCount;
set => this.RaiseAndSetIfChanged(ref _isEnabledByCount, value);
}
public OscillatorItemViewModel SelectedItem
{
get => _selectedItem;
set => this.RaiseAndSetIfChanged(ref _selectedItem, value);
}
public ICommand PlayCommand { get; }
public ICommand AddItemCommand { get; }
public ICommand RemoveItemCommand { get; }
public OscillatorViewModel(DevicesEnumerator? devicesEnumerator = null) //Конструктор
{
_devicesEnumerator = devicesEnumerator ?? Locator.Current.GetService<DevicesEnumerator>()!;
Devices = _devicesEnumerator!.DevicesUpdater.InputDevices;
SelectedDevice = Devices.FirstOrDefault();
Items = new ObservableCollection<OscillatorItemViewModel>();
PlayCommand = ReactiveCommand.Create(() => Play());
AddItemCommand = ReactiveCommand.Create(() => AddItem());
RemoveItemCommand = ReactiveCommand.Create(() => RemoveItem());
this.WhenAnyValue(x => x.Devices)
.WhereNotNull().Subscribe(x =>
{
SelectedDevice = null!;
SelectedDevice = Devices?.FirstOrDefault();
ReloadDevices();
});
this.WhenAnyValue(x => x.Items.Count).WhereNotNull().Subscribe(x =>
{
IsEnabledByCount = Items.Count > 0 ? true : false;
});
this.WhenAnyValue(x => x.Devices.Count).Subscribe(x =>
{
foreach (var item in Items)
{
item.WaveOut.Stop();
item.IsPlaying = false;
}
Items.Clear();
});
}
private void Play() //Запуск/остановка осцилляторов
{
if (_isPlaying!)
{
PlayButtonText = "Начать прослушивание";
foreach (var item in _items)
{
item.WaveOut.Stop();
item.IsPlaying = false;
}
}
else
{
PlayButtonText = "Остановить прослушивание";
foreach (var item in _items)
{
item.WaveOut.Play();
item.IsPlaying = true;
}
}
_isPlaying = !_isPlaying;
}
private void AddItem() //Добавление нового осциллятора
{
if (Items.Count < 10)
{
foreach (var item in Items)
{
item.WaveOut.Stop();
item.IsPlaying = false;
}
IsPlaying = false;
PlayButtonText = "Начать прослушивание";
OscillatorItemViewModel oscillatorItem = new OscillatorItemViewModel(SelectedDevice);
Items.Add(oscillatorItem);
foreach (var ite in Items)
{
ite.WhenAnyValue(
x => x.Frequency,
x => x.Sin,
x => x.Square,
x => x.Triangle,
x => x.Sawtooth,
x => x.Noise).Subscribe(x =>
{
ite.WaveOut?.Stop();
ite.IsPlaying = false;
PlayButtonText = "Начать прослушивание";
});
}
}
}
private void RemoveItem() //Удаление выбранного осциллятора
{
if (SelectedItem != null)
{
SelectedItem.WaveOut.Stop();
Items.Remove(SelectedItem);
}
}
private void ReloadDevices() => this.WhenAnyValue(x => x.SelectedDevice)
.Subscribe(_ =>
{
Devices = _devicesEnumerator.DevicesUpdater.OutputDevices;
IsEnabled = SelectedDeviceIndex == -1 || Devices.Count == 0 ? false : true;
});
}

View File

@ -0,0 +1,148 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using NAudio.CoreAudioApi;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using ReactiveUI;
using SoundTesting;
using Splat;
namespace SoundTester.ViewModels;
public class PanningPickerViewModel : ViewModelBase //Тестер панорамирования
{
private string _playButtonContent = "Начать проверку";
private string _selectedDevice;
private ObservableCollection<string> _devices;
private float _panningValue = 0f;
private int _selectedIndex;
private bool _isPlaying;
private bool _isEnabled = false;
private WasapiOut _wasapiOut;
private SignalGenerator _signalGenerator = new SignalGenerator
{
Gain = 0.5,
Frequency = 440,
Type = SignalGeneratorType.Sin
};
private ISampleProvider _sampleProvider;
private DevicesEnumerator _devicesEnumerator;
public string PlayButtonContent
{
get => _playButtonContent;
set => this.RaiseAndSetIfChanged(ref _playButtonContent, value);
}
public float PanningValue
{
get => _panningValue;
set => this.RaiseAndSetIfChanged(ref _panningValue, value);
}
public int SelectedIndex
{
get => _selectedIndex;
set => this.RaiseAndSetIfChanged(ref _selectedIndex, value);
}
public string SelectedDevice
{
get => _selectedDevice;
set => this.RaiseAndSetIfChanged(ref _selectedDevice, value);
}
public ObservableCollection<string> Devices
{
get => _devices;
set => this.RaiseAndSetIfChanged(ref _devices, value);
}
public bool IsPlaying
{
get => _isPlaying;
set => this.RaiseAndSetIfChanged(ref _isPlaying, value);
}
public bool IsEnabled
{
get => _isEnabled;
set => this.RaiseAndSetIfChanged(ref _isEnabled, value);
}
public ICommand PlayCommand { get; }
public PanningPickerViewModel(DevicesEnumerator? devicesEnumerator = null) //конструктор
{
_devicesEnumerator = devicesEnumerator ?? Locator.Current.GetService<DevicesEnumerator>()!;
Devices = _devicesEnumerator!.DevicesUpdater.OutputDevices;
IsEnabled = SelectedIndex == -1 || Devices.Count == 0 ? false : true;
SelectedDevice = Devices.FirstOrDefault();
PlayCommand = ReactiveCommand.Create( () => Play());
this.WhenAnyValue(x => x.Devices, x => x.SelectedDevice)
.WhereNotNull()
.Subscribe(x =>
{
Devices = _devicesEnumerator.DevicesUpdater.OutputDevices;
IsEnabled = SelectedIndex == -1 || Devices.Count == 0 ? false : true;
});
this.WhenAnyValue(x => x.PanningValue, x => x.SelectedIndex).Subscribe(x =>
{
if (IsPlaying)
{
IsPlaying = false;
_wasapiOut?.Stop();
PlayButtonContent = "Начать проверку";
PanningAudioInit();
}
});
}
private void Play() //Запуск/остановка тестера
{
if (_isPlaying)
{
_wasapiOut?.Stop();
PlayButtonContent = "Начать проверку";
}
else
{
PanningAudioInit();
_wasapiOut.Play();
PlayButtonContent = "Остановить проверку";
}
_isPlaying = !_isPlaying;
}
private void PanningAudioInit() //Инициализация тестера
{
_wasapiOut = null;
var en = new MMDeviceEnumerator(); //костыль
var outD = en.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active).Where(x => x.FriendlyName == SelectedDevice).FirstOrDefault();
_wasapiOut = new WasapiOut(outD,AudioClientShareMode.Shared, false, 50); //Инициализация WasapiOut с помощью SelectedDevice не работает т.к. не удается корректно привести объект к интерфейсу IMMDevice
_sampleProvider = _signalGenerator.ToMono();
PanningSampleProvider panning = new PanningSampleProvider(_sampleProvider);
panning.Pan = PanningValue;
_wasapiOut.Init(panning);
en.Dispose();
}
}

View File

@ -0,0 +1,7 @@
using ReactiveUI;
namespace SoundTester.ViewModels;
public class ViewModelBase : ReactiveObject
{
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using Avalonia.Threading;
using NAudio.CoreAudioApi;
using NAudio.Wave;
using ReactiveUI;
using SoundTester.Service;
using SoundTesting;
using Splat;
namespace SoundTester.ViewModels;
public class VoiceTrackerViewModel : ViewModelBase
{
private string _recButtonContent = "Начать проверку";
private string _selectedDevice;
private int _selectedDeviceIndex;
private ObservableCollection<string> _devices;
private float _volume = -96;
private bool _isMonitoring = false;
private bool _isEnabled = false;
private WasapiCapture _wasapiCapture;
private WasapiOut _wasapiOut;
private BufferedWaveProvider _bufferedWaveProvider;
private DevicesEnumerator _devicesEnumerator;
public string SelectedDevice
{
get => _selectedDevice;
set => this.RaiseAndSetIfChanged(ref _selectedDevice, value);
}
public int SelectedDeviceIndex
{
get => _selectedDeviceIndex;
set => this.RaiseAndSetIfChanged(ref _selectedDeviceIndex, value);
}
public ObservableCollection<string>? Devices
{
get => _devices;
set => this.RaiseAndSetIfChanged(ref _devices, value);
}
public float Volume
{
get => _volume;
set => this.RaiseAndSetIfChanged(ref _volume, value);
}
public bool IsEnabled
{
get => _isEnabled;
set => this.RaiseAndSetIfChanged(ref _isEnabled, value);
}
public string RecButtonContent
{
get => _recButtonContent;
set => this.RaiseAndSetIfChanged(ref _recButtonContent, value);
}
public ICommand RecordCommand { get; }
public VoiceTrackerViewModel(DevicesEnumerator? devicesEnumerator = null) //Конструктор
{
;
_devicesEnumerator = devicesEnumerator ?? Locator.Current.GetService<DevicesEnumerator>()!;
Devices = _devicesEnumerator!.DevicesUpdater.InputDevices;
SelectedDevice = Devices.FirstOrDefault();
VoiceTrackerService voiceTrackerService = new VoiceTrackerService(SelectedDevice);
voiceTrackerService.DecibelLevelEvent += DecibelTracker;
RecordCommand = ReactiveCommand.Create(() => voiceTrackerService.Record());
this.WhenAnyValue(x => x.Devices, x => x.SelectedDevice)
.WhereNotNull()
.Subscribe(x =>
{
Devices = _devicesEnumerator.DevicesUpdater.InputDevices;
IsEnabled = SelectedDeviceIndex == -1 || Devices.Count == 0 ? false : true;
});
}
private void DecibelTracker(float level)
{
RefreshProgressBar(level);
}
private void RefreshProgressBar(float percentage)
{
Volume = percentage;
}
}

View File

@ -0,0 +1,6 @@
namespace SoundTester.ViewModels;
public class VolumePickerViewModel
{
}

34
Views/MainWindow.axaml Normal file
View File

@ -0,0 +1,34 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:SoundTester.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:view="clr-namespace:SoundTester.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
MinHeight="550" MinWidth="500" Height="550" Width="500"
WindowStartupLocation="CenterScreen"
x:Class="SoundTester.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="SoundTester">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainWindowViewModel />
</Design.DataContext>
<TabControl>
<TabItem Header="Запись">
<ContentControl Content="{Binding VoiceTracker }"/>
</TabItem>
<TabItem Header="Воспроизведение">
<ContentControl Content="{Binding Oscillator}"/>
</TabItem>
<TabItem Header="Баланс">
<ContentControl Content="{Binding PanningPicker}"/>
</TabItem>
</TabControl>
</Window>

12
Views/MainWindow.axaml.cs Normal file
View File

@ -0,0 +1,12 @@
using Avalonia.ReactiveUI;
using SoundTester.ViewModels;
namespace SoundTester.Views;
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,30 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SoundTester.ViewModels"
mc:Ignorable="d"
x:Class="SoundTester.Views.OscillatorItemView"
x:DataType="vm:OscillatorItemViewModel">
<Design.DataContext>
<vm:OscillatorItemViewModel />
</Design.DataContext>
<Border BorderBrush="Black" BorderThickness="1" Margin="5" Background="{DynamicResource BaseHigh}">
<StackPanel Margin="5">
<TextBlock Text="{Binding ItemName, StringFormat='{}Выбранное аудиоустройство: {0}'}" HorizontalAlignment="Center"
TextWrapping="WrapWithOverflow" />
<Slider Name="SliderFrequency" Orientation="Horizontal" Minimum="20" Maximum="20000" Value="{Binding Frequency}"
IsEnabled="{Binding !Noise}" />
<TextBlock Text="{Binding #SliderFrequency.Value, StringFormat='{}Частота: {0:0.00}'}" />
<StackPanel Spacing="10" Orientation="Horizontal" HorizontalAlignment="Center">
<RadioButton GroupName="{Binding GroupKey}" Content="SIN" IsChecked="{Binding Sin}" />
<RadioButton GroupName="{Binding GroupKey}" Content="SQR" IsChecked="{Binding Square}" />
<RadioButton GroupName="{Binding GroupKey}" Content="SAW" IsChecked="{Binding Sawtooth}" />
<RadioButton GroupName="{Binding GroupKey}" Content="TRI" IsChecked="{Binding Triangle}" />
<RadioButton GroupName="{Binding GroupKey}" Content="NOISE" IsChecked="{Binding Noise}" />
</StackPanel>
</StackPanel>
</Border>
</UserControl>

View File

@ -0,0 +1,16 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using SoundTester.ViewModels;
namespace SoundTester.Views;
public partial class OscillatorItemView : ReactiveUserControl<OscillatorItemViewModel>
{
public OscillatorItemView()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,41 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SoundTester.ViewModels"
xmlns:v="clr-namespace:SoundTester.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SoundTester.Views.OscillatorView"
x:DataType="vm:OscillatorViewModel">
<Grid RowDefinitions="Auto,Auto,Auto,*" Margin="5">
<TextBlock Grid.Row="0" TextWrapping="WrapWithOverflow" Text="Для проверки воспроизведения аудио на подключенных аудиостройствах системы выберите доступное устройство из списка и нажмите &#x22;Добавить&#x22;. В список ниже добавится осциллятор, частоту и тип волны которого можно натроить с помощью слайдера и галочек соответсвенно. Вы можете добавить несколько осцилляторов для одного устройства. Также, Вы можете добавить осцилляторы для разных аудиоустройств одновременно. Для произведения проверки нажмите на кнопку &#x22;Начать прослушивание&#x22;."/>
<Border Grid.Row="1" BorderThickness="1" BorderBrush="Black" Margin="5" Padding="10" CornerRadius="10">
<StackPanel Spacing="10">
<TextBlock Text="Доступные устройства:" />
<ComboBox ItemsSource="{Binding Devices}"
SelectedItem="{Binding SelectedDevice}"
SelectedIndex="{Binding SelectedDeviceIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding }" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<StackPanel Orientation="Horizontal" Spacing="5">
<Button Content="{Binding PlayButtonText}" Command="{Binding PlayCommand}" IsEnabled="{Binding IsEnabledByCount}" />
<Button Content="Добавить" Command="{Binding AddItemCommand}" IsEnabled="{Binding IsEnabled}" />
<Button Content="Удалить" Command="{Binding RemoveItemCommand}" IsEnabled="{Binding IsEnabled}" />
</StackPanel>
</StackPanel>
</Border>
<TextBlock Grid.Row="2" Text="{Binding Items.Count, StringFormat='{}{0}/10'}" HorizontalAlignment="Center" Margin="3"/>
<ListBox SelectionMode="AlwaysSelected" Grid.Row="3" ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}" Margin="10">
<ListBox.ItemTemplate>
<DataTemplate>
<v:OscillatorItemView></v:OscillatorItemView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>

View File

@ -0,0 +1,16 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using SoundTester.ViewModels;
namespace SoundTester.Views;
public partial class OscillatorView : ReactiveUserControl<OscillatorViewModel>
{
public OscillatorView()
{
DataContext = new OscillatorViewModel();
InitializeComponent();
}
}

View File

@ -0,0 +1,43 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SoundTester.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SoundTester.Views.PanningPickerView"
x:DataType="vm:PanningPickerViewModel">
<StackPanel Spacing="10" Margin="10">
<TextBlock TextWrapping="WrapWithOverflow" Text="Для проверки воспроизведения аудио в левом и правом каналах выберите устройтсво из списка доступных устройств, настройте значение смещения через слайдер (R - право, L - лево). После этого нажмите на кнопку &#x22;Начать проверку&#x22;."/>
<Border BorderThickness="1" BorderBrush="Black" Margin="5" Padding="5" CornerRadius="10">
<StackPanel
Margin="5" Spacing="10">
<StackPanel Spacing="10">
<TextBlock Text="Доступные устройства:" />
<ComboBox
ItemsSource="{Binding Devices}"
SelectedItem="{Binding SelectedDevice}" SelectedIndex="{Binding SelectedIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock TextWrapping="WrapWithOverflow" Text="{Binding }" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<Grid RowDefinitions="auto,auto,auto,auto">
<TextBlock
Text="R" Grid.Row="1" HorizontalAlignment="Right" />
<TextBlock
Text="L" Grid.Row="1" HorizontalAlignment="Left" />
<Slider
Minimum="-1" Maximum="1" Value="{Binding PanningValue}"
Grid.Row="2"
HorizontalAlignment="Stretch" />
<Button
Grid.Row="3" HorizontalAlignment="Center"
Content="{Binding PlayButtonContent}" IsEnabled="{Binding IsEnabled}" Command="{Binding PlayCommand}" />
</Grid>
</StackPanel>
</Border>
</StackPanel>
</UserControl>

View File

@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace SoundTester.Views;
public partial class PanningPickerView : ReactiveUserControl<PanningPickerView>
{
public PanningPickerView()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,35 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SoundTester.ViewModels"
mc:Ignorable="d"
x:Class="SoundTester.Views.VoiceTrackerView"
x:DataType="vm:VoiceTrackerViewModel">
<StackPanel Spacing="10" Margin="10">
<TextBlock TextWrapping="WrapWithOverflow" Text="Для произведения проверки микрофона выберите необходимое устройство из списка доступных устройств и нажмите на кнопку &#x22;Начать проверку&#x22;. Вы услышите звук, передающийся на микрофон через устройство воспроизведения, которое выбрано по-умолчанию в вашей системе."/>
<Border BorderThickness="1" BorderBrush="Black" Margin="5" Padding="5" CornerRadius="10">
<StackPanel Spacing="10" Margin="5">
<StackPanel Spacing="10">
<TextBlock Text="Доступные устройства:" />
<ComboBox ItemsSource="{Binding Devices}"
SelectedItem="{Binding SelectedDevice}"
SelectedIndex="{Binding SelectedDeviceIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding }" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<TextBlock Text="{Binding SelectedDevice,StringFormat='{}Выбран микрофон: {0}'}" />
<ProgressBar Minimum="-96" Maximum="0" Value="{Binding Volume}" />
<Button Content="{Binding RecButtonContent}" Command="{Binding RecordCommand}" IsEnabled="{Binding IsEnabled}" />
</StackPanel>
</Border>
</StackPanel>
</UserControl>

View File

@ -0,0 +1,18 @@
using System.Reactive.Disposables;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using ReactiveUI;
using SoundTester.ViewModels;
namespace SoundTester.Views;
public partial class VoiceTrackerView : ReactiveUserControl<VoiceTrackerViewModel>
{
public VoiceTrackerView()
{
DataContext = new VoiceTrackerViewModel();
InitializeComponent();
}
}

View File

@ -0,0 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SoundTester.Views.VolumePickerView">
Welcome to Avalonia!
</UserControl>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace SoundTester.Views;
public partial class VolumePickerView : UserControl
{
public VolumePickerView()
{
InitializeComponent();
}
}

18
app.manifest Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="SoundTester.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/Debug/net9.0/NAudio.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,933 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v9.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v9.0": {
"SoundTester/1.0.0": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.Desktop": "11.2.1",
"Avalonia.Diagnostics": "11.2.1",
"Avalonia.Fonts.Inter": "11.2.1",
"Avalonia.ReactiveUI": "11.2.1",
"Avalonia.Themes.Fluent": "11.2.1",
"Microsoft.Extensions.DependencyInjection": "9.0.4",
"NAudio": "2.2.1",
"Splat.Microsoft.Extensions.DependencyInjection": "15.3.1"
},
"runtime": {
"SoundTester.dll": {}
}
},
"Avalonia/11.2.1": {
"dependencies": {
"Avalonia.BuildServices": "0.0.29",
"Avalonia.Remote.Protocol": "11.2.1",
"MicroCom.Runtime": "0.11.0"
},
"runtime": {
"lib/net8.0/Avalonia.Base.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.Controls.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.DesignerSupport.dll": {
"assemblyVersion": "0.7.0.0",
"fileVersion": "0.7.0.0"
},
"lib/net8.0/Avalonia.Dialogs.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.Markup.Xaml.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.Markup.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.Metal.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.MicroCom.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.OpenGL.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.Vulkan.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
},
"lib/net8.0/Avalonia.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Angle.Windows.Natives/2.1.22045.20230930": {
"runtimeTargets": {
"runtimes/win-arm64/native/av_libglesv2.dll": {
"rid": "win-arm64",
"assetType": "native",
"fileVersion": "2.1.22045.0"
},
"runtimes/win-x64/native/av_libglesv2.dll": {
"rid": "win-x64",
"assetType": "native",
"fileVersion": "2.1.22045.0"
},
"runtimes/win-x86/native/av_libglesv2.dll": {
"rid": "win-x86",
"assetType": "native",
"fileVersion": "2.1.22045.0"
}
}
},
"Avalonia.BuildServices/0.0.29": {},
"Avalonia.Controls.ColorPicker/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.Remote.Protocol": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Controls.ColorPicker.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Controls.DataGrid/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.Remote.Protocol": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Controls.DataGrid.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Desktop/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.Native": "11.2.1",
"Avalonia.Skia": "11.2.1",
"Avalonia.Win32": "11.2.1",
"Avalonia.X11": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Desktop.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Diagnostics/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.Controls.ColorPicker": "11.2.1",
"Avalonia.Controls.DataGrid": "11.2.1",
"Avalonia.Themes.Simple": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Diagnostics.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Fonts.Inter/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Fonts.Inter.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.FreeDesktop/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Tmds.DBus.Protocol": "0.20.0"
},
"runtime": {
"lib/net8.0/Avalonia.FreeDesktop.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Native/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Native.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
},
"runtimeTargets": {
"runtimes/osx/native/libAvaloniaNative.dylib": {
"rid": "osx",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"Avalonia.ReactiveUI/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"ReactiveUI": "20.1.1",
"System.Reactive": "6.0.1"
},
"runtime": {
"lib/net8.0/Avalonia.ReactiveUI.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Remote.Protocol/11.2.1": {
"runtime": {
"lib/net8.0/Avalonia.Remote.Protocol.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Skia/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"HarfBuzzSharp": "7.3.0.2",
"HarfBuzzSharp.NativeAssets.Linux": "7.3.0.2",
"HarfBuzzSharp.NativeAssets.WebAssembly": "7.3.0.3-preview.2.2",
"SkiaSharp": "2.88.8",
"SkiaSharp.NativeAssets.Linux": "2.88.8",
"SkiaSharp.NativeAssets.WebAssembly": "2.88.8"
},
"runtime": {
"lib/net8.0/Avalonia.Skia.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Themes.Fluent/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Themes.Fluent.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Themes.Simple/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.Themes.Simple.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.Win32/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.Angle.Windows.Natives": "2.1.22045.20230930"
},
"runtime": {
"lib/net8.0/Avalonia.Win32.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"Avalonia.X11/11.2.1": {
"dependencies": {
"Avalonia": "11.2.1",
"Avalonia.FreeDesktop": "11.2.1",
"Avalonia.Skia": "11.2.1"
},
"runtime": {
"lib/net8.0/Avalonia.X11.dll": {
"assemblyVersion": "11.2.1.0",
"fileVersion": "11.2.1.0"
}
}
},
"DynamicData/8.4.1": {
"dependencies": {
"System.Reactive": "6.0.1"
},
"runtime": {
"lib/net8.0/DynamicData.dll": {
"assemblyVersion": "8.4.0.0",
"fileVersion": "8.4.1.20756"
}
}
},
"HarfBuzzSharp/7.3.0.2": {
"dependencies": {
"HarfBuzzSharp.NativeAssets.Win32": "7.3.0.2",
"HarfBuzzSharp.NativeAssets.macOS": "7.3.0.2"
},
"runtime": {
"lib/net6.0/HarfBuzzSharp.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "7.3.0.2"
}
}
},
"HarfBuzzSharp.NativeAssets.Linux/7.3.0.2": {
"dependencies": {
"HarfBuzzSharp": "7.3.0.2"
},
"runtimeTargets": {
"runtimes/linux-arm/native/libHarfBuzzSharp.so": {
"rid": "linux-arm",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/linux-arm64/native/libHarfBuzzSharp.so": {
"rid": "linux-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/linux-musl-x64/native/libHarfBuzzSharp.so": {
"rid": "linux-musl-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/linux-x64/native/libHarfBuzzSharp.so": {
"rid": "linux-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"HarfBuzzSharp.NativeAssets.macOS/7.3.0.2": {
"runtimeTargets": {
"runtimes/osx/native/libHarfBuzzSharp.dylib": {
"rid": "osx",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"HarfBuzzSharp.NativeAssets.WebAssembly/7.3.0.3-preview.2.2": {},
"HarfBuzzSharp.NativeAssets.Win32/7.3.0.2": {
"runtimeTargets": {
"runtimes/win-arm64/native/libHarfBuzzSharp.dll": {
"rid": "win-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/win-x64/native/libHarfBuzzSharp.dll": {
"rid": "win-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/win-x86/native/libHarfBuzzSharp.dll": {
"rid": "win-x86",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"MicroCom.Runtime/0.11.0": {
"runtime": {
"lib/net5.0/MicroCom.Runtime.dll": {
"assemblyVersion": "0.11.0.0",
"fileVersion": "0.11.0.0"
}
}
},
"Microsoft.Extensions.DependencyInjection/9.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.4"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/9.0.4": {
"runtime": {
"lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.NETCore.Platforms/3.1.0": {},
"Microsoft.Win32.Registry/4.7.0": {
"dependencies": {
"System.Security.AccessControl": "4.7.0",
"System.Security.Principal.Windows": "4.7.0"
}
},
"NAudio/2.2.1": {
"dependencies": {
"NAudio.Asio": "2.2.1",
"NAudio.Core": "2.2.1",
"NAudio.Midi": "2.2.1",
"NAudio.Wasapi": "2.2.1",
"NAudio.WinMM": "2.2.1"
},
"runtime": {
"lib/net6.0/NAudio.dll": {
"assemblyVersion": "2.2.1.0",
"fileVersion": "2.2.1.0"
}
}
},
"NAudio.Asio/2.2.1": {
"dependencies": {
"Microsoft.Win32.Registry": "4.7.0",
"NAudio.Core": "2.2.1"
},
"runtime": {
"lib/netstandard2.0/NAudio.Asio.dll": {
"assemblyVersion": "2.2.1.0",
"fileVersion": "2.2.1.0"
}
}
},
"NAudio.Core/2.2.1": {
"runtime": {
"lib/netstandard2.0/NAudio.Core.dll": {
"assemblyVersion": "2.2.1.0",
"fileVersion": "2.2.1.0"
}
}
},
"NAudio.Midi/2.2.1": {
"dependencies": {
"NAudio.Core": "2.2.1"
},
"runtime": {
"lib/netstandard2.0/NAudio.Midi.dll": {
"assemblyVersion": "2.2.1.0",
"fileVersion": "2.2.1.0"
}
}
},
"NAudio.Wasapi/2.2.1": {
"dependencies": {
"NAudio.Core": "2.2.1"
},
"runtime": {
"lib/netstandard2.0/NAudio.Wasapi.dll": {
"assemblyVersion": "2.2.1.0",
"fileVersion": "2.2.1.0"
}
}
},
"NAudio.WinMM/2.2.1": {
"dependencies": {
"Microsoft.Win32.Registry": "4.7.0",
"NAudio.Core": "2.2.1"
},
"runtime": {
"lib/netstandard2.0/NAudio.WinMM.dll": {
"assemblyVersion": "2.2.1.0",
"fileVersion": "2.2.1.0"
}
}
},
"ReactiveUI/20.1.1": {
"dependencies": {
"DynamicData": "8.4.1",
"Splat": "15.3.1",
"System.ComponentModel.Annotations": "5.0.0"
},
"runtime": {
"lib/net8.0/ReactiveUI.dll": {
"assemblyVersion": "20.1.0.0",
"fileVersion": "20.1.1.46356"
}
}
},
"SkiaSharp/2.88.8": {
"dependencies": {
"SkiaSharp.NativeAssets.Win32": "2.88.8",
"SkiaSharp.NativeAssets.macOS": "2.88.8"
},
"runtime": {
"lib/net6.0/SkiaSharp.dll": {
"assemblyVersion": "2.88.0.0",
"fileVersion": "2.88.8.0"
}
}
},
"SkiaSharp.NativeAssets.Linux/2.88.8": {
"dependencies": {
"SkiaSharp": "2.88.8"
},
"runtimeTargets": {
"runtimes/linux-arm/native/libSkiaSharp.so": {
"rid": "linux-arm",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/linux-arm64/native/libSkiaSharp.so": {
"rid": "linux-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/linux-musl-x64/native/libSkiaSharp.so": {
"rid": "linux-musl-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/linux-x64/native/libSkiaSharp.so": {
"rid": "linux-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"SkiaSharp.NativeAssets.macOS/2.88.8": {
"runtimeTargets": {
"runtimes/osx/native/libSkiaSharp.dylib": {
"rid": "osx",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"SkiaSharp.NativeAssets.WebAssembly/2.88.8": {},
"SkiaSharp.NativeAssets.Win32/2.88.8": {
"runtimeTargets": {
"runtimes/win-arm64/native/libSkiaSharp.dll": {
"rid": "win-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/win-x64/native/libSkiaSharp.dll": {
"rid": "win-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
},
"runtimes/win-x86/native/libSkiaSharp.dll": {
"rid": "win-x86",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"Splat/15.3.1": {
"runtime": {
"lib/net9.0/Splat.dll": {
"assemblyVersion": "15.3.0.0",
"fileVersion": "15.3.1.27942"
}
}
},
"Splat.Microsoft.Extensions.DependencyInjection/15.3.1": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.4",
"Splat": "15.3.1"
},
"runtime": {
"lib/net9.0/Splat.Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "15.3.0.0",
"fileVersion": "15.3.1.27942"
}
}
},
"System.ComponentModel.Annotations/5.0.0": {},
"System.IO.Pipelines/8.0.0": {},
"System.Reactive/6.0.1": {
"runtime": {
"lib/net6.0/System.Reactive.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.1.7420"
}
}
},
"System.Security.AccessControl/4.7.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "3.1.0",
"System.Security.Principal.Windows": "4.7.0"
}
},
"System.Security.Principal.Windows/4.7.0": {},
"Tmds.DBus.Protocol/0.20.0": {
"dependencies": {
"System.IO.Pipelines": "8.0.0"
},
"runtime": {
"lib/net8.0/Tmds.DBus.Protocol.dll": {
"assemblyVersion": "0.20.0.0",
"fileVersion": "0.20.0.0"
}
}
}
}
},
"libraries": {
"SoundTester/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Avalonia/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-AyYhIN2A7bRwxp6BFHrIbXAHUFPXegzSMYwDrUnw1BzZs9ctwYTiCPCM5wbE2PXsEBwFDVJ/a2YHTOp56fSYAw==",
"path": "avalonia/11.2.1",
"hashPath": "avalonia.11.2.1.nupkg.sha512"
},
"Avalonia.Angle.Windows.Natives/2.1.22045.20230930": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Bo3qOhKC1b84BIhiogndMdAzB3UrrESKK7hS769f5HWeoMw/pcd42US5KFYW2JJ4ZSTrXnP8mXwLTMzh+S+9Lg==",
"path": "avalonia.angle.windows.natives/2.1.22045.20230930",
"hashPath": "avalonia.angle.windows.natives.2.1.22045.20230930.nupkg.sha512"
},
"Avalonia.BuildServices/0.0.29": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U4eJLQdoDNHXtEba7MZUCwrBErBTxFp6sUewXBOdAhU0Kwzwaa/EKFcYm8kpcysjzKtfB4S0S9n0uxKZFz/ikw==",
"path": "avalonia.buildservices/0.0.29",
"hashPath": "avalonia.buildservices.0.0.29.nupkg.sha512"
},
"Avalonia.Controls.ColorPicker/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-t8ViFwfIe6jCO5HvzPWOtwGNSMHYNc8XakWp76Rgy1MOiht8tHKry9cU7k40AHEYU6wVjiYBkl0c8zYZyyha1g==",
"path": "avalonia.controls.colorpicker/11.2.1",
"hashPath": "avalonia.controls.colorpicker.11.2.1.nupkg.sha512"
},
"Avalonia.Controls.DataGrid/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UaNQrY86GBqMZqZ/N/5/wLzr4Emh2N405VZI/IgH0I8BoMrjnosNr+++D7BOcahMNce0lUZLOsFyy+OY02PUAw==",
"path": "avalonia.controls.datagrid/11.2.1",
"hashPath": "avalonia.controls.datagrid.11.2.1.nupkg.sha512"
},
"Avalonia.Desktop/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-q6alzkTgFjukOrbiiFlh0mkhkxGRMRTMS8zdNEixIl9apPnD2ln9sjAC4NR2agNz5+HmZVfXYu6kYK12rMmKwA==",
"path": "avalonia.desktop/11.2.1",
"hashPath": "avalonia.desktop.11.2.1.nupkg.sha512"
},
"Avalonia.Diagnostics/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-axUWa4sZoe9HgUXPEDhbZXijL8ex+lwQGVwNQLmD299O7pCqKcYThjyG/eCETO/boqjKTt3H85LHEPx94BP9dg==",
"path": "avalonia.diagnostics/11.2.1",
"hashPath": "avalonia.diagnostics.11.2.1.nupkg.sha512"
},
"Avalonia.Fonts.Inter/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-egEFQWLHuSzyWKolPy9u4qPor270N2GL/4CI33eBxr09chrUVQsOlxQ6zeWPiBLzzgv/lCrZhOMCAIWsOz3tNg==",
"path": "avalonia.fonts.inter/11.2.1",
"hashPath": "avalonia.fonts.inter.11.2.1.nupkg.sha512"
},
"Avalonia.FreeDesktop/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ChKdPjQ2uBJUN0y+/RsdoETzXRn/q1eWFBDwprDy+Zi/AVkUfRk06hKbsb/U+Q3zO65CMEprRcMPbys0EkK2vg==",
"path": "avalonia.freedesktop/11.2.1",
"hashPath": "avalonia.freedesktop.11.2.1.nupkg.sha512"
},
"Avalonia.Native/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1cVasDUIkqfAYLkaLFDx+VDZymer2v643OYD6Jd6nzP20TNTqN2LfFOpxXCTYMrWc9Dk5AoVJJCrz3wRE5kooQ==",
"path": "avalonia.native/11.2.1",
"hashPath": "avalonia.native.11.2.1.nupkg.sha512"
},
"Avalonia.ReactiveUI/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SgjmPrkpAyxnG9z9Ms1Nj53xTvD2W00GQ0w+WGMrt3Jm8UNHha8b0LK1Gx9WT4Do/ggH51j76RfRdXchbardWw==",
"path": "avalonia.reactiveui/11.2.1",
"hashPath": "avalonia.reactiveui.11.2.1.nupkg.sha512"
},
"Avalonia.Remote.Protocol/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aqEialxjir7DO/dOFf7BGN/yQ4/adSC5UuVfqBr/RUHOENSH6CqoHj8kmtmJxnuz7ESQFSB2+h1kLVnk5csiDw==",
"path": "avalonia.remote.protocol/11.2.1",
"hashPath": "avalonia.remote.protocol.11.2.1.nupkg.sha512"
},
"Avalonia.Skia/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FkqiXWT1hN0s5MIx5IKDGZaqewQENikQh6aBQyApiZVu5koa8H8RW1yfb2cFK3M4IVIyhqwl8ZirkXsS18lf/Q==",
"path": "avalonia.skia/11.2.1",
"hashPath": "avalonia.skia.11.2.1.nupkg.sha512"
},
"Avalonia.Themes.Fluent/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9YUzDmZO5oDppsoA3Igeu/v1cVi4xu8jdO6ZrBzXJXJ9mma/htK0Ub9+V1lRoCW/O70nQfBX+ZDpm0dca1PVgw==",
"path": "avalonia.themes.fluent/11.2.1",
"hashPath": "avalonia.themes.fluent.11.2.1.nupkg.sha512"
},
"Avalonia.Themes.Simple/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ToiYv8hhJ5gcEtD54VZv7NpBFiqGasj4bjFh/AtjXApiYOp8r3orFPX8Nsc3kHcUCvNNjbjAy9dmBG65nYePkw==",
"path": "avalonia.themes.simple/11.2.1",
"hashPath": "avalonia.themes.simple.11.2.1.nupkg.sha512"
},
"Avalonia.Win32/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-7Gfw7S1PoINaCXaIV1rh7zo82IhsqhR7a0PAt281cBrfDkJiNU0DYgW2RZxKl3oVFxtfbxJZbdP7hSVmHvoDfw==",
"path": "avalonia.win32/11.2.1",
"hashPath": "avalonia.win32.11.2.1.nupkg.sha512"
},
"Avalonia.X11/11.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-h2aCpyLmxGkldPK7cbncEgyobrJ5En7gQtrwVARLmN32Rw6dHut3jyF3P8at2DmWxRuKwZVXgWBSSI62hINgrQ==",
"path": "avalonia.x11/11.2.1",
"hashPath": "avalonia.x11.11.2.1.nupkg.sha512"
},
"DynamicData/8.4.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Mn1+fU/jqxgONEJq8KLQPGWEi7g/hUVTbjZyn4QM0sWWDAVOHPO9WjXWORSykwdfg/6S3GM15qsfz+2EvO+QAQ==",
"path": "dynamicdata/8.4.1",
"hashPath": "dynamicdata.8.4.1.nupkg.sha512"
},
"HarfBuzzSharp/7.3.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-0tCd6HyCmNsX/DniCp2b00fo0xPbdNwKOs9BxxyT8oOOuMlWjcSFwzONKyeckCKVBFEsbSmsAHPDTqxoSDwZMg==",
"path": "harfbuzzsharp/7.3.0.2",
"hashPath": "harfbuzzsharp.7.3.0.2.nupkg.sha512"
},
"HarfBuzzSharp.NativeAssets.Linux/7.3.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aKa5J1RqjXKAtdcZJp5wjC78klfBIzJHM6CneN76lFmQ9LLRJA9Oa0TkIDaV8lVLDKMAy5fCKHXFlXUK1YfL/g==",
"path": "harfbuzzsharp.nativeassets.linux/7.3.0.2",
"hashPath": "harfbuzzsharp.nativeassets.linux.7.3.0.2.nupkg.sha512"
},
"HarfBuzzSharp.NativeAssets.macOS/7.3.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-nycYH/WLJ6ogm+I+QSFCdPJsdxSb5GANWYbQyp1vsd/KjXN56RVUJWPhbgP2GKb/Y7mrsHM7EProqVXlO/EMsA==",
"path": "harfbuzzsharp.nativeassets.macos/7.3.0.2",
"hashPath": "harfbuzzsharp.nativeassets.macos.7.3.0.2.nupkg.sha512"
},
"HarfBuzzSharp.NativeAssets.WebAssembly/7.3.0.3-preview.2.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Dc+dolrhmkpqwT25NfNEEgceW0//KRR2WIOvxlyIIHIIMBCn0FfUeJX5RhFll8kyaZwF8tuKsxRJtQG/rzSBog==",
"path": "harfbuzzsharp.nativeassets.webassembly/7.3.0.3-preview.2.2",
"hashPath": "harfbuzzsharp.nativeassets.webassembly.7.3.0.3-preview.2.2.nupkg.sha512"
},
"HarfBuzzSharp.NativeAssets.Win32/7.3.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DpF9JBzwws2dupOLnjME65hxQWWbN/GD40AoTkwB4S05WANvxo3n81AnQJKxWDCnrWfWhLPB36OF27TvEqzb/A==",
"path": "harfbuzzsharp.nativeassets.win32/7.3.0.2",
"hashPath": "harfbuzzsharp.nativeassets.win32.7.3.0.2.nupkg.sha512"
},
"MicroCom.Runtime/0.11.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA==",
"path": "microcom.runtime/0.11.0",
"hashPath": "microcom.runtime.0.11.0.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-f2MTUaS2EQ3lX4325ytPAISZqgBfXmY0WvgD80ji6Z20AoDNiCESxsqo6mFRwHJD/jfVKRw9FsW6+86gNre3ug==",
"path": "microsoft.extensions.dependencyinjection/9.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.9.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UI0TQPVkS78bFdjkTodmkH0Fe8lXv9LnhGFKgKrsgUJ5a5FVdFRcgjIkBVLbGgdRhxWirxH/8IXUtEyYJx6GQg==",
"path": "microsoft.extensions.dependencyinjection.abstractions/9.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.4.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/3.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-z7aeg8oHln2CuNulfhiLYxCVMPEwBl3rzicjvIX+4sUuCwvXw5oXQEtbiU2c0z4qYL5L3Kmx0mMA/+t/SbY67w==",
"path": "microsoft.netcore.platforms/3.1.0",
"hashPath": "microsoft.netcore.platforms.3.1.0.nupkg.sha512"
},
"Microsoft.Win32.Registry/4.7.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-KSrRMb5vNi0CWSGG1++id2ZOs/1QhRqROt+qgbEAdQuGjGrFcl4AOl4/exGPUYz2wUnU42nvJqon1T3U0kPXLA==",
"path": "microsoft.win32.registry/4.7.0",
"hashPath": "microsoft.win32.registry.4.7.0.nupkg.sha512"
},
"NAudio/2.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-c0DzwiyyklM0TP39Y7RObwO3QkWecgM6H60ikiEnsV/aEAJPbj5MFCLaD8BSfKuZe0HGuh9GRGWWlJmSxDc9MA==",
"path": "naudio/2.2.1",
"hashPath": "naudio.2.2.1.nupkg.sha512"
},
"NAudio.Asio/2.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hQglyOT5iT3XuGpBP8ZG0+aoqwRfidHjTNehpoWwX0g6KJEgtH2VaqM2nuJ2mheKZa/IBqB4YQTZVvrIapzfOA==",
"path": "naudio.asio/2.2.1",
"hashPath": "naudio.asio.2.2.1.nupkg.sha512"
},
"NAudio.Core/2.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-GgkdP6K/7FqXFo7uHvoqGZTJvW4z8g2IffhOO4JHaLzKCdDOUEzVKtveoZkCuUX8eV2HAINqi7VFqlFndrnz/g==",
"path": "naudio.core/2.2.1",
"hashPath": "naudio.core.2.2.1.nupkg.sha512"
},
"NAudio.Midi/2.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6r23ylGo5aeP02WFXsPquz0T0hFJWyh+7t++tz19tc3Kr38NHm+Z9j+FiAv+xkH8tZqXJqus9Q8p6u7bidIgbw==",
"path": "naudio.midi/2.2.1",
"hashPath": "naudio.midi.2.2.1.nupkg.sha512"
},
"NAudio.Wasapi/2.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-lFfXoqacZZe0WqNChJgGYI+XV/n/61LzPHT3C1CJp4khoxeo2sziyX5wzNYWeCMNbsWxFvT3b3iXeY1UYjBhZw==",
"path": "naudio.wasapi/2.2.1",
"hashPath": "naudio.wasapi.2.2.1.nupkg.sha512"
},
"NAudio.WinMM/2.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xFHRFwH4x6aq3IxRbewvO33ugJRvZFEOfO62i7uQJRUNW2cnu6BeBTHUS0JD5KBucZbHZaYqxQG8dwZ47ezQuQ==",
"path": "naudio.winmm/2.2.1",
"hashPath": "naudio.winmm.2.2.1.nupkg.sha512"
},
"ReactiveUI/20.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9hNPknWjijnaSWs6auypoXqUptPZcRpUypF+cf1zD50fgW+SEoQda502N3fVZ2eWPcaiUad+z6GaLwOWmUVHNw==",
"path": "reactiveui/20.1.1",
"hashPath": "reactiveui.20.1.1.nupkg.sha512"
},
"SkiaSharp/2.88.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-bRkp3uKp5ZI8gXYQT57uKwil1uobb2p8c69n7v5evlB/2JNcMAXVcw9DZAP5Ig3WSvgzGm2YSn27UVeOi05NlA==",
"path": "skiasharp/2.88.8",
"hashPath": "skiasharp.2.88.8.nupkg.sha512"
},
"SkiaSharp.NativeAssets.Linux/2.88.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-0FO6YA7paNFBMJULvEyecPmCvL9/STvOAi5VOUw2srqJ7pNTbiiZkfl7sulAzcumbWgfzaVjRXYTgMj7SoUnWQ==",
"path": "skiasharp.nativeassets.linux/2.88.8",
"hashPath": "skiasharp.nativeassets.linux.2.88.8.nupkg.sha512"
},
"SkiaSharp.NativeAssets.macOS/2.88.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6Kn5TSkKlfyS6azWHF3Jk2sW5C4jCE5uSshM/5AbfFrR+5n6qM5XEnz9h4VaVl7LTxBvHvMkuPb/3bpbq0vxTw==",
"path": "skiasharp.nativeassets.macos/2.88.8",
"hashPath": "skiasharp.nativeassets.macos.2.88.8.nupkg.sha512"
},
"SkiaSharp.NativeAssets.WebAssembly/2.88.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-S3qRo8c+gVYOyfrdf6FYnjx/ft+gPkb4dNY2IPv5Oy5yNBhDhXhKqHFr9h4+ne6ZU+7D4dbuRQqsIqCo8u1/DA==",
"path": "skiasharp.nativeassets.webassembly/2.88.8",
"hashPath": "skiasharp.nativeassets.webassembly.2.88.8.nupkg.sha512"
},
"SkiaSharp.NativeAssets.Win32/2.88.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-O9QXoWEXA+6cweR4h3BOnwMz+pO9vL9mXdjLrpDd0w1QzCgWmLQBxa1VgySDITiH7nQndrDG1h6937zm9pLj1Q==",
"path": "skiasharp.nativeassets.win32/2.88.8",
"hashPath": "skiasharp.nativeassets.win32.2.88.8.nupkg.sha512"
},
"Splat/15.3.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zyu98Mwp8gTi3MlS6EGtvcacmw5W/qA4/h/DVeZ28A1dR6mcM628ujHck6LK5SM6LwroR5LzBonWgeFtwo2Afg==",
"path": "splat/15.3.1",
"hashPath": "splat.15.3.1.nupkg.sha512"
},
"Splat.Microsoft.Extensions.DependencyInjection/15.3.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9iKQ2T2Mit/yzVew/FEi+A3wWgHEDv8EQtoUX7ArK/bughD17DYVlalM2X/uxW3Jf5BO0xqRByXXTMmV0z2BfA==",
"path": "splat.microsoft.extensions.dependencyinjection/15.3.1",
"hashPath": "splat.microsoft.extensions.dependencyinjection.15.3.1.nupkg.sha512"
},
"System.ComponentModel.Annotations/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==",
"path": "system.componentmodel.annotations/5.0.0",
"hashPath": "system.componentmodel.annotations.5.0.0.nupkg.sha512"
},
"System.IO.Pipelines/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==",
"path": "system.io.pipelines/8.0.0",
"hashPath": "system.io.pipelines.8.0.0.nupkg.sha512"
},
"System.Reactive/6.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rHaWtKDwCi9qJ3ObKo8LHPMuuwv33YbmQi7TcUK1C264V3MFnOr5Im7QgCTdLniztP3GJyeiSg5x8NqYJFqRmg==",
"path": "system.reactive/6.0.1",
"hashPath": "system.reactive.6.0.1.nupkg.sha512"
},
"System.Security.AccessControl/4.7.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JECvTt5aFF3WT3gHpfofL2MNNP6v84sxtXxpqhLBCcDRzqsPBmHhQ6shv4DwwN2tRlzsUxtb3G9M3763rbXKDg==",
"path": "system.security.accesscontrol/4.7.0",
"hashPath": "system.security.accesscontrol.4.7.0.nupkg.sha512"
},
"System.Security.Principal.Windows/4.7.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ojD0PX0XhneCsUbAZVKdb7h/70vyYMDYs85lwEI+LngEONe/17A0cFaRFqZU+sOEidcVswYWikYOQ9PPfjlbtQ==",
"path": "system.security.principal.windows/4.7.0",
"hashPath": "system.security.principal.windows.4.7.0.nupkg.sha512"
},
"Tmds.DBus.Protocol/0.20.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-2gkt2kuYPhDKd8gtl34jZSJOnn4nRJfFngCDcTZT/uySbK++ua0YQx2418l9Rn1Y4dE5XNq6zG9ZsE5ltLlNNw==",
"path": "tmds.dbus.protocol/0.20.0",
"hashPath": "tmds.dbus.protocol.0.20.0.nupkg.sha512"
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,13 @@
{
"runtimeOptions": {
"tfm": "net9.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
},
"configProperties": {
"System.Runtime.InteropServices.BuiltInComInterop.IsSupported": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

BIN
bin/Debug/net9.0/Splat.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")]

View File

@ -0,0 +1 @@
9f85c56b89948d4a430fafe1ae34b39891c7fdfbabf4ff7dd731602c9bc9efe0

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More