Example #1
0
 public DCSPlayerRadioInfo()
 {
     for (var i = 0; i < radios.Length; i++)
     {
         radios[i] = new RadioInformation();
     }
 }
Example #2
0
 public BotAudioProvider(RadioInformation receivedRadioInfo, ConcurrentQueue <byte[]> responseQueue)
 {
     LogClientId          = receivedRadioInfo.name;
     _speechAudioProvider = new BufferedWaveProvider(PcmMono16Ks16Le)
     {
         BufferDuration          = new TimeSpan(0, 1, 0),
         DiscardOnBufferOverflow = true,
         ReadFully = false
     };
     _silence = new byte[_speechAudioProvider.WaveFormat.AverageBytesPerSecond * 2];
     SpeechRecognitionListener = new SpeechRecognitionListener(_speechAudioProvider, responseQueue, receivedRadioInfo);
 }
        private List <RadioInformation> PTTPressed(out int sendingOn)
        {
            sendingOn = -1;


            var radioInfo = _clientStateSingleton.PlayerGameState;

            //If its a hot intercom and thats not the currently selected radio
            //this is special logic currently for the gazelle as it has a hot mic, but no way of knowing if you're transmitting from the module itself
            //so we have to figure out what you're transmitting on in SRS
            if (radioInfo.intercomHotMic &&
                radioInfo.control == PlayerGameState.RadioSwitchControls.IN_COCKPIT &&
                radioInfo.selected != 0 && !_ptt && !radioInfo.ptt)
            {
                if (radioInfo.radios[0].modulation == RadioInformation.Modulation.INTERCOM)
                {
                    var intercom = new List <RadioInformation>();
                    intercom.Add(radioInfo.radios[0]);
                    sendingOn = 0;
                    return(intercom);
                }
            }

            var transmittingRadios = new List <RadioInformation>();

            if (_ptt || _clientStateSingleton.PlayerGameState.ptt)
            {
                // Always add currently selected radio (if valid)
                var currentSelected = _clientStateSingleton.PlayerGameState.selected;
                RadioInformation currentlySelectedRadio = null;
                if (currentSelected >= 0 &&
                    currentSelected < _clientStateSingleton.PlayerGameState.radios.Length)
                {
                    currentlySelectedRadio = _clientStateSingleton.PlayerGameState.radios[currentSelected];

                    if (currentlySelectedRadio != null && currentlySelectedRadio.modulation !=
                        RadioInformation.Modulation.DISABLED &&
                        (currentlySelectedRadio.freq > 100 ||
                         currentlySelectedRadio.modulation ==
                         RadioInformation.Modulation.INTERCOM))
                    {
                        sendingOn = currentSelected;
                        transmittingRadios.Add(currentlySelectedRadio);
                    }
                }
            }

            return(transmittingRadios);
        }
        public static async Task LogTransmissionToDiscord(string transmission, RadioInformation radioInfo, Network.Client client)
        {
            transmission += $"\nClients on freq {radioInfo.freq / 1000000}MHz: {string.Join(", ", GetClientsOnFrequency(radioInfo, client))}\n" +
                            $"Total / Compatible / On Freq Callsigns : {GetHumanSrsClients(client).Count} / {GetBotCallsignCompatibleClients(client).Count} / {GetClientsOnFrequency(radioInfo, client).Count}\n" +
                            $"On Freq percentage of Total / Compatible: { Math.Round(GetClientsOnFrequency(radioInfo, client).Count / (double)GetHumanSrsClients(client).Count * 100, 2) }% / " +
                            $"{ Math.Round(GetClientsOnFrequency(radioInfo, client).Count / (double)GetBotCallsignCompatibleClients(client).Count * 100, 2) }%";

            if (_socket == null || _socket.ConnectionState != ConnectionState.Connected)
            {
                return;
            }
            try
            {
                using (Constants.ActivitySource.StartActivity("DiscordClient.LogToDiscord", ActivityKind.Client))
                {
                    await _socket.GetGuild(TransmissionLogDiscordGuildId)
                    .GetTextChannel(radioInfo.discordTransmissionLogChannelId).SendMessageAsync(transmission);
                }
            }
            catch (Exception e)
            {
                Logger.Error(e);
            }
        }
        // Allows OverlordBot to listen for a specific word to start listening. Currently not used although the setup has all been done.
        // This is due to wierd state transition errors that I cannot be bothered to debug. Possible benefit is less calls to Speech endpoint but
        // not sure if that is good enough or not to keep investigating.
        //private readonly KeywordRecognitionModel _wakeWord;

        public SpeechRecognitionListener(BufferedWaveProvider bufferedWaveProvider, ConcurrentQueue <byte[]> responseQueue, RadioInformation radioInfo)
        {
            radioInfo.TransmissionQueue = responseQueue;
            _botType   = radioInfo.botType;
            _frequency = radioInfo.freq;
            _callsign  = radioInfo.callsign;

            _logClientId = radioInfo.name;

            switch (radioInfo.botType)
            {
            case "ATC":
                Controller = new AtcController
                {
                    Callsign = radioInfo.callsign,
                    Voice    = radioInfo.voice,
                    Radio    = radioInfo
                };
                break;

            case "AWACS":
                Controller = new AwacsController
                {
                    Callsign = radioInfo.callsign,
                    Voice    = radioInfo.voice,
                    Radio    = radioInfo
                };
                break;

            default:
                Controller = new MuteController
                {
                    Callsign = radioInfo.callsign,
                    Voice    = null,
                    Radio    = null
                };
                break;
            }

            var encoder = OpusEncoder.Create(AudioManager.InputSampleRate, 1, Application.Voip);

            encoder.ForwardErrorCorrection = false;
            encoder.FrameByteCount(AudioManager.SegmentFrames);

            var streamReader = new BufferedWaveProviderStreamReader(bufferedWaveProvider);

            _audioConfig = AudioConfig.FromStreamInput(streamReader, AudioStreamFormat.GetWaveFormatPCM(16000, 16, 1));

            //_wakeWord = KeywordRecognitionModel.FromFile($"Overlord/WakeWords/{callsign}.table");
        }
        public void StartExternalAWACSModeLoop()
        {
            _stopExternalAWACSMode = false;

            RadioInformation[] awacsRadios;
            try
            {
                string radioJson = File.ReadAllText(AWACS_RADIOS_FILE);
                awacsRadios = JsonConvert.DeserializeObject <RadioInformation[]>(radioJson);
            }
            catch (Exception ex)
            {
                Logger.Warn(ex, "Failed to load AWACS radio file");

                awacsRadios = new RadioInformation[11];
                for (int i = 0; i < 11; i++)
                {
                    awacsRadios[i] = new RadioInformation
                    {
                        freq       = 1,
                        freqMin    = 1,
                        freqMax    = 1,
                        secFreq    = 0,
                        modulation = RadioInformation.Modulation.DISABLED,
                        name       = "No Radio",
                        freqMode   = RadioInformation.FreqMode.COCKPIT,
                        encMode    = RadioInformation.EncryptionMode.NO_ENCRYPTION,
                        volMode    = RadioInformation.VolumeMode.COCKPIT
                    };
                }
            }

            // Force an immediate update of radio information
            _clientStateSingleton.LastSent = 0;

            Task.Factory.StartNew(() =>
            {
                Logger.Debug("Starting external AWACS mode loop");

                while (!_stopExternalAWACSMode)
                {
                    _dcsRadioSyncHandler.ProcessRadioInfo(new DCSPlayerRadioInfo
                    {
                        LastUpdate = 0,
                        control    = DCSPlayerRadioInfo.RadioSwitchControls.HOTAS,
                        name       = _clientStateSingleton.LastSeenName,
                        pos        = new DcsPosition {
                            x = 0, y = 0, z = 0
                        },
                        ptt      = false,
                        radios   = awacsRadios,
                        selected = 1,
                        latLng   = new DCSLatLngPosition(),
                        simultaneousTransmission = false,
                        unit       = "External AWACS",
                        unitId     = 100000001,
                        inAircraft = false
                    });

                    Thread.Sleep(200);
                }

                Logger.Debug("Stopping external AWACS mode loop");
            });
        }
        private static List <string> GetClientsOnFrequency(RadioInformation radioInfo, Network.Client srsClient)
        {
            var clientsOnFreq = srsClient.ClientsOnFreq(radioInfo.freq, RadioInformation.Modulation.AM);

            return((from client in clientsOnFreq where client.Name != "OverlordBot" select client.Name).ToList());
        }
        private List <RadioInformation> PTTPressed(out int sendingOn)
        {
            sendingOn = -1;
            if (_clientStateSingleton.InhibitTX.InhibitTX)
            {
                TimeSpan time = new TimeSpan(DateTime.Now.Ticks - _clientStateSingleton.InhibitTX.LastReceivedAt);

                //inhibit for up to 5 seconds since the last message from VAICOM
                if (time.TotalSeconds < 5)
                {
                    return(new List <RadioInformation>());
                }
            }

            var radioInfo = _clientStateSingleton.DcsPlayerRadioInfo;

            //If its a hot intercom and thats not the currently selected radio
            //this is special logic currently for the gazelle as it has a hot mic, but no way of knowing if you're transmitting from the module itself
            //so we have to figure out what you're transmitting on in SRS
            if (radioInfo.intercomHotMic &&
                radioInfo.control == DCSPlayerRadioInfo.RadioSwitchControls.IN_COCKPIT &&
                radioInfo.selected != 0 && !_ptt && !radioInfo.ptt)
            {
                if (radioInfo.radios[0].modulation == RadioInformation.Modulation.INTERCOM)
                {
                    var intercom = new List <RadioInformation>();
                    intercom.Add(radioInfo.radios[0]);
                    sendingOn = 0;
                    return(intercom);
                }
            }

            var transmittingRadios = new List <RadioInformation>();

            if (_ptt || _clientStateSingleton.DcsPlayerRadioInfo.ptt)
            {
                // Always add currently selected radio (if valid)
                var currentSelected = _clientStateSingleton.DcsPlayerRadioInfo.selected;
                RadioInformation currentlySelectedRadio = null;
                if (currentSelected >= 0 &&
                    currentSelected < _clientStateSingleton.DcsPlayerRadioInfo.radios.Length)
                {
                    currentlySelectedRadio = _clientStateSingleton.DcsPlayerRadioInfo.radios[currentSelected];

                    if (currentlySelectedRadio != null && currentlySelectedRadio.modulation !=
                        RadioInformation.Modulation.DISABLED &&
                        (currentlySelectedRadio.freq > 100 ||
                         currentlySelectedRadio.modulation ==
                         RadioInformation.Modulation.INTERCOM))
                    {
                        sendingOn = currentSelected;
                        transmittingRadios.Add(currentlySelectedRadio);
                    }
                }

                // Add all radios toggled for simultaneous transmission if the global flag has been set
                if (_clientStateSingleton.DcsPlayerRadioInfo.simultaneousTransmission)
                {
                    var i = 0;
                    foreach (var radio in _clientStateSingleton.DcsPlayerRadioInfo.radios)
                    {
                        if (radio != null && radio.simul && radio.modulation != RadioInformation.Modulation.DISABLED &&
                            (radio.freq > 100 || radio.modulation == RadioInformation.Modulation.INTERCOM) &&
                            !transmittingRadios.Contains(radio)
                            ) // Make sure we don't add the selected radio twice
                        {
                            if (sendingOn == -1)
                            {
                                sendingOn = i;
                            }
                            transmittingRadios.Add(radio);
                        }

                        i++;
                    }
                }
            }

            return(transmittingRadios);
        }
