Skip to content

Commit

Permalink
Added Microphone Boost
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Ciaran Fisher committed Jun 7, 2016
1 parent 78966de commit b16a608
Show file tree
Hide file tree
Showing 11 changed files with 446 additions and 80 deletions.
147 changes: 147 additions & 0 deletions DCS-SR-Client/AppConfiguration.cs
Original file line number Diff line number Diff line change
@@ -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);

}
}
}
}
47 changes: 36 additions & 11 deletions DCS-SR-Client/AudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class AudioManager

ConcurrentDictionary<String, SRClient> clientsList;

ConcurrentDictionary<String, ClientAudioProvider> clientsBufferedAudio = new ConcurrentDictionary<string, ClientAudioProvider>();
ConcurrentDictionary<String, ClientAudioProvider> _clientsBufferedAudio = new ConcurrentDictionary<string, ClientAudioProvider>();

WaveIn _waveIn;
WaveOut _waveOut;
Expand All @@ -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<String, SRClient> clientsList)
{
Expand All @@ -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;
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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);

Expand Down Expand Up @@ -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);

Expand All @@ -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();
Expand Down
88 changes: 88 additions & 0 deletions DCS-SR-Client/AudioPreview.cs
Original file line number Diff line number Diff line change
@@ -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;
}

}

}
}
2 changes: 2 additions & 0 deletions DCS-SR-Client/DCS-SR-Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,11 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="AudioManager.cs" />
<Compile Include="AudioPreview.cs" />
<Compile Include="ClientAudio.cs" />
<Compile Include="ClientAudioProvider.cs" />
<Compile Include="DejitterBuffer.cs" />
<Compile Include="AppConfiguration.cs" />
<Compile Include="InputConfiguration.cs" />
<Compile Include="InputDevice.cs" />
<Compile Include="InputDeviceManager.cs" />
Expand Down
7 changes: 6 additions & 1 deletion DCS-SR-Client/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -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">

<TabControl>
<TabItem Header="General">
Expand All @@ -17,6 +17,11 @@
<Label x:Name="micLabel" Content="Microphone" HorizontalAlignment="Center"/>
<ComboBox x:Name="mic" HorizontalAlignment="Center" VerticalAlignment="Top" Width="150"/>

<Slider x:Name="microphoneBoost" Width="300" Maximum="6.0" Minimum="1.0" ValueChanged="MicrophoneBoost_ValueChanged" Margin="0,10,0,0"/>

<Button x:Name="preview" HorizontalAlignment="Center" VerticalAlignment="Top" Content="Preview Audio" Margin="0,10,0,0" Click="PreviewAudio" />


<Label x:Name="speakerLabel" Content="Speakers" HorizontalAlignment="Center"/>
<ComboBox x:Name="speakers" HorizontalAlignment="Center" VerticalAlignment="Top" Width="150"/>

Expand Down
Loading

0 comments on commit b16a608

Please sign in to comment.