diff --git a/WhackerLinkConsoleV2.sln b/WhackerLinkConsoleV2.sln index 149eb69..0309ce5 100644 --- a/WhackerLinkConsoleV2.sln +++ b/WhackerLinkConsoleV2.sln @@ -15,35 +15,50 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 NoVocode|Any CPU = NoVocode|Any CPU + NoVocode|x64 = NoVocode|x64 NoVocode|x86 = NoVocode|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5918329A-6374-40E2-874D-445360C89676}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5918329A-6374-40E2-874D-445360C89676}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5918329A-6374-40E2-874D-445360C89676}.Debug|x64.ActiveCfg = AmbeVocode|x64 + {5918329A-6374-40E2-874D-445360C89676}.Debug|x64.Build.0 = AmbeVocode|x64 {5918329A-6374-40E2-874D-445360C89676}.Debug|x86.ActiveCfg = Debug|x86 {5918329A-6374-40E2-874D-445360C89676}.Debug|x86.Build.0 = Debug|x86 {5918329A-6374-40E2-874D-445360C89676}.NoVocode|Any CPU.ActiveCfg = NoVocode|Any CPU {5918329A-6374-40E2-874D-445360C89676}.NoVocode|Any CPU.Build.0 = NoVocode|Any CPU + {5918329A-6374-40E2-874D-445360C89676}.NoVocode|x64.ActiveCfg = NoVocode|x64 + {5918329A-6374-40E2-874D-445360C89676}.NoVocode|x64.Build.0 = NoVocode|x64 {5918329A-6374-40E2-874D-445360C89676}.NoVocode|x86.ActiveCfg = NoVocode|x86 {5918329A-6374-40E2-874D-445360C89676}.NoVocode|x86.Build.0 = NoVocode|x86 {5918329A-6374-40E2-874D-445360C89676}.Release|Any CPU.ActiveCfg = Release|Any CPU {5918329A-6374-40E2-874D-445360C89676}.Release|Any CPU.Build.0 = Release|Any CPU + {5918329A-6374-40E2-874D-445360C89676}.Release|x64.ActiveCfg = Release|x64 + {5918329A-6374-40E2-874D-445360C89676}.Release|x64.Build.0 = Release|x64 {5918329A-6374-40E2-874D-445360C89676}.Release|x86.ActiveCfg = Release|x86 {5918329A-6374-40E2-874D-445360C89676}.Release|x86.Build.0 = Release|x86 {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Debug|x64.ActiveCfg = Debug|x64 + {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Debug|x64.Build.0 = Debug|x64 {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Debug|x86.ActiveCfg = Debug|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Debug|x86.Build.0 = Debug|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.NoVocode|Any CPU.ActiveCfg = Debug|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.NoVocode|Any CPU.Build.0 = Debug|Any CPU + {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.NoVocode|x64.ActiveCfg = Debug|x64 + {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.NoVocode|x64.Build.0 = Debug|x64 {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.NoVocode|x86.ActiveCfg = Debug|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.NoVocode|x86.Build.0 = Debug|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Release|Any CPU.ActiveCfg = Release|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Release|Any CPU.Build.0 = Release|Any CPU + {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Release|x64.ActiveCfg = Release|x64 + {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Release|x64.Build.0 = Release|x64 {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Release|x86.ActiveCfg = Release|Any CPU {710D1FA8-2E0D-42CB-9174-FCD9EB7A718F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection diff --git a/WhackerLinkConsoleV2/AudioManager.cs b/WhackerLinkConsoleV2/AudioManager.cs index 45ee825..7ed87d2 100644 --- a/WhackerLinkConsoleV2/AudioManager.cs +++ b/WhackerLinkConsoleV2/AudioManager.cs @@ -24,6 +24,9 @@ using System.Collections.Generic; namespace WhackerLinkConsoleV2 { + /// + /// Class for managing + /// public class AudioManager { private Dictionary _talkgroupProviders; diff --git a/WhackerLinkConsoleV2/MainWindow.xaml.cs b/WhackerLinkConsoleV2/MainWindow.xaml.cs index c8cb50d..62d8a5e 100644 --- a/WhackerLinkConsoleV2/MainWindow.xaml.cs +++ b/WhackerLinkConsoleV2/MainWindow.xaml.cs @@ -429,7 +429,7 @@ namespace WhackerLinkConsoleV2 _audioManager.AddTalkgroupStream(cpgChannel.Tgid, combinedAudio); }); - await Task.Run(async () => + await Task.Run(() => { for (int i = 0; i < totalChunks; i++) { @@ -454,12 +454,10 @@ namespace WhackerLinkConsoleV2 }; handler.SendMessage(voicePacket.GetData()); - - await Task.Delay(20); } }); - double totalDurationMs = (toneADuration + toneBDuration) * 1000 + 500; + double totalDurationMs = (toneADuration + toneBDuration) * 1000 + 250; await Task.Delay((int)totalDurationMs); GRP_VCH_RLS release = new GRP_VCH_RLS @@ -474,6 +472,7 @@ namespace WhackerLinkConsoleV2 Dispatcher.Invoke(() => { + //channel.PageState = false; // TODO: Investigate channel.PageSelectButton.Background = Brushes.Green; }); } @@ -487,18 +486,6 @@ namespace WhackerLinkConsoleV2 { try { - try - { - using (var player = new SoundPlayer(e.AlertFilePath)) - { - player.Play(); - } - } - catch (Exception ex) - { - MessageBox.Show($"Failed to play alert: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); - } - foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels()) { Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName); @@ -507,37 +494,49 @@ namespace WhackerLinkConsoleV2 if (channel.PageState) { - List pcmChunks = new List(); - WaveFileReader waveReader = null; + byte[] pcmData; - using (waveReader = new WaveFileReader(e.AlertFilePath)) + using (var waveReader = new WaveFileReader(e.AlertFilePath)) { - if (waveReader.WaveFormat.Encoding != WaveFormatEncoding.Pcm) + if (waveReader.WaveFormat.Encoding != WaveFormatEncoding.Pcm || + waveReader.WaveFormat.SampleRate != 8000 || + waveReader.WaveFormat.BitsPerSample != 16 || + waveReader.WaveFormat.Channels != 1) { - MessageBox.Show("The alert tone is not in PCM format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show("The alert tone must be PCM 16-bit, Mono, 8000Hz format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - byte[] buffer = new byte[1600]; - int bytesRead; - - while ((bytesRead = waveReader.Read(buffer, 0, buffer.Length)) > 0) + using (MemoryStream ms = new MemoryStream()) { - if (bytesRead < buffer.Length) - { - byte[] finalChunk = new byte[bytesRead]; - Array.Copy(buffer, finalChunk, bytesRead); - pcmChunks.Add(finalChunk); - } - else - { - pcmChunks.Add((byte[])buffer.Clone()); - } + waveReader.CopyTo(ms); + pcmData = ms.ToArray(); } } - foreach (var chunk in pcmChunks) + int chunkSize = 1600; + int totalChunks = (pcmData.Length + chunkSize - 1) / chunkSize; + + if (pcmData.Length % chunkSize != 0) { + byte[] paddedData = new byte[totalChunks * chunkSize]; + Buffer.BlockCopy(pcmData, 0, paddedData, 0, pcmData.Length); + pcmData = paddedData; + } + + Task.Factory.StartNew(() => + { + _audioManager.AddTalkgroupStream(cpgChannel.Tgid, pcmData); + }); + + DateTime startTime = DateTime.UtcNow; + + for (int i = 0; i < totalChunks; i++) + { + int offset = i * chunkSize; + byte[] chunk = new byte[chunkSize]; + Buffer.BlockCopy(pcmData, offset, chunk, 0, chunkSize); + AudioPacket voicePacket = new AudioPacket { Data = chunk, @@ -554,10 +553,18 @@ namespace WhackerLinkConsoleV2 handler.SendMessage(voicePacket.GetData()); - int chunkDurationMs = (int)(1600.0 / waveReader.WaveFormat.AverageBytesPerSecond * 1000); - await Task.Delay(chunkDurationMs); + DateTime nextPacketTime = startTime.AddMilliseconds((i + 1) * 100); + TimeSpan waitTime = nextPacketTime - DateTime.UtcNow; + + if (waitTime.TotalMilliseconds > 0) + { + await Task.Delay(waitTime); + } } + double totalDurationMs = ((double)pcmData.Length / 16000) * 1000 + 500; + await Task.Delay((int)totalDurationMs); + GRP_VCH_RLS release = new GRP_VCH_RLS { SrcId = system.Rid, diff --git a/WhackerLinkConsoleV2/SettingsManager.cs b/WhackerLinkConsoleV2/SettingsManager.cs index 9e0acee..96690b9 100644 --- a/WhackerLinkConsoleV2/SettingsManager.cs +++ b/WhackerLinkConsoleV2/SettingsManager.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 * */ diff --git a/WhackerLinkConsoleV2/WhackerLinkConsoleV2.csproj b/WhackerLinkConsoleV2/WhackerLinkConsoleV2.csproj index 06be86e..f081958 100644 --- a/WhackerLinkConsoleV2/WhackerLinkConsoleV2.csproj +++ b/WhackerLinkConsoleV2/WhackerLinkConsoleV2.csproj @@ -6,6 +6,7 @@ disable enable true + AnyCPU;x64