From b16a6083b32c57cc0bbb392d320975c17304d607 Mon Sep 17 00:00:00 2001 From: Ciaran Fisher Date: Tue, 7 Jun 2016 22:27:27 +0100 Subject: [PATCH] Added Microphone Boost Added Microphone Boost #7 Fixed Client audio not working after disconnecting once and reconnecting Saved common settings #8 Added ability to use domain name in the connect window --- DCS-SR-Client/AppConfiguration.cs | 147 ++++++++++++ DCS-SR-Client/AudioManager.cs | 47 +++- DCS-SR-Client/AudioPreview.cs | 88 +++++++ DCS-SR-Client/DCS-SR-Client.csproj | 2 + DCS-SR-Client/MainWindow.xaml | 7 +- DCS-SR-Client/MainWindow.xaml.cs | 217 +++++++++++++----- DCS-SR-Client/Properties/AssemblyInfo.cs | 4 +- .../Properties/AssemblyInfo.cs | 4 +- Installer/Properties/AssemblyInfo.cs | 4 +- RadioGui/Properties/AssemblyInfo.cs | 4 +- Scripts/DCS-SimpleRadioStandalone.lua | 2 +- 11 files changed, 446 insertions(+), 80 deletions(-) create mode 100644 DCS-SR-Client/AppConfiguration.cs create mode 100644 DCS-SR-Client/AudioPreview.cs diff --git a/DCS-SR-Client/AppConfiguration.cs b/DCS-SR-Client/AppConfiguration.cs new file mode 100644 index 000000000..423f5c8b6 --- /dev/null +++ b/DCS-SR-Client/AppConfiguration.cs @@ -0,0 +1,147 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ciribob.DCS.SimpleRadio.Standalone.Client +{ + public class AppConfiguration + { + public enum RegKeys + { + AUDIO_INPUT_DEVICE_ID, + AUDIO_OUTPUT_DEVICE_ID, + LAST_SERVER, + MIC_BOOST + } + + const string REG_PATH = "HKEY_CURRENT_USER\\SOFTWARE\\DCS-SimpleRadioStandalone"; + + private int _audioInputDeviceId; + private int _audioOutputDeviceId; + private String _lastServer; + private float _micBoost; + + public AppConfiguration() + { + try + { + AudioInputDeviceId = (int)Registry.GetValue(REG_PATH, + RegKeys.AUDIO_INPUT_DEVICE_ID.ToString(), + 0); + } + catch (Exception ex) + { + AudioInputDeviceId = 0; + } + + try + { + AudioOutputDeviceId = (int)Registry.GetValue(REG_PATH, + RegKeys.AUDIO_OUTPUT_DEVICE_ID.ToString(), + 0); + } + catch (Exception ex) + { + AudioOutputDeviceId = 0; + } + + try + { + LastServer = (String)Registry.GetValue(REG_PATH, + RegKeys.LAST_SERVER.ToString(), + "127.0.0.1"); + + } + catch (Exception ex) + { + LastServer = "127.0.0.1"; + } + + try + { + MicBoost = float.Parse( (String)Registry.GetValue(REG_PATH, + RegKeys.MIC_BOOST.ToString(), + "1.0")); + } + catch (Exception ex) + { + MicBoost = 1.0f; + } + + + + + + } + + + public int AudioInputDeviceId + { + get + { + return _audioInputDeviceId; + } + set + { + _audioInputDeviceId = value; + + Registry.SetValue(REG_PATH, + RegKeys.AUDIO_INPUT_DEVICE_ID.ToString(), + _audioInputDeviceId); + + } + } + + public int AudioOutputDeviceId + { + get + { + return _audioOutputDeviceId; + } + set + { + _audioOutputDeviceId = value; + + Registry.SetValue(REG_PATH, + RegKeys.AUDIO_OUTPUT_DEVICE_ID.ToString(), + _audioOutputDeviceId); + + } + } + public String LastServer + { + get + { + return _lastServer; + } + set + { + _lastServer = value; + + Registry.SetValue(REG_PATH, + RegKeys.LAST_SERVER.ToString(), + _lastServer); + + } + } + public float MicBoost + { + get + { + return _micBoost; + } + set + { + _micBoost = value; + + Registry.SetValue(REG_PATH, + RegKeys.MIC_BOOST.ToString(), + _micBoost); + + } + } + } +} diff --git a/DCS-SR-Client/AudioManager.cs b/DCS-SR-Client/AudioManager.cs index 317a6d54e..8242574be 100644 --- a/DCS-SR-Client/AudioManager.cs +++ b/DCS-SR-Client/AudioManager.cs @@ -23,7 +23,7 @@ public class AudioManager ConcurrentDictionary clientsList; - ConcurrentDictionary clientsBufferedAudio = new ConcurrentDictionary(); + ConcurrentDictionary _clientsBufferedAudio = new ConcurrentDictionary(); WaveIn _waveIn; WaveOut _waveOut; @@ -37,7 +37,9 @@ public class AudioManager byte[] _notEncodedBuffer = new byte[0]; UDPVoiceHandler udpVoiceHandler; - MixingSampleProvider mixing; + MixingSampleProvider _mixing; + + public float Volume { get; set; } = 1.0f; public AudioManager(ConcurrentDictionary clientsList) { @@ -50,18 +52,18 @@ internal void addClientAudio(ClientAudio audio) //Clean - remove if we havent received audio in a while // If we have recieved audio, create a new buffered audio and read it ClientAudioProvider client = null; - if (clientsBufferedAudio.ContainsKey(audio.ClientGUID)) + if (_clientsBufferedAudio.ContainsKey(audio.ClientGUID)) { - client = clientsBufferedAudio[audio.ClientGUID]; + client = _clientsBufferedAudio[audio.ClientGUID]; client.lastUpdate = GetTickCount64(); } else { client = new ClientAudioProvider(); client.lastUpdate = GetTickCount64(); - clientsBufferedAudio[audio.ClientGUID] = client; + _clientsBufferedAudio[audio.ClientGUID] = client; - mixing.AddMixerInput(client.VolumeSampleProvider); + _mixing.AddMixerInput(client.VolumeSampleProvider); } client.VolumeSampleProvider.Volume = audio.Volume; @@ -80,13 +82,13 @@ public void StartEncoding(int mic, int speakers, string guid, InputDeviceManager { // _playBuffer = new BufferedWaveProvider(new NAudio.Wave.WaveFormat(48000, 16, 1)); - mixing = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(24000, 1)); + _mixing = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(24000, 1)); //add silence track? BufferedWaveProvider provider = new BufferedWaveProvider(WaveFormat.CreateIeeeFloatWaveFormat(24000, 1)); // provider.BufferDuration = TimeSpan.FromMilliseconds(100); - mixing.AddMixerInput(provider); + _mixing.AddMixerInput(provider); //TODO pass all this to the audio manager @@ -97,7 +99,7 @@ public void StartEncoding(int mic, int speakers, string guid, InputDeviceManager _waveOut.DesiredLatency = 100; //75ms latency in output buffer _waveOut.DeviceNumber = speakers; - _waveOut.Init(mixing); + _waveOut.Init(_mixing); _waveOut.Play(); _segmentFrames = 960; //960 frames is 20 ms of audio @@ -112,7 +114,6 @@ public void StartEncoding(int mic, int speakers, string guid, InputDeviceManager _waveIn.DataAvailable += _waveIn_DataAvailable; _waveIn.WaveFormat = new NAudio.Wave.WaveFormat(24000, 16, 1); // should this be 44100?? - udpVoiceHandler = new UDPVoiceHandler(clientsList, guid, ipAddress, _decoder, this, inputManager); Thread voiceSenderThread = new Thread(udpVoiceHandler.Listen); @@ -157,10 +158,27 @@ void _waveIn_DataAvailable(object sender, WaveInEventArgs e) for (int i = 0; i < segmentCount; i++) { + //create segment of audio byte[] segment = new byte[byteCap]; for (int j = 0; j < segment.Length; j++) + { segment[j] = soundBuffer[(i * byteCap) + j]; - + } + + //boost microphone volume if needed + if (Volume != 1.0f) + { + for (int n = 0; n < segment.Length; n += 2) + { + short sample = (short)((segment[n + 1] << 8) | segment[n + 0]); + // n.b. no clipping test going on here // FROM NAUDIO SOURCE ! + sample = (short)(sample * this.Volume); + segment[n] = (byte)(sample & 0xFF); + segment[n + 1] = (byte)(sample >> 8); + } + } + + //encode as opus bytes int len; byte[] buff = _encoder.Encode(segment, segment.Length, out len); @@ -171,6 +189,13 @@ void _waveIn_DataAvailable(object sender, WaveInEventArgs e) public void StopEncoding() { + if(_mixing!=null) + { + _mixing.RemoveAllMixerInputs(); + } + + _clientsBufferedAudio.Clear(); + if (_waveIn != null) { _waveIn.StopRecording(); diff --git a/DCS-SR-Client/AudioPreview.cs b/DCS-SR-Client/AudioPreview.cs new file mode 100644 index 000000000..a4b9ce355 --- /dev/null +++ b/DCS-SR-Client/AudioPreview.cs @@ -0,0 +1,88 @@ +using Ciribob.DCS.SimpleRadio.Standalone.Client; +using NAudio.Wave; +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ciribob.DCS.SimpleRadio.Standalone.Client +{ + class AudioPreview + { + private static Logger logger = LogManager.GetCurrentClassLogger(); + WaveIn _waveIn; + WaveOut _waveOut; + BufferedWaveProvider _playBuffer; + + public VolumeWaveProvider16 Volume { get; private set; } + + public void StartPreview(int mic, int speakers) + { + try + { + _playBuffer = new BufferedWaveProvider(new NAudio.Wave.WaveFormat(24000, 16, 1)); + + _waveOut = new WaveOut(); + _waveOut.DesiredLatency = 100; //75ms latency in output buffer + _waveOut.DeviceNumber = speakers; + + Volume = new VolumeWaveProvider16(_playBuffer); + Volume.Volume = 1.0f; // seems a good max 4.5f + + _waveOut.Init(Volume); + _waveOut.Play(); + + _waveIn = new WaveIn(WaveCallbackInfo.FunctionCallback()); + _waveIn.BufferMilliseconds = 60; + _waveIn.DeviceNumber = mic; + _waveIn.DataAvailable += _waveIn_DataAvailable; + _waveIn.WaveFormat = new NAudio.Wave.WaveFormat(24000, 16, 1); + + _waveIn.StartRecording(); + } + catch (Exception ex) + { + logger.Error(ex, "Error starting audio Quitting!"); + + Environment.Exit(1); + } + + } + + + + void _waveIn_DataAvailable(object sender, WaveInEventArgs e) + { + + _playBuffer.AddSamples(e.Buffer, 0, e.BytesRecorded); + + } + + public void StopEncoding() + { + if (_waveIn != null) + { + _waveIn.StopRecording(); + _waveIn.Dispose(); + _waveIn = null; + } + + if (_waveOut != null) + { + _waveOut.Stop(); + _waveOut.Dispose(); + _waveOut = null; + } + + if (_playBuffer != null) + { + _playBuffer.ClearBuffer(); + _playBuffer = null; + } + + } + + } +} diff --git a/DCS-SR-Client/DCS-SR-Client.csproj b/DCS-SR-Client/DCS-SR-Client.csproj index e54fa57df..8f0d82a01 100644 --- a/DCS-SR-Client/DCS-SR-Client.csproj +++ b/DCS-SR-Client/DCS-SR-Client.csproj @@ -125,9 +125,11 @@ Designer + + diff --git a/DCS-SR-Client/MainWindow.xaml b/DCS-SR-Client/MainWindow.xaml index 682fe686b..bfae574ba 100644 --- a/DCS-SR-Client/MainWindow.xaml +++ b/DCS-SR-Client/MainWindow.xaml @@ -6,7 +6,7 @@ xmlns:local="clr-namespace:DCS_SR_Client" mc:Ignorable="d" ResizeMode="CanMinimize" - Title="SR Client" Height="300" Width="500"> + Title="SR Client" Height="350" Width="500"> @@ -17,6 +17,11 @@