using System.Diagnostics; using System.Reflection; using HidLibrary; using Voicemeeter; using VoiceMeeter; namespace HidSliders.Gui { public partial class Form1 : Form { private IDisposable? _vmClient; private IHidDevice? _hidDevice; private const float Resolution = 72.0f; private readonly List _channels; public Form1() { InitializeComponent(); _channels = new List { new (numericUpDown1, trackBar1, ch1A1Checkbox, ch1A2Checkbox, ch1A3Checkbox, ch1A4Checkbox, ch1A5Checkbox, ch1B1Checkbox, ch1B2Checkbox, ch1B3Checkbox, checkBox1, checkBox2), new (numericUpDown2, trackBar2, checkBox12, checkBox11, checkBox10, checkBox9, checkBox8, checkBox7, checkBox6, checkBox5, checkBox4, checkBox3), new (numericUpDown3, trackBar3, checkBox22, checkBox21, checkBox20, checkBox19, checkBox18, checkBox17, checkBox16, checkBox15, checkBox14, checkBox13), new (numericUpDown4, trackBar4, checkBox32, checkBox31, checkBox30, checkBox29, checkBox28, checkBox27, checkBox26, checkBox25, checkBox24, checkBox23), new (numericUpDown5, trackBar5, checkBox42, checkBox41, checkBox40, checkBox39, checkBox38, checkBox37, checkBox36, checkBox35, checkBox34, checkBox33), }; switch (Properties.Settings.Default.VMVersion) { case 1: vmRadio.Checked = true; break; case 2: vmBananaRadio.Checked = true; break; case 3: vmPotatoRadio.Checked = true; break; } _channels[0].ChannelSelector.Value = Properties.Settings.Default.Channel1Strip; _channels[1].ChannelSelector.Value = Properties.Settings.Default.Channel2Strip; _channels[2].ChannelSelector.Value = Properties.Settings.Default.Channel3Strip; _channels[3].ChannelSelector.Value = Properties.Settings.Default.Channel4Strip; _channels[4].ChannelSelector.Value = Properties.Settings.Default.Channel5Strip; var enumerator = new HidEnumerator(); var hidDevices = enumerator.Enumerate(0x0359, [0x6497]); _hidDevice = hidDevices.FirstOrDefault(); label1.Text = $"Mixer {(_hidDevice?.IsConnected == true ? "" : "not ")}connected"; } private async void connectButton_Click(object sender, EventArgs e) { RunVoicemeeterParam version = RunVoicemeeterParam.None; if (vmRadio.Checked) { version = RunVoicemeeterParam.Voicemeeter; } else if (vmBananaRadio.Checked) { version = RunVoicemeeterParam.VoicemeeterBanana; } else if (vmPotatoRadio.Checked) { version = RunVoicemeeterParam.VoicemeeterPotato; } Properties.Settings.Default.VMVersion = (int)version; _vmClient = await Remote.Initialize(version); if (_vmClient != null) { EnableVMControls(version); } } private void EnableVMControls(RunVoicemeeterParam version) { foreach (var channel in _channels) { channel.TrackBar.Enabled = true; channel.SoloCheckBox.Enabled = true; channel.MuteCheckBox.Enabled = true; channel.EnableBusses(version); SyncChannelControls(channel); } } private void SyncChannelControls(ChannelControlCollection channel) { channel.BusA1Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A1); channel.BusB1Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.B1); if (vmBananaRadio.Checked || vmPotatoRadio.Checked) { channel.BusA2Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A2); channel.BusA3Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A3); channel.BusB2Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.B2); } if (vmPotatoRadio.Checked) { channel.BusA4Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A4); channel.BusA5Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.A5); channel.BusB3Checkbox.Checked = GetBusEnabled(channel.CurrentStrip, VMBus.B3); } channel.TrackBar.Value = (int)GetStripGain(channel.CurrentStrip); channel.SoloCheckBox.Checked = GetChannelSolo(channel.CurrentStrip); channel.MuteCheckBox.Checked = GetChannelMute(channel.CurrentStrip); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { _vmClient?.Dispose(); Properties.Settings.Default.Save(); } private async void button1_Click(object sender, EventArgs e) { if (_hidDevice == null) return; var stopwatch = new Stopwatch(); while (true) { if (_hidDevice.IsConnected) { button1.Enabled = false; stopwatch.Start(); //label1.Text = "waiting for report"; var progress = new Progress(); progress.ProgressChanged += (o, s) => label1.Text = s; var report = await Task.Run(() => _hidDevice.ReadReport()); var labelText = string.Empty; if (report.ReadStatus == HidDeviceData.ReadStatus.Success) { var reportChunk = new byte[2]; for (int i = 0; i < 5; i++) { Array.Copy(report.Data, i * 2, reportChunk, 0, 2); var sliderVal = BitConverter.ToInt16(reportChunk); var gain = HidToGain(sliderVal); labelText += $"Value {i}: {sliderVal} ({gain}dB)\n"; SetStripGain(_channels[i].CurrentStrip, gain); _channels[i].TrackBar.Value = (int)gain; } } stopwatch.Stop(); labelText += $"Report time: {stopwatch.ElapsedMilliseconds}ms"; stopwatch.Reset(); label1.Text = labelText; //button1.Enabled = true; } else { button1.Enabled = true; } } } private float HidToGain(int hidValue) { // adjusted regression of yamaha board is approx y = 5.8456 + 17.0486 * ln(x) // Truncate to first decimal (move decimal, int truncate, move decimal) var realResult = 5.8456f + 17.0486f * (float)Math.Log(Math.Max(hidValue / Resolution, 0.02)); return ((int)(realResult * 10)) / 10.0f; } private void trackBar_Scroll(object sender, EventArgs e) { if (sender is TrackBar trackBar && _vmClient != null) { var channel = _channels.First(c => c.OwnsControl(trackBar)); SetStripGain(channel.CurrentStrip, trackBar.Value); } } private void busCheckbox_CheckedChanged(object sender, EventArgs e) { if (sender is CheckBox { Tag: VMBus bus } checkBox && _vmClient != null) { var channel = _channels.First(c => c.OwnsControl(checkBox)); SetBusEnabled(channel.CurrentStrip, bus, checkBox.Checked); } } private void SetStripGain(int strip, float value) { Remote.SetParameter($"Strip[{strip}].Gain", value); } private float GetStripGain(int index) { return Remote.GetParameter($"Strip[{index}].Gain"); } private void vmRadio_CheckedChanged(object sender, EventArgs e) { if (vmRadio.Checked) { setMaxChannel(2); } } private void vmBananaRadio_CheckedChanged(object sender, EventArgs e) { if (vmBananaRadio.Checked) { setMaxChannel(4); } } private void setMaxChannel(int max) { numericUpDown1.Maximum = max; numericUpDown2.Maximum = max; numericUpDown3.Maximum = max; numericUpDown4.Maximum = max; numericUpDown5.Maximum = max; } private void vmPotatoRadio_CheckedChanged(object sender, EventArgs e) { if (vmPotatoRadio.Checked) { setMaxChannel(7); } } private void SetBusEnabled(int strip, VMBus bus, bool enabled) { Remote.SetParameter($"Strip[{strip}].{bus}", enabled ? 1 : 0); } private bool GetBusEnabled(int strip, VMBus bus) { return (int)Remote.GetParameter($"Strip[{strip}].{bus}") == 1; } private void SetChannelSolo(int strip, bool enabled) { Remote.SetParameter($"Strip[{strip}].Solo", enabled ? 1 : 0); } private bool GetChannelSolo(int strip) { return (int)Remote.GetParameter($"Strip[{strip}].Solo") == 1; } private void SetChannelMute(int strip, bool enabled) { Remote.SetParameter($"Strip[{strip}].Mute", enabled ? 1 : 0); } private bool GetChannelMute(int strip) { return (int)Remote.GetParameter($"Strip[{strip}].Mute") == 1; } private void numericUpDown_ValueChanged(object sender, EventArgs e) { if (sender is NumericUpDown numericUpDown) { var channel = _channels.First(c => c.OwnsControl(numericUpDown)); if (_vmClient != null) { SyncChannelControls(channel); } var index = _channels.FindIndex(c => c == channel); var settingsType = Properties.Settings.Default.GetType(); settingsType.GetProperty($"Channel{index + 1}Strip").SetValue(Properties.Settings.Default, (int)numericUpDown.Value); } } private void soloCheckBox_CheckedChanged(object sender, EventArgs e) { if (sender is CheckBox checkBox && _vmClient != null) { var channel = _channels.First(c => c.OwnsControl(checkBox)); SetChannelSolo(channel.CurrentStrip, checkBox.Checked); } } private void muteCheckBox_CheckedChanged(object sender, EventArgs e) { if (sender is CheckBox checkBox && _vmClient != null) { var channel = _channels.First(c => c.OwnsControl(checkBox)); SetChannelMute(channel.CurrentStrip, checkBox.Checked); } } } }