public DCSPlayerRadioInfo() { for (var i = 0; i < radios.Length; i++) { radios[i] = new RadioInformation(); } }
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); }
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); }