Example #9
0
        public bool Send(byte[] bytes, int len)
        {
            //if either PTT is true, a microphone is available && socket connected etc
            if (_ready &&
                _listener != null &&
                (_ptt || _clientStateSingleton.DcsPlayerRadioInfo.ptt) &&
                _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent() &&
                _clientStateSingleton.MicrophoneAvailable &&
                (bytes != null))
            //can only send if DCS is connected
            {
                try
                {
                    // List of radios the transmission is sent to (can me multiple if simultaneous transmission is enabled)
                    List <RadioInformation> transmittingRadios = new List <RadioInformation>();

                    // Always add currently selected radio (if valid)
                    var currentSelected = _clientStateSingleton.DcsPlayerRadioInfo.selected;
                    RadioInformation currentlySelectedRadio = null;
                    if (currentSelected >= 0 &&
                        currentSelected < _clientStateSingleton.DcsPlayerRadioInfo.radios.Length)
                    {
                        currentlySelectedRadio = _clientStateSingleton.DcsPlayerRadioInfo.radios[currentSelected];

                        if (currentlySelectedRadio != null && currentlySelectedRadio.modulation !=
                            RadioInformation.Modulation.DISABLED &&
                            (currentlySelectedRadio.freq > 100 ||
                             currentlySelectedRadio.modulation ==
                             RadioInformation.Modulation.INTERCOM))
                        {
                            transmittingRadios.Add(currentlySelectedRadio);
                        }
                    }

                    // Add all radios toggled for simultaneous transmission if the global flag has been set
                    if (_clientStateSingleton.DcsPlayerRadioInfo.simultaneousTransmission)
                    {
                        foreach (var radio in _clientStateSingleton.DcsPlayerRadioInfo.radios)
                        {
                            if (radio != null && radio.simul && radio.modulation != RadioInformation.Modulation.DISABLED &&
                                (radio.freq > 100 || radio.modulation == RadioInformation.Modulation.INTERCOM) &&
                                !transmittingRadios.Contains(radio)
                                ) // Make sure we don't add the selected radio twice
                            {
                                transmittingRadios.Add(radio);
                            }
                        }
                    }

                    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++
                        };

                        var encodedUdpVoicePacket = udpVoicePacket.EncodePacket();

                        _listener.Send(encodedUdpVoicePacket, encodedUdpVoicePacket.Length, new IPEndPoint(_address, _port));

                        //not sending or really quickly switched sending
                        if (currentlySelectedRadio != null &&
                            (!RadioSendingState.IsSending || RadioSendingState.SendingOn != currentSelected))
                        {
                            _audioManager.PlaySoundEffectStartTransmit(currentSelected,
                                                                       currentlySelectedRadio.enc && (currentlySelectedRadio.encKey > 0),
                                                                       currentlySelectedRadio.volume);
                        }

                        //set radio overlay state
                        RadioSendingState = new RadioSendingState
                        {
                            IsSending  = true,
                            LastSentAt = DateTime.Now.Ticks,
                            SendingOn  = currentSelected
                        };
                        return(true);
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e, "Exception Sending Audio Message " + e.Message);
                }
            }
            else
            {
                if (RadioSendingState.IsSending)
                {
                    RadioSendingState.IsSending = false;

                    if (RadioSendingState.SendingOn >= 0)
                    {
                        var radio = _clientStateSingleton.DcsPlayerRadioInfo.radios[RadioSendingState.SendingOn];

                        _audioManager.PlaySoundEffectEndTransmit(RadioSendingState.SendingOn, radio.volume);
                    }
                }
            }

            return(false);
        }