Refactor the audio system; use a AudioManager to manage incoming audio; refactor how we check to send or not send audio

pull/1/head
firealarmss 1 year ago
parent 2102570d51
commit 3ad8b9b867

@ -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 <http://www.gnu.org/licenses/>.
*
* 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<string, BufferedWaveProvider> _talkgroupProviders;
/// <summary>
/// Creates an instance of <see cref="AudioManager"/>
/// </summary>
public AudioManager()
{
_waveOut = new WaveOutEvent();
_talkgroupProviders = new Dictionary<string, BufferedWaveProvider>();
_mixer = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(8000, 1))
{
ReadFully = true
};
_waveOut.Init(_mixer);
_waveOut.Play();
}
/// <summary>
/// Bad name, adds samples to a provider or creates a new provider
/// </summary>
/// <param name="talkgroupId"></param>
/// <param name="audioData"></param>
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);
}
/// <summary>
/// Lop off the wave out
/// </summary>
public void Stop()
{
_waveOut.Stop();
}
}
}

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* Copyright (C) 2024 Caleb, K4PHP * Copyright (C) 2024-2025 Caleb, K4PHP
* *
*/ */
@ -53,7 +53,6 @@ namespace WhackerLinkConsoleV2
private double _offsetX; private double _offsetX;
private double _offsetY; private double _offsetY;
private bool _isDragging; private bool _isDragging;
private bool _stopSending;
private SettingsManager _settingsManager = new SettingsManager(); private SettingsManager _settingsManager = new SettingsManager();
private SelectedChannelsManager _selectedChannelsManager; private SelectedChannelsManager _selectedChannelsManager;
@ -62,8 +61,7 @@ namespace WhackerLinkConsoleV2
private WebSocketManager _webSocketManager = new WebSocketManager(); private WebSocketManager _webSocketManager = new WebSocketManager();
private readonly WaveInEvent _waveIn; private readonly WaveInEvent _waveIn;
private readonly WaveOutEvent _waveOut; private readonly AudioManager _audioManager;
private readonly BufferedWaveProvider _waveProvider;
public MainWindow() public MainWindow()
{ {
@ -85,14 +83,7 @@ namespace WhackerLinkConsoleV2
_waveIn.StartRecording(); _waveIn.StartRecording();
_waveOut = new WaveOutEvent(); _audioManager = new AudioManager();
_waveProvider = new BufferedWaveProvider(new WaveFormat(8000, 16, 1))
{
DiscardOnBufferOverflow = true
};
_waveOut.Init(_waveProvider);
_waveOut.Play();
_selectedChannelsManager.SelectedChannelsChanged += SelectedChannelsChanged; _selectedChannelsManager.SelectedChannelsChanged += SelectedChannelsChanged;
Loaded += MainWindow_Loaded; Loaded += MainWindow_Loaded;
@ -331,7 +322,7 @@ namespace WhackerLinkConsoleV2
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName); Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
IPeer handler = _webSocketManager.GetWebSocketHandler(system.Name); IPeer handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (channel.IsSelected && channel.VoiceChannel != null && !_stopSending) if (channel.IsSelected && channel.VoiceChannel != null && channel.PttState)
{ {
object voicePaket = new object voicePaket = new
{ {
@ -397,10 +388,10 @@ namespace WhackerLinkConsoleV2
_waveIn.DeviceNumber = inputDeviceIndex.Value; _waveIn.DeviceNumber = inputDeviceIndex.Value;
_waveIn.StartRecording(); _waveIn.StartRecording();
_waveOut.Stop(); //_waveOut.Stop();
_waveOut.DeviceNumber = outputDeviceIndex.Value; //_waveOut.DeviceNumber = outputDeviceIndex.Value;
_waveOut.Init(_waveProvider); //_waveOut.Init(_waveProvider);
_waveOut.Play(); //_waveOut.Play();
MessageBox.Show("Audio devices updated successfully.", "Success"); MessageBox.Show("Audio devices updated successfully.", "Success");
} }
@ -462,8 +453,8 @@ namespace WhackerLinkConsoleV2
Task.Factory.StartNew(() => Task.Factory.StartNew(() =>
{ {
_waveProvider.ClearBuffer(); //_waveProvider.ClearBuffer();
_waveProvider.AddSamples(combinedAudio, 0, combinedAudio.Length); _audioManager.AddTalkgroupStream(cpgChannel.Tgid, combinedAudio);
}); });
for (int i = 0; i < totalChunks; i++) for (int i = 0; i < totalChunks; i++)
@ -659,6 +650,7 @@ namespace WhackerLinkConsoleV2
private void HandleReceivedAudio(AudioPacket audioPacket) private void HandleReceivedAudio(AudioPacket audioPacket)
{ {
bool shouldReceive = false; bool shouldReceive = false;
string talkgroupId = audioPacket.VoiceChannel.DstId;
foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels()) foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels())
{ {
@ -667,14 +659,11 @@ namespace WhackerLinkConsoleV2
IPeer handler = _webSocketManager.GetWebSocketHandler(system.Name); IPeer handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (audioPacket.VoiceChannel.SrcId != system.Rid && audioPacket.VoiceChannel.Frequency == channel.VoiceChannel && audioPacket.VoiceChannel.DstId == cpgChannel.Tgid) if (audioPacket.VoiceChannel.SrcId != system.Rid && audioPacket.VoiceChannel.Frequency == channel.VoiceChannel && audioPacket.VoiceChannel.DstId == cpgChannel.Tgid)
{ shouldReceive = true;
_waveProvider.AddSamples(audioPacket.Data, 0, audioPacket.Data.Length);
}
} }
if (shouldReceive) if (shouldReceive)
_waveProvider.AddSamples(audioPacket.Data, 0, audioPacket.Data.Length); _audioManager.AddTalkgroupStream(talkgroupId, audioPacket.Data);
} }
private void HandleVoiceRelease(GRP_VCH_RLS response) 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) if (channel.PttState && response.Status == (int)ResponseType.GRANT && response.Channel != null && response.SrcId == system.Rid && response.DstId == cpgChannel.Tgid)
{ {
channel.VoiceChannel = response.Channel; channel.VoiceChannel = response.Channel;
_stopSending = false;
} else if (response.Status == (int)ResponseType.GRANT && response.SrcId != system.Rid && response.DstId == cpgChannel.Tgid) } else if (response.Status == (int)ResponseType.GRANT && response.SrcId != system.Rid && response.DstId == cpgChannel.Tgid)
{ {
channel.VoiceChannel = response.Channel; channel.VoiceChannel = response.Channel;
@ -759,7 +747,6 @@ namespace WhackerLinkConsoleV2
} }
else else
{ {
//_stopSending = true;
GRP_VCH_RLS release = new GRP_VCH_RLS GRP_VCH_RLS release = new GRP_VCH_RLS
{ {
SrcId = system.Rid, SrcId = system.Rid,
@ -795,7 +782,6 @@ namespace WhackerLinkConsoleV2
} }
else else
{ {
_stopSending = true;
GRP_VCH_RLS release = new GRP_VCH_RLS GRP_VCH_RLS release = new GRP_VCH_RLS
{ {
SrcId = system.Rid, SrcId = system.Rid,

Loading…
Cancel
Save

Powered by TurnKey Linux.