public void AddClientAudioSamples(ClientAudio audio) { var newTransmission = LikelyNewTransmission(); if (newTransmission) { Logger.Debug($"{LogClientId}| Likely New Transmission"); } var decoded = Decoder.Decode(audio.EncodedAudio, audio.EncodedAudio.Length, out var decodedLength, newTransmission); if (decodedLength > 0) { // for some reason if this is removed then it lags?! //guess it makes a giant buffer and only uses a little? //Answer: makes a buffer of 4000 bytes - so throw away most of it var tmp = new byte[decodedLength]; Buffer.BlockCopy(decoded, 0, tmp, 0, decodedLength); audio.PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp); if (newTransmission) { // System.Diagnostics.Debug.WriteLine(audio.ClientGuid+"ADDED"); //append ms of silence - this functions as our jitter buffer?? var silencePad = AudioManager.InputSampleRate / 1000 * SilencePad; var newAudio = new short[audio.PcmAudioShort.Length + silencePad]; Buffer.BlockCopy(audio.PcmAudioShort, 0, newAudio, silencePad, audio.PcmAudioShort.Length); audio.PcmAudioShort = newAudio; } LastUpdate = DateTime.Now.Ticks; var pcmAudio = ConversionHelpers.ShortArrayToByteArray(audio.PcmAudioShort); _speechAudioProvider.AddSamples(pcmAudio, 0, pcmAudio.Length); } else { Logger.Debug($"{LogClientId}| Failed to decode audio from Packet for client"); } }
private void TaskAudioSub(CancellationToken cancelToken, BlockingCollection <ClientAudio> outputQueue, string address) { using (var subSocket = new SubscriberSocket()) { //subSocket.Options.ReceiveHighWatermark = 1000; subSocket.Connect(address); subSocket.Subscribe(callsign); while (!cancelToken.IsCancellationRequested) { var messageTopicReceived = subSocket.ReceiveFrameString(); //Should always == _username int bytesReceived = 0; ClientAudio clientAudio = subSocket.Deserialise <ClientAudio>(out bytesReceived); ClientStatistics.AudioBytesReceived += bytesReceived; outputQueue.Add(clientAudio); } } taskAudioSub = null; }
public void AddAudio(ClientAudio audio) { lock (_lock) { var radioBuffer = _clientRadioBuffers[audio.ReceivedRadio]; if (!radioBuffer.ContainsKey(audio.ClientGuid)) { radioBuffer[audio.ClientGuid] = new List <ClientAudio> { audio }; } else { // logger.Info("adding"); radioBuffer[audio.ClientGuid].Add(audio); } } }
public void AddClientAudio(ClientAudio audio) { //sort out effects! //16bit PCM Audio //TODO: 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)) { client = _clientsBufferedAudio[audio.ClientGuid]; } else { client = new ClientAudioProvider(); _clientsBufferedAudio[audio.ClientGuid] = client; _clientAudioMixer.AddMixerInput(client.SampleProvider); } client.AddClientAudioSamples(audio); }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = GetTickCount64(); //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length > 36)) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent()) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); // check the radio RadioReceivingState receivingState = null; var receivingRadio = _clientStateSingleton.DcsPlayerRadioInfo.CanHearTransmission( udpVoicePacket.Frequency, (RadioInformation.Modulation)udpVoicePacket.Modulation, udpVoicePacket.UnitId, out receivingState); //Check that we're not transmitting on this radio double receivingPowerLossPercent = 0; float lineOfSightLoss = 0; if ((receivingRadio != null) && (receivingState != null) && ((receivingRadio.modulation == RadioInformation.Modulation.INTERCOM) // INTERCOM Modulation is 2 so if its two dont bother checking LOS and Range || ( HasLineOfSight(udpVoicePacket, out lineOfSightLoss) && InRange(udpVoicePacket, out receivingPowerLossPercent) && !ShouldBlockRxAsTransmitting(receivingState.ReceivedOn) ) ) ) { // RadioReceivingState[receivingState.ReceivedOn] = receivingState; //DECODE audio int len1; var decoded = _decoder.Decode(udpVoicePacket.AudioPart1Bytes, udpVoicePacket.AudioPart1Bytes.Length, out len1); if (len1 > 0) { // for some reason if this is removed then it lags?! //guess it makes a giant buffer and only uses a little? var tmp = new byte[len1]; Buffer.BlockCopy(decoded, 0, tmp, 0, len1); //ALL GOOD! //create marker for bytes var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp), //Convert to Shorts! ReceiveTime = GetTickCount64(), Frequency = udpVoicePacket.Frequency, Modulation = udpVoicePacket.Modulation, Volume = receivingRadio.volume, ReceivedRadio = receivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = udpVoicePacket.Encryption, Decryptable = (udpVoicePacket.Encryption == receivingRadio.encKey) && receivingRadio.enc, // mark if we can decrypt it RadioReceivingState = receivingState, RecevingPower = receivingPowerLossPercent, //loss of 1.0 or greater is total loss LineOfSightLoss = lineOfSightLoss, // Loss of 1.0 or greater is total loss PacketNumber = udpVoicePacket.PacketNumber }; //handle effects var radioState = RadioReceivingState[audio.ReceivedRadio]; if ((radioState == null) || radioState.PlayedEndOfTransmission || !radioState.IsReceiving) { var decrytable = audio.Decryptable || (audio.Encryption == 0); //mark that we have decrpyted encrypted audio for sound effects if (decrytable && (audio.Encryption > 0)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, true, audio.Volume); } else { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume); } } RadioReceivingState[audio.ReceivedRadio] = new RadioReceivingState { IsSecondary = receivingState.IsSecondary, LastReceviedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = receivingState.ReceivedOn }; _audioManager.AddClientAudio(audio); } else { Logger.Info("Failed to decode audio from Packet"); } } } } } catch (Exception ex) { Logger.Info("Failed to decode audio from Packet"); } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = DateTime.Now.Ticks; //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length >= (UDPVoicePacket.PacketHeaderLength + UDPVoicePacket.FixedPacketLength + UDPVoicePacket.FrequencySegmentLength))) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null)) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); if (udpVoicePacket != null) { var vehicleId = -1; if (_clients.TryGetValue(udpVoicePacket.Guid, out var transmittingClient)) { vehicleId = transmittingClient.GameState.vehicleId; } var globalFrequencies = _serverSettings.GlobalFrequencies; var frequencyCount = udpVoicePacket.Frequencies.Length; List <RadioReceivingPriority> radioReceivingPriorities = new List <RadioReceivingPriority>(frequencyCount); List <int> blockedRadios = CurrentlyBlockedRadios(); // Parse frequencies into receiving radio priority for selection below for (var i = 0; i < frequencyCount; i++) { RadioReceivingState state = null; bool decryptable; //Check if Global bool globalFrequency = globalFrequencies.Contains(udpVoicePacket.Frequencies[i]); var radio = _clientStateSingleton.PlayerGameState.CanHearTransmission( udpVoicePacket.Frequencies[i], (RadioInformation.Modulation)udpVoicePacket.Modulations[i], udpVoicePacket.UnitId, vehicleId, blockedRadios, out state); float losLoss = 0.0f; double receivPowerLossPercent = 0.0; if (radio != null && state != null) { if ( radio.modulation == RadioInformation.Modulation.INTERCOM || globalFrequency || (!blockedRadios.Contains(state.ReceivedOn) ) ) { radioReceivingPriorities.Add(new RadioReceivingPriority() { Frequency = udpVoicePacket.Frequencies[i], Modulation = udpVoicePacket.Modulations[i], ReceivingRadio = radio, ReceivingState = state }); } } } // Sort receiving radios to play audio on correct one radioReceivingPriorities.Sort(SortRadioReceivingPriorities); if (radioReceivingPriorities.Count > 0) { //ALL GOOD! //create marker for bytes for (int i = 0; i < radioReceivingPriorities.Count; i++) { var destinationRadio = radioReceivingPriorities[i]; var isSimultaneousTransmission = radioReceivingPriorities.Count > 1 && i > 0; var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, EncodedAudio = udpVoicePacket.AudioPart1Bytes, //Convert to Shorts! ReceiveTime = DateTime.Now.Ticks, Frequency = destinationRadio.Frequency, Modulation = destinationRadio.Modulation, Volume = destinationRadio.ReceivingRadio.volume, ReceivedRadio = destinationRadio.ReceivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, RadioReceivingState = destinationRadio.ReceivingState, PacketNumber = udpVoicePacket.PacketNumber, OriginalClientGuid = udpVoicePacket.OriginalClientGuid }; //handle effects var radioState = _radioReceivingState[audio.ReceivedRadio]; if (!isSimultaneousTransmission && (radioState == null || radioState.PlayedEndOfTransmission || !radioState.IsReceiving)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume, (RadioInformation.Modulation)audio.Modulation); } var transmitterName = ""; if (_serverSettings.GetSettingAsBool(ServerSettingsKeys.SHOW_TRANSMITTER_NAME) && _globalSettings.GetClientSettingBool(GlobalSettingsKeys.ShowTransmitterName) && transmittingClient != null) { transmitterName = transmittingClient.Name; } var newRadioReceivingState = new RadioReceivingState { IsSecondary = destinationRadio.ReceivingState.IsSecondary, LastReceivedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = destinationRadio.ReceivingState.ReceivedOn, SentBy = transmitterName }; _radioReceivingState[audio.ReceivedRadio] = newRadioReceivingState; // Only play actual audio once if (i == 0) { _audioManager.AddClientAudio(audio); } } } } } } } catch (Exception ex) { if (!_stop) { Logger.Info(ex, "Failed to decode audio from Packet"); } } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = DateTime.Now.Ticks; //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length >= (UDPVoicePacket.PacketHeaderLength + UDPVoicePacket.FixedPacketLength + UDPVoicePacket.FrequencySegmentLength))) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent()) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); if (udpVoicePacket != null && udpVoicePacket.Modulations[0] != 4) { var globalFrequencies = _serverSettings.GlobalFrequencies; var frequencyCount = udpVoicePacket.Frequencies.Length; List <RadioReceivingPriority> radioReceivingPriorities = new List <RadioReceivingPriority>(frequencyCount); List <int> blockedRadios = CurrentlyBlockedRadios(); // Parse frequencies into receiving radio priority for selection below for (var i = 0; i < frequencyCount; i++) { RadioReceivingState state = null; bool decryptable; //Check if Global bool globalFrequency = globalFrequencies.Contains(udpVoicePacket.Frequencies[i]); if (globalFrequency) { //remove encryption for global udpVoicePacket.Encryptions[i] = 0; } var radio = _clientStateSingleton.DcsPlayerRadioInfo.CanHearTransmission( udpVoicePacket.Frequencies[i], (RadioInformation.Modulation)udpVoicePacket.Modulations[i], udpVoicePacket.Encryptions[i], udpVoicePacket.UnitId, blockedRadios, out state, out decryptable); float losLoss = 0.0f; double receivPowerLossPercent = 0.0; if (radio != null && state != null) { if ( radio.modulation == RadioInformation.Modulation.INTERCOM || globalFrequency || ( HasLineOfSight(udpVoicePacket, out losLoss) && InRange(udpVoicePacket.Guid, udpVoicePacket.Frequencies[i], out receivPowerLossPercent) && !blockedRadios.Contains(state.ReceivedOn) ) ) { decryptable = (udpVoicePacket.Encryptions[i] == 0) || (udpVoicePacket.Encryptions[i] == radio.encKey && radio.enc); radioReceivingPriorities.Add(new RadioReceivingPriority() { Decryptable = decryptable, Encryption = udpVoicePacket.Encryptions[i], Frequency = udpVoicePacket.Frequencies[i], LineOfSightLoss = losLoss, Modulation = udpVoicePacket.Modulations[i], ReceivingPowerLossPercent = receivPowerLossPercent, ReceivingRadio = radio, ReceivingState = state }); } } } // Sort receiving radios to play audio on correct one radioReceivingPriorities.Sort(SortRadioReceivingPriorities); if (radioReceivingPriorities.Count > 0) { //ALL GOOD! //create marker for bytes for (int i = 0; i < radioReceivingPriorities.Count; i++) { var destinationRadio = radioReceivingPriorities[i]; var isSimultaneousTransmission = radioReceivingPriorities.Count > 1 && i > 0; var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, EncodedAudio = udpVoicePacket.AudioPart1Bytes, //Convert to Shorts! ReceiveTime = DateTime.Now.Ticks, Frequency = destinationRadio.Frequency, Modulation = destinationRadio.Modulation, Volume = destinationRadio.ReceivingRadio.volume, ReceivedRadio = destinationRadio.ReceivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = destinationRadio.Encryption, Decryptable = destinationRadio.Decryptable, // mark if we can decrypt it RadioReceivingState = destinationRadio.ReceivingState, RecevingPower = destinationRadio .ReceivingPowerLossPercent, //loss of 1.0 or greater is total loss LineOfSightLoss = destinationRadio .LineOfSightLoss, // Loss of 1.0 or greater is total loss PacketNumber = udpVoicePacket.PacketNumber }; //handle effects var radioState = RadioReceivingState[audio.ReceivedRadio]; if (!isSimultaneousTransmission && (radioState == null || radioState.PlayedEndOfTransmission || !radioState.IsReceiving)) { var audioDecryptable = audio.Decryptable || (audio.Encryption == 0); //mark that we have decrpyted encrypted audio for sound effects if (audioDecryptable && (audio.Encryption > 0)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, true, audio.Volume); } else { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume); } } RadioReceivingState[audio.ReceivedRadio] = new RadioReceivingState { IsSecondary = destinationRadio.ReceivingState.IsSecondary, IsSimultaneous = isSimultaneousTransmission, LastReceviedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = destinationRadio.ReceivingState.ReceivedOn }; // Only play actual audio once if (i == 0) { _audioManager.AddClientAudio(audio); } } } } } } } catch (Exception ex) { if (!_stop) { Logger.Info(ex, "Failed to decode audio from Packet"); } } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; try { _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); } catch (OperationCanceledException ex) { Logger.Debug(ex, $"{_mainClient.LogClientId}| Cancelled operating to get encoded audio"); } if (encodedOpusAudio == null || encodedOpusAudio.Length < UDPVoicePacket.PacketHeaderLength + UDPVoicePacket.FixedPacketLength + UDPVoicePacket.FrequencySegmentLength) { continue; } // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if (myClient == null) { continue; } //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); if (udpVoicePacket == null || (Modulation)udpVoicePacket.Modulations[0] != Modulation.AM && (Modulation)udpVoicePacket.Modulations[0] != Modulation.FM) { continue; } var globalFrequencies = _serverSettings.GlobalFrequencies; var frequencyCount = udpVoicePacket.Frequencies.Length; var radioReceivingPriorities = new List <RadioReceivingPriority>(frequencyCount); var blockedRadios = CurrentlyBlockedRadios(); // Parse frequencies into receiving radio priority for selection below for (var i = 0; i < frequencyCount; i++) { //Check if Global var globalFrequency = globalFrequencies.Contains(udpVoicePacket.Frequencies[i]); if (globalFrequency) { //remove encryption for global udpVoicePacket.Encryptions[i] = 0; } var radio = _mainClient.DcsPlayerRadioInfo.CanHearTransmission( udpVoicePacket.Frequencies[i], (Modulation)udpVoicePacket.Modulations[i], udpVoicePacket.Encryptions[i], udpVoicePacket.UnitId, blockedRadios, out var state, out var decryptable); var losLoss = 0.0f; var receivPowerLossPercent = 0.0; if (radio == null || state == null) { continue; } if (radio.modulation != Modulation.INTERCOM && !globalFrequency && (!HasLineOfSight(udpVoicePacket, out losLoss) || !InRange(udpVoicePacket.Guid, udpVoicePacket.Frequencies[i], out receivPowerLossPercent) || blockedRadios.Contains(state.ReceivedOn))) { continue; } decryptable = udpVoicePacket.Encryptions[i] == 0 || udpVoicePacket.Encryptions[i] == radio.encKey && radio.enc; radioReceivingPriorities.Add(new RadioReceivingPriority { Decryptable = decryptable, Encryption = udpVoicePacket.Encryptions[i], Frequency = udpVoicePacket.Frequencies[i], LineOfSightLoss = losLoss, Modulation = udpVoicePacket.Modulations[i], ReceivingPowerLossPercent = receivPowerLossPercent, ReceivingRadio = radio, ReceivingState = state }); } // Sort receiving radios to play audio on correct one radioReceivingPriorities.Sort(SortRadioReceivingPriorities); if (radioReceivingPriorities.Count <= 0) { continue; } { //ALL GOOD! //create marker for bytes for (var i = 0; i < radioReceivingPriorities.Count; i++) { var destinationRadio = radioReceivingPriorities[i]; var isSimultaneousTransmission = radioReceivingPriorities.Count > 1 && i > 0; var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, EncodedAudio = udpVoicePacket.AudioPart1Bytes, //Convert to Shorts! ReceiveTime = DateTime.Now.Ticks, Frequency = destinationRadio.Frequency, Modulation = destinationRadio.Modulation, Volume = destinationRadio.ReceivingRadio.volume, ReceivedRadio = destinationRadio.ReceivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = destinationRadio.Encryption, Decryptable = destinationRadio.Decryptable, // mark if we can decrypt it RadioReceivingState = destinationRadio.ReceivingState, RecevingPower = destinationRadio .ReceivingPowerLossPercent, //loss of 1.0 or greater is total loss LineOfSightLoss = destinationRadio .LineOfSightLoss, // Loss of 1.0 or greater is total loss PacketNumber = udpVoicePacket.PacketNumber }; RadioReceivingState[audio.ReceivedRadio] = new RadioReceivingState { IsSecondary = destinationRadio.ReceivingState.IsSecondary, IsSimultaneous = isSimultaneousTransmission, LastReceviedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = destinationRadio.ReceivingState.ReceivedOn }; // Only play actual audio once if (i == 0) { _mainClient.AudioManager.AddClientAudio(audio); } } } } catch (Exception ex) { if (!_stop) { Logger.Info(ex, $"{_mainClient.LogClientId}| Failed to decode audio from Packet"); } } } } catch (OperationCanceledException) { Logger.Info($"{_mainClient.LogClientId}| Stopped DeJitter Buffer"); } }
public void AddClientAudio(ClientAudio audio) { BotAudioProvider.AddClientAudioSamples(audio); }
public ClientAudio Send(byte[] bytes, int len) { // List of radios the transmission is sent to (can me multiple if simultaneous transmission is enabled) List <RadioInformation> transmittingRadios; //if either PTT is true, a microphone is available && socket connected etc var sendingOn = -1; if (_ready && _listener != null && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent() && _audioInputSingleton.MicrophoneAvailable && (bytes != null) && (transmittingRadios = PTTPressed(out sendingOn)).Count > 0) //can only send if DCS is connected { try { if (transmittingRadios.Count > 0) { List <double> frequencies = new List <double>(transmittingRadios.Count); List <byte> encryptions = new List <byte>(transmittingRadios.Count); List <byte> modulations = new List <byte>(transmittingRadios.Count); for (int i = 0; i < transmittingRadios.Count; i++) { var radio = transmittingRadios[i]; // Further deduplicate transmitted frequencies if they have the same freq./modulation/encryption (caused by differently named radios) bool alreadyIncluded = false; for (int j = 0; j < frequencies.Count; j++) { if (frequencies[j] == radio.freq && modulations[j] == (byte)radio.modulation && encryptions[j] == (radio.enc ? radio.encKey : (byte)0)) { alreadyIncluded = true; break; } } if (alreadyIncluded) { continue; } frequencies.Add(radio.freq); encryptions.Add(radio.enc ? radio.encKey : (byte)0); modulations.Add((byte)radio.modulation); } //generate packet var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = bytes, AudioPart1Length = (ushort)bytes.Length, Frequencies = frequencies.ToArray(), UnitId = _clientStateSingleton.DcsPlayerRadioInfo.unitId, Encryptions = encryptions.ToArray(), Modulations = modulations.ToArray(), PacketNumber = _packetNumber++, OriginalClientGuidBytes = _guidAsciiBytes }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); _listener.Send(encodedUdpVoicePacket, encodedUdpVoicePacket.Length, new IPEndPoint(_address, _port)); var currentlySelectedRadio = _clientStateSingleton.DcsPlayerRadioInfo.radios[sendingOn]; //not sending or really quickly switched sending if (currentlySelectedRadio != null && (!_clientStateSingleton.RadioSendingState.IsSending || _clientStateSingleton.RadioSendingState.SendingOn != sendingOn)) { _audioManager.PlaySoundEffectStartTransmit(sendingOn, currentlySelectedRadio.enc && (currentlySelectedRadio.encKey > 0), currentlySelectedRadio.volume, currentlySelectedRadio.modulation); } //set radio overlay state _clientStateSingleton.RadioSendingState = new RadioSendingState { IsSending = true, LastSentAt = DateTime.Now.Ticks, SendingOn = sendingOn }; var send = new ClientAudio() { Frequency = frequencies[0], Modulation = modulations[0], EncodedAudio = bytes, Encryption = 0, Volume = 1, Decryptable = true, LineOfSightLoss = 0, RecevingPower = 0, ReceivedRadio = 1 }; return(send); } } catch (Exception e) { Logger.Error(e, "Exception Sending Audio Message " + e.Message); } } else { if (_clientStateSingleton.RadioSendingState.IsSending) { _clientStateSingleton.RadioSendingState.IsSending = false; if (_clientStateSingleton.RadioSendingState.SendingOn >= 0) { var radio = _clientStateSingleton.DcsPlayerRadioInfo.radios[_clientStateSingleton.RadioSendingState.SendingOn]; _audioManager.PlaySoundEffectEndTransmit(_clientStateSingleton.RadioSendingState.SendingOn, radio.volume, radio.modulation); } } } return(null); }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = GetTickCount64(); //should add at the receive instead? if (encodedOpusAudio != null && encodedOpusAudio.Length > 36) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if (myClient != null && RadioDCSSyncServer.DcsPlayerRadioInfo.IsCurrent()) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); // check the radio RadioReceivingState receivingState = null; var receivingRadio = RadioDCSSyncServer.DcsPlayerRadioInfo.CanHearTransmission(udpVoicePacket.Frequency, udpVoicePacket.Modulation, udpVoicePacket.UnitId, out receivingState); //Check that we're not transmitting on this radio double receivingPower = 0; float lineOfSightLoss = 0; if (receivingRadio != null && receivingState != null && (receivingRadio.modulation == 2 // INTERCOM Modulation is 2 so if its two dont bother checking LOS and Range || ( HasLineOfSight(udpVoicePacket, out lineOfSightLoss) && InRange(udpVoicePacket, out receivingPower) && !ShouldBlockRxAsTransmitting(receivingState.ReceivedOn) ) ) ) { // RadioReceivingState[receivingState.ReceivedOn] = receivingState; //DECODE audio int len1; var decoded = _decoder.Decode(udpVoicePacket.AudioPart1Bytes, udpVoicePacket.AudioPart1Bytes.Length, out len1); int len2; var decoded2 = _decoder.Decode(udpVoicePacket.AudioPart2Bytes, udpVoicePacket.AudioPart2Bytes.Length, out len2); if (len1 > 0 && len2 > 0) { // for some reason if this is removed then it lags?! //guess it makes a giant buffer and only uses a little? var tmp = new byte[len1 + len2]; Buffer.BlockCopy(decoded, 0, tmp, 0, len1); Buffer.BlockCopy(decoded2, 0, tmp, len1, len2); //ALL GOOD! //create marker for bytes var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp), //Convert to Shorts! ReceiveTime = GetTickCount64(), Frequency = udpVoicePacket.Frequency, Modulation = udpVoicePacket.Modulation, Volume = receivingRadio.volume, ReceivedRadio = receivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = udpVoicePacket.Encryption, Decryptable = udpVoicePacket.Encryption == receivingRadio.encKey && receivingRadio.enc, // mark if we can decrypt it RadioReceivingState = receivingState, RecevingPower = receivingPower, LineOfSightLoss = lineOfSightLoss // Loss of 1.0 or greater is total loss }; //add to JitterBuffer! lock (_lock) { _jitterBuffer.AddAudio(audio); } } } } } } catch (Exception ex) { Logger.Info("Failed Decoding"); } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = DateTime.Now.Ticks; //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length >= (UDPVoicePacket.PacketHeaderLength + UDPVoicePacket.FixedPacketLength + UDPVoicePacket.FrequencySegmentLength))) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent()) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); if (udpVoicePacket != null) { var globalFrequencies = _serverSettings.GlobalFrequencies; var frequencyCount = udpVoicePacket.Frequencies.Length; List <RadioReceivingPriority> radioReceivingPriorities = new List <RadioReceivingPriority>(frequencyCount); List <int> blockedRadios = CurrentlyBlockedRadios(); var strictEncryption = _serverSettings.GetSettingAsBool(ServerSettingsKeys.STRICT_RADIO_ENCRYPTION); // Parse frequencies into receiving radio priority for selection below for (var i = 0; i < frequencyCount; i++) { RadioReceivingState state = null; bool decryptable; //Check if Global bool globalFrequency = globalFrequencies.Contains(udpVoicePacket.Frequencies[i]); if (globalFrequency) { //remove encryption for global udpVoicePacket.Encryptions[i] = 0; } var radio = _clientStateSingleton.DcsPlayerRadioInfo.CanHearTransmission( udpVoicePacket.Frequencies[i], (RadioInformation.Modulation)udpVoicePacket.Modulations[i], udpVoicePacket.Encryptions[i], strictEncryption, udpVoicePacket.UnitId, blockedRadios, out state, out decryptable); float losLoss = 0.0f; double receivPowerLossPercent = 0.0; if (radio != null && state != null) { if ( radio.modulation == RadioInformation.Modulation.INTERCOM || radio.modulation == RadioInformation.Modulation.MIDS || // IGNORE LOS and Distance for MIDS - we assume a Link16 Network is in place globalFrequency || ( HasLineOfSight(udpVoicePacket, out losLoss) && InRange(udpVoicePacket.Guid, udpVoicePacket.Frequencies[i], out receivPowerLossPercent) && !blockedRadios.Contains(state.ReceivedOn) ) ) { // This is already done in CanHearTransmission!! //decryptable = // (udpVoicePacket.Encryptions[i] == radio.encKey && radio.enc) || // (!strictEncryption && udpVoicePacket.Encryptions[i] == 0); radioReceivingPriorities.Add(new RadioReceivingPriority() { Decryptable = decryptable, Encryption = udpVoicePacket.Encryptions[i], Frequency = udpVoicePacket.Frequencies[i], LineOfSightLoss = losLoss, Modulation = udpVoicePacket.Modulations[i], ReceivingPowerLossPercent = receivPowerLossPercent, ReceivingRadio = radio, ReceivingState = state }); } } } // Sort receiving radios to play audio on correct one radioReceivingPriorities.Sort(SortRadioReceivingPriorities); if (radioReceivingPriorities.Count > 0) { //ALL GOOD! //create marker for bytes for (int i = 0; i < radioReceivingPriorities.Count; i++) { var destinationRadio = radioReceivingPriorities[i]; var isSimultaneousTransmission = radioReceivingPriorities.Count > 1 && i > 0; var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, EncodedAudio = udpVoicePacket.AudioPart1Bytes, //Convert to Shorts! ReceiveTime = DateTime.Now.Ticks, Frequency = destinationRadio.Frequency, Modulation = destinationRadio.Modulation, Volume = destinationRadio.ReceivingRadio.volume, ReceivedRadio = destinationRadio.ReceivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = destinationRadio.Encryption, Decryptable = destinationRadio.Decryptable, // mark if we can decrypt it RadioReceivingState = destinationRadio.ReceivingState, RecevingPower = destinationRadio .ReceivingPowerLossPercent, //loss of 1.0 or greater is total loss LineOfSightLoss = destinationRadio .LineOfSightLoss, // Loss of 1.0 or greater is total loss PacketNumber = udpVoicePacket.PacketNumber, OriginalClientGuid = udpVoicePacket.OriginalClientGuid }; //handle effects var radioState = _radioReceivingState[audio.ReceivedRadio]; if (!isSimultaneousTransmission && (radioState == null || radioState.PlayedEndOfTransmission || !radioState.IsReceiving)) { var audioDecryptable = audio.Decryptable /* || (audio.Encryption == 0) <--- this has already been tested above */; //mark that we have decrypted encrypted audio for sound effects if (audioDecryptable && (audio.Encryption > 0)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, true, audio.Volume, (Modulation)audio.Modulation); } else { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume, (Modulation)audio.Modulation); } } var transmitterName = ""; if (_serverSettings.GetSettingAsBool(ServerSettingsKeys.SHOW_TRANSMITTER_NAME) && _globalSettings.GetClientSettingBool(GlobalSettingsKeys.ShowTransmitterName) && _clients.TryGetValue(udpVoicePacket.Guid, out var transmittingClient)) { transmitterName = transmittingClient.Name; } var newRadioReceivingState = new RadioReceivingState { IsSecondary = destinationRadio.ReceivingState.IsSecondary, IsSimultaneous = isSimultaneousTransmission, LastReceviedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = destinationRadio.ReceivingState.ReceivedOn, SentBy = transmitterName }; _radioReceivingState[audio.ReceivedRadio] = newRadioReceivingState; if (i == 0) { bool overrideEffects = false; if (_serverSettings.GetSettingAsBool(ServerSettingsKeys .RADIO_EFFECT_OVERRIDE)) { overrideEffects = _serverSettings.GlobalFrequencies.Contains(audio.Frequency); } _audioManager.AddClientAudio(audio, overrideEffects); } } //handle retransmission RetransmitAudio(udpVoicePacket, radioReceivingPriorities); } } } } } catch (Exception ex) { if (!_stop) { Logger.Info(ex, "Failed to decode audio from Packet"); } } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }