diff --git a/WhackerLinkConsoleV2/AudioManager.cs b/WhackerLinkConsoleV2/AudioManager.cs
new file mode 100644
index 0000000..ef369da
--- /dev/null
+++ b/WhackerLinkConsoleV2/AudioManager.cs
@@ -0,0 +1,79 @@
+/*
+* WhackerLink - WhackerLinkConsoleV2
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*
+* Copyright (C) 2025 Caleb, K4PHP
+*
+*/
+
+using NAudio.Wave;
+using NAudio.Wave.SampleProviders;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace WhackerLinkConsoleV2
+{
+ public class AudioManager
+ {
+ private WaveOutEvent _waveOut;
+ private MixingSampleProvider _mixer;
+ private Dictionary _talkgroupProviders;
+
+ ///
+ /// Creates an instance of
+ ///
+ public AudioManager()
+ {
+ _waveOut = new WaveOutEvent();
+ _talkgroupProviders = new Dictionary();
+ _mixer = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(8000, 1))
+ {
+ ReadFully = true
+ };
+
+ _waveOut.Init(_mixer);
+ _waveOut.Play();
+ }
+
+ ///
+ /// Bad name, adds samples to a provider or creates a new provider
+ ///
+ ///
+ ///
+ public void AddTalkgroupStream(string talkgroupId, byte[] audioData)
+ {
+ if (!_talkgroupProviders.ContainsKey(talkgroupId))
+ {
+ var provider = new BufferedWaveProvider(new WaveFormat(8000, 16, 1))
+ {
+ DiscardOnBufferOverflow = true
+ };
+
+ _talkgroupProviders[talkgroupId] = provider;
+ _mixer.AddMixerInput(provider.ToSampleProvider());
+ }
+
+ _talkgroupProviders[talkgroupId].AddSamples(audioData, 0, audioData.Length);
+ }
+
+ ///
+ /// Lop off the wave out
+ ///
+ public void Stop()
+ {
+ _waveOut.Stop();
+ }
+ }
+}
diff --git a/WhackerLinkConsoleV2/MainWindow.xaml.cs b/WhackerLinkConsoleV2/MainWindow.xaml.cs
index 8016118..450a4a9 100644
--- a/WhackerLinkConsoleV2/MainWindow.xaml.cs
+++ b/WhackerLinkConsoleV2/MainWindow.xaml.cs
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
-* Copyright (C) 2024 Caleb, K4PHP
+* Copyright (C) 2024-2025 Caleb, K4PHP
*
*/
@@ -53,7 +53,6 @@ namespace WhackerLinkConsoleV2
private double _offsetX;
private double _offsetY;
private bool _isDragging;
- private bool _stopSending;
private SettingsManager _settingsManager = new SettingsManager();
private SelectedChannelsManager _selectedChannelsManager;
@@ -62,8 +61,7 @@ namespace WhackerLinkConsoleV2
private WebSocketManager _webSocketManager = new WebSocketManager();
private readonly WaveInEvent _waveIn;
- private readonly WaveOutEvent _waveOut;
- private readonly BufferedWaveProvider _waveProvider;
+ private readonly AudioManager _audioManager;
public MainWindow()
{
@@ -85,14 +83,7 @@ namespace WhackerLinkConsoleV2
_waveIn.StartRecording();
- _waveOut = new WaveOutEvent();
- _waveProvider = new BufferedWaveProvider(new WaveFormat(8000, 16, 1))
- {
- DiscardOnBufferOverflow = true
- };
- _waveOut.Init(_waveProvider);
-
- _waveOut.Play();
+ _audioManager = new AudioManager();
_selectedChannelsManager.SelectedChannelsChanged += SelectedChannelsChanged;
Loaded += MainWindow_Loaded;
@@ -331,7 +322,7 @@ namespace WhackerLinkConsoleV2
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
IPeer handler = _webSocketManager.GetWebSocketHandler(system.Name);
- if (channel.IsSelected && channel.VoiceChannel != null && !_stopSending)
+ if (channel.IsSelected && channel.VoiceChannel != null && channel.PttState)
{
object voicePaket = new
{
@@ -397,10 +388,10 @@ namespace WhackerLinkConsoleV2
_waveIn.DeviceNumber = inputDeviceIndex.Value;
_waveIn.StartRecording();
- _waveOut.Stop();
- _waveOut.DeviceNumber = outputDeviceIndex.Value;
- _waveOut.Init(_waveProvider);
- _waveOut.Play();
+ //_waveOut.Stop();
+ //_waveOut.DeviceNumber = outputDeviceIndex.Value;
+ //_waveOut.Init(_waveProvider);
+ //_waveOut.Play();
MessageBox.Show("Audio devices updated successfully.", "Success");
}
@@ -462,8 +453,8 @@ namespace WhackerLinkConsoleV2
Task.Factory.StartNew(() =>
{
- _waveProvider.ClearBuffer();
- _waveProvider.AddSamples(combinedAudio, 0, combinedAudio.Length);
+ //_waveProvider.ClearBuffer();
+ _audioManager.AddTalkgroupStream(cpgChannel.Tgid, combinedAudio);
});
for (int i = 0; i < totalChunks; i++)
@@ -659,6 +650,7 @@ namespace WhackerLinkConsoleV2
private void HandleReceivedAudio(AudioPacket audioPacket)
{
bool shouldReceive = false;
+ string talkgroupId = audioPacket.VoiceChannel.DstId;
foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels())
{
@@ -667,14 +659,11 @@ namespace WhackerLinkConsoleV2
IPeer handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (audioPacket.VoiceChannel.SrcId != system.Rid && audioPacket.VoiceChannel.Frequency == channel.VoiceChannel && audioPacket.VoiceChannel.DstId == cpgChannel.Tgid)
- {
- _waveProvider.AddSamples(audioPacket.Data, 0, audioPacket.Data.Length);
- }
+ shouldReceive = true;
}
if (shouldReceive)
- _waveProvider.AddSamples(audioPacket.Data, 0, audioPacket.Data.Length);
-
+ _audioManager.AddTalkgroupStream(talkgroupId, audioPacket.Data);
}
private void HandleVoiceRelease(GRP_VCH_RLS response)
@@ -711,7 +700,6 @@ namespace WhackerLinkConsoleV2
if (channel.PttState && response.Status == (int)ResponseType.GRANT && response.Channel != null && response.SrcId == system.Rid && response.DstId == cpgChannel.Tgid)
{
channel.VoiceChannel = response.Channel;
- _stopSending = false;
} else if (response.Status == (int)ResponseType.GRANT && response.SrcId != system.Rid && response.DstId == cpgChannel.Tgid)
{
channel.VoiceChannel = response.Channel;
@@ -759,7 +747,6 @@ namespace WhackerLinkConsoleV2
}
else
{
- //_stopSending = true;
GRP_VCH_RLS release = new GRP_VCH_RLS
{
SrcId = system.Rid,
@@ -795,7 +782,6 @@ namespace WhackerLinkConsoleV2
}
else
{
- _stopSending = true;
GRP_VCH_RLS release = new GRP_VCH_RLS
{
SrcId = system.Rid